diff --git a/.github/jobs/baseinstall.sh b/.github/jobs/baseinstall.sh index 40d1ab2103..719f065608 100755 --- a/.github/jobs/baseinstall.sh +++ b/.github/jobs/baseinstall.sh @@ -30,7 +30,6 @@ section_end section_start "Install JS frontend dependencies" cd webapp -apt-get update; apt-get install -y yarnpkg yarnpkg install cd .. section_end diff --git a/webapp/package.json b/webapp/package.json index c97d546996..4219d31cbb 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -11,6 +11,7 @@ "file-saver": "^2.0.5", "flag-icons": "^7.5.0", "jquery-debounce-throttle": "^1.0.6-rc.0", + "mathjax": "^4.0.0", "monaco-editor": "^0.54.0", "nvd3": "1.8.6", "select2": "^4.0.13", diff --git a/webapp/public/js/domjudge.js b/webapp/public/js/domjudge.js index 371ae20e92..fdb21bb8be 100644 --- a/webapp/public/js/domjudge.js +++ b/webapp/public/js/domjudge.js @@ -939,6 +939,7 @@ function previewClarification($input, $previewDiv) { } }).done(function (data) { $previewDiv.html(data.html); + MathJax.typesetPromise([document.getElementById($previewDiv[0].id)]); }); } } diff --git a/webapp/public/js/tex-chtml.js b/webapp/public/js/tex-chtml.js new file mode 120000 index 0000000000..47467ad03c --- /dev/null +++ b/webapp/public/js/tex-chtml.js @@ -0,0 +1 @@ +../../node_modules/mathjax/tex-chtml.js \ No newline at end of file diff --git a/webapp/public/mathjax b/webapp/public/mathjax new file mode 120000 index 0000000000..3a045cb444 --- /dev/null +++ b/webapp/public/mathjax @@ -0,0 +1 @@ +../node_modules/mathjax \ No newline at end of file diff --git a/webapp/public/mathjaxfonts b/webapp/public/mathjaxfonts new file mode 120000 index 0000000000..89fd736689 --- /dev/null +++ b/webapp/public/mathjaxfonts @@ -0,0 +1 @@ +../node_modules/@mathjax/mathjax-newcm-font/chtml/woff2 \ No newline at end of file diff --git a/webapp/src/Twig/TwigExtension.php b/webapp/src/Twig/TwigExtension.php index 60df1de6cc..df51044e3b 100644 --- a/webapp/src/Twig/TwigExtension.php +++ b/webapp/src/Twig/TwigExtension.php @@ -37,6 +37,7 @@ use Twig\Environment; use Twig\Extension\AbstractExtension; use Twig\Extension\GlobalsInterface; +use Twig\Extra\Markdown\MarkdownRuntime; use Twig\Runtime\EscaperRuntime; use Twig\TwigFilter; use Twig\TwigFunction; @@ -124,6 +125,7 @@ public function getFilters(): array new TwigFilter('medalType', $this->awards->medalType(...)), new TwigFilter('numTableActions', $this->numTableActions(...)), new TwigFilter('extensionToMime', $this->extensionToMime(...)), + new TwigFilter('domjudgeMarkdownToHtml', $this->domjudgeMarkdownToHTML(...), ['is_safe' => ['html']]), ]; } @@ -1406,4 +1408,39 @@ public function extensionToMime(string $extension): string { return DOMJudgeService::EXTENSION_TO_MIMETYPE[$extension]; } + + /** + * Extract all LaTeX code from the given string, sanitize the markdown and + * inject the original LaTeX code back so MathJax can render it. + */ + public function domjudgeMarkdownToHTML(string $markdown): string + { + $latexFound = []; + while (true) { + $start = strpos($markdown, '$$'); + $end = strpos(substr($markdown, $start+2), '$$'); + if ($start === false || $end === false) { + break; + } + $latexFound[] = substr($markdown, $start, $end+2+2); + $newMarkdown = substr($markdown, 0, $start); + $newMarkdown .= '$LaTeX$'; + $newMarkdown .= substr($markdown, $end+$start+4); + $markdown = $newMarkdown; + } + + /** @var MarkdownRuntime $runtime */ + $runtime = $this->twig->getRuntime(MarkdownRuntime::class); + $markdown = (string)$runtime->convert($markdown); + + $new = ''; + foreach ($latexFound as $inlineLatex) { + $replacedStart = strpos($markdown, '$LaTeX$'); + $new = substr($markdown, 0, $replacedStart); + $new .= $inlineLatex; + $new .= substr($markdown, $replacedStart+strlen('$LaTeX$')); + $markdown = $new; + } + return $markdown; + } } diff --git a/webapp/templates/base.html.twig b/webapp/templates/base.html.twig index e953356b67..ecf48113bc 100644 --- a/webapp/templates/base.html.twig +++ b/webapp/templates/base.html.twig @@ -13,6 +13,7 @@ + {% include 'partials/mathjaxhead.html.twig' %} {% for file in customAssetFiles('js') %} diff --git a/webapp/templates/jury/clarification.html.twig b/webapp/templates/jury/clarification.html.twig index e7e7c4d24b..70e79957ed 100644 --- a/webapp/templates/jury/clarification.html.twig +++ b/webapp/templates/jury/clarification.html.twig @@ -110,7 +110,7 @@
| Content |
- {{ clarification.body | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}
+ {{ clarification.body | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }}
|
- {{ reply.body | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}
+ {{ reply.body | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }}
|
{% endfor %}
diff --git a/webapp/templates/jury/export/layout.html.twig b/webapp/templates/jury/export/layout.html.twig
index 4e465a2aab..39d6ae36a3 100644
--- a/webapp/templates/jury/export/layout.html.twig
+++ b/webapp/templates/jury/export/layout.html.twig
@@ -108,6 +108,7 @@
color: darkgrey;
}
+ {% include 'partials/mathjaxhead.html.twig' %}
+ | - {{ clarification.summary | markdown_to_html | sanitize_html('app.clarification_sanitizer') }} + {{ clarification.summary | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }} + | {%- endfor %} diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 1a9e6f48e5..dc7a2a29ad 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-7.1.0.tgz#8eb76278515341720aa74485266f8be121089529" integrity sha512-+WxNld5ZCJHvPQCr/GnzCTVREyStrAJjisUPtUxG5ngDA8TMlPnKp6dddlTpai4+1GNmltAeuk1hJEkBohwZYA== +"@mathjax/mathjax-newcm-font@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@mathjax/mathjax-newcm-font/-/mathjax-newcm-font-4.0.0.tgz#01afa8b20f2114665dc1d9a7fbc623a23ddb54e4" + integrity sha512-kpsJgIF4FpWiwIkFgOPmWwy5GXfL25spmJJNg27HQxPddmEL8Blx0jn2BuU/nlwjM/9SnYpEfDrWiAMgLPlB8Q== + "@melloware/coloris@^0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@melloware/coloris/-/coloris-0.25.0.tgz#7012c10dc510dca1660b3692ed3c812344aec6ca" @@ -79,6 +84,13 @@ marked@14.0.0: resolved "https://registry.yarnpkg.com/marked/-/marked-14.0.0.tgz#79a1477358a59e0660276f8fec76de2c33f35d83" integrity sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ== +mathjax@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-4.0.0.tgz#ff7aa8b6bfdc7e97e41091a9ed6d8c8f8eefd2a0" + integrity sha512-ThMPHiPl9ibZBInAmfoTCNq9MgCdH7ChIQ9YhKFc325noJ4DMzy9/Q14qdcuPzVJjEmC3kyXhwnERZWX3hbWzQ== + dependencies: + "@mathjax/mathjax-newcm-font" "^4.0.0" + monaco-editor@^0.54.0: version "0.54.0" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.54.0.tgz#c0d6ebb46b83f1bef6f67f6aa471e38ba7ef8231"|