MDL-75963 filter: Added code highlighter filter

If enabled, the filter will convert text wrapped by language-* style class
into a well-styled block of code.
The filter uses PrismJS, and it also used by the TinyMCE editor to
highlight the code sample plugin.
This commit is contained in:
Meirza 2023-05-11 23:05:00 +07:00 committed by meirzamoodle
parent 5d320dd7d1
commit 6772c9b8e8
15 changed files with 3553 additions and 1 deletions

View File

@ -0,0 +1,10 @@
/**
* Prism.js initialization.
*
* @module filter/codegihlighter
* @copyright 2023 Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("filter_codehighlighter/prism-init",["./prism"],(function(PrismJS){PrismJS.highlightAll()}));
//# sourceMappingURL=prism-init.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"prism-init.min.js","sources":["../src/prism-init.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Prism.js initialization.\n *\n * @module filter/codegihlighter\n * @copyright 2023 Meirza <meirza.arson@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['./prism'], function(PrismJS) {\n PrismJS.highlightAll();\n});\n"],"names":["define","PrismJS","highlightAll"],"mappings":";;;;;;;AAsBAA,2CAAO,CAAC,YAAY,SAASC,SACzBA,QAAQC"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,25 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Prism.js initialization.
*
* @module filter/codegihlighter
* @copyright 2023 Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['./prism'], function(PrismJS) {
PrismJS.highlightAll();
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace filter_codehighlighter\privacy;
/**
* Privacy Subsystem for filter_codehighlighter implementing null_provider.
*
* @package filter_codehighlighter
* @copyright 2023 Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() : string {
return 'privacy:metadata';
}
}

View File

@ -0,0 +1,52 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Code highlighter filter.
*
* Filter converting text code into a well-styled block of code.
*
* @package filter_codehighlighter
* @copyright 2023 Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class filter_codehighlighter extends moodle_text_filter {
/**
* Apply the filter to the text
*
* @param string $text to be processed by the text
* @param array $options filter options
* @return string text after processing
*/
public function filter($text, array $options = []): string {
global $PAGE;
if (!isset($options['originalformat'])) {
return $text;
}
// The pattern.
$re = '/<pre.+?class=".*?language-.*?"><code>/i';
// Stops looking after the first match.
preg_match($re, $text, $matches);
if ($matches) {
$PAGE->requires->js_call_amd('filter_codehighlighter/prism-init');
}
return $text;
}
}

View File

@ -0,0 +1,28 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for filter_codehighlighter
*
* @package filter_codehighlighter
* @copyright 2023 Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['filtername'] = 'Code highlighter';
$string['privacy:metadata'] = 'The code highlighter plugin does not store any personal data.';

View File

@ -0,0 +1,70 @@
Description of Code Highlighter Filter in Moodle
====================================================
Code highlighter uses PrismJS.
Why PrismJS?
---------------------------------------------------
One of the editors in Moodle is TinyMCE, and the Code Sample plugin makes use of PrismJS.
Hence, the code-highlighter filter likewise uses PrismJS to get the same behavior and look.
As a result, when we need to upgrade the PrismJS version in this filter,
We must take into account the PrismJS version that TinyMCE is currently using.
Upgrading steps:
---------------------------------------------------
Prerequisite: Make sure the grunt watcher is running during the below process:
1. In yourmoodle directory, run "npm install && grunt watch -f".
It will generate minified js files automatically if there is a change in all JS files in the amd folder.
2. Download PrismJS
See the lib/editor/tiny/thirdpartylibs.xml to get the current TinyMCE version (X.Y.Z).
Download the ZIP file at https://github.com/tinymce/tinymce/tree/X.Y.Z and extract the ZIP file.
For instance, if TinyMCE version is 6.3.2, the file to download should be https://github.com/tinymce/tinymce/tree/6.3.2.
3. In the extracted folder, run "yarn".
4. Copy the node_modules/prismjs/themes/prism.css to yourmoodle/filter/codehighlighter/styles.css
5. Edit the styles.css to make sure the indentation is made using spaces, not tabs, and remove trailing spaces.
6. To avoid conflict with the theme code tag style.
Remove all the lines that contain 'code[class*="language-"]' text in the styles.css,
and also remove the comma character after the text if necessary to make sure that the CSS structure is correct.
Please see the examples below:
* code[class*="language-"],
* :not(pre) > code[class*="language-"],
* code[class*="language-"]::-moz-selection,
* code[class*="language-"] ::-moz-selection
* code[class*="language-"]::selection,
* code[class*="language-"] ::selection
* code[class*="language-"]
7. See if the grunt watch is reporting problems. If yes, follow the instructions to fix it. e.g:
Before:
```
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection {
pre[class*="language-"]::selection, pre[class*="language-"] ::selection {
```
After:
```
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection {
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection {
```
And remove the warning from color-hex-case by renaming "#DD4A68" to lowercase "#dd4a68".
8. In the extracted folder, run "./bin/build-prism.js"
9. Copy the node_modules/prismjs/prism.js to yourmoodle/filter/codehighlighter/amd/src/prism.js
10. Edit the prism.js to make sure the indentation is made using spaces, not tabs, and remove trailing spaces.
Note: As long as the grunt watcher says Done, then the upgrade process is complete.

View File

@ -0,0 +1,130 @@
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
pre[class*="language-"] {
background: #f5f2f0;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
/* This background color was intended by the author of this theme. */
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #dd4a68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,22 @@
@editor @editor_tiny @filter @filter_codehighlighter
Feature: Render text content using a codehighliter filter
To display code to be well-styled - I need to render text content.
@javascript
Scenario: Update admin profile description with a code content
Given the "codehighlighter" filter is "on"
And I log in as "admin"
And I follow "Profile" in the user menu
When I click on "Edit profile" "link" in the "region-main" "region"
And I click on "//span[@class='tox-mbtn__select-label'][contains(text(), 'Insert')]" "xpath_element"
And I click on "//div[@class='tox-collection__item-label'][contains(text(), 'Code sample...')]" "xpath_element"
And I set the field with xpath "//div[@class='tox-selectfield']/select" to "PHP"
And I set the field with xpath "//textarea" to "<pre class=\"language-php\"><code>$t = date();</code></pre>"
And I click on "//button[@class='tox-button'][contains(text(), 'Save')]" "xpath_element"
And I click on "Update profile" "button"
Then I should see "Changes saved"
And "//span[@class='token variable'][contains(text(),'$t')]" "xpath_element" should exist
And "//span[@class='token operator'][contains(text(),'=')]" "xpath_element" should exist
And "//span[@class='token punctuation'][contains(text(),'(')]" "xpath_element" should exist
And "//span[@class='token punctuation'][contains(text(),')')]" "xpath_element" should exist
And "//span[@class='token punctuation'][contains(text(),';')]" "xpath_element" should exist

View File

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<libraries>
<library>
<location>amd/src/prism.js</location>
<name>PrismJS</name>
<description>Prism is a lightweight, robust, and elegant syntax highlighting library. It's a spin-off project from Dabblet.</description>
<version>1.16.0</version>
<license>MIT</license>
<repository>https://github.com/PrismJS/prism</repository>
<copyrights>
<copyright>2012 Lea Verou</copyright>
</copyrights>
</library>
</libraries>

View File

@ -0,0 +1,29 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version information
*
* @package filter_codehighlighter
* @copyright 2023 Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2023031400; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2023031000; // Requires this Moodle version.
$plugin->component = 'filter_codehighlighter'; // Full name of the plugin (used for diagnostics).

View File

@ -1870,7 +1870,7 @@ class core_plugin_manager {
'filter' => array(
'activitynames', 'algebra', 'emailprotect',
'emoticon', 'displayh5p', 'mathjaxloader', 'mediaplugin', 'multilang', 'tex', 'tidy',
'urltolink', 'data', 'glossary'
'urltolink', 'data', 'glossary', 'codehighlighter'
),
'format' => array(