Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a1eadfd
Manage JS frontend libraries with yarn
vmcj Oct 26, 2025
0cf9afb
Display some unrelated formula for easier testing
vmcj Sep 14, 2025
75e501a
Display clarifications when queue has been removed
vmcj Oct 30, 2025
9fe8ea1
Use our own markdown_to_html convertor
vmcj Sep 26, 2025
4d90038
Get MathJax from yarn
vmcj Oct 28, 2025
7679030
Render MathJax in clarifications
vmcj Oct 30, 2025
962a350
Handle the case with missing file for symlink
vmcj Oct 26, 2025
d7ca092
mathjaxfonts symlink seems to fail
vmcj Oct 31, 2025
70a54dd
Where does it fial
vmcj Oct 31, 2025
8c66ba3
Show the right error
vmcj Oct 31, 2025
6361298
Try to fail in CI again
vmcj Oct 31, 2025
40cd21c
Let more people use Fedora for development
vmcj Oct 31, 2025
fedd005
Debug further
vmcj Oct 31, 2025
33607b0
Update webapp/templates/jury/clarification.html.twig
vmcj Oct 31, 2025
a35cf13
Update webapp/src/Twig/TwigExtension.php
vmcj Oct 31, 2025
3e72b94
Update webapp/src/Twig/TwigExtension.php
vmcj Oct 31, 2025
0921a04
Update webapp/src/Twig/TwigExtension.php
vmcj Oct 31, 2025
bb6caa6
Merge branch 'main' into mathjax
vmcj Oct 31, 2025
d036557
Add realpath checks for public directories
vmcj Oct 31, 2025
cf52598
Add pwd command for debugging in baseinstall.sh
vmcj Nov 1, 2025
8291d73
Enhance debugging for JS frontend dependencies
vmcj Nov 1, 2025
10433e1
Update Makefile
vmcj Nov 1, 2025
6232e6e
Update baseinstall.sh
vmcj Nov 1, 2025
df76750
Update baseinstall.sh
vmcj Nov 1, 2025
f9b2e2f
Update codeql-analysis.yml
vmcj Nov 1, 2025
a25851d
Update codeql-analysis.yml
vmcj Nov 1, 2025
4cc9133
Update codeql-analysis.yml
vmcj Nov 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/jobs/baseinstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ composer install --no-scripts |tee "$ARTIFACTS"/composer_out.txt
cd ..
section_end

section_start "Install JS frontend dependencies"
cd webapp
apt-get update; apt-get install -y yarnpkg
yarnpkg install
cd ..
section_end

section_start "Set simple admin password"
echo "password" > ./etc/initial_admin_password.secret
echo "default login admin password password" > ~/.netrc
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ jobs:
with:
languages: ${{ matrix.language }}

- name: Install yarn files
if: ${{ contains(env.COMPILED, matrix.language) }}
run: |
cd webapp
sudo apt-get update; sudo apt-get install yarnpkg -y
sudo yarnpkg install

- name: Install composer files
if: ${{ contains(env.COMPILED, matrix.language) }}
run: |
Expand Down
4 changes: 2 additions & 2 deletions doc/manual/develop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ already listed under

sudo apt install autoconf automake bats \
python3-sphinx python3-sphinx-rtd-theme fontconfig python3-yaml \
latexmk texlive-latex-recommended texlive-latex-extra tex-gyre
latexmk yarnpkg texlive-latex-recommended texlive-latex-extra tex-gyre

For Fedora use::

sudo dnf install git autoconf automake bats \
sphinx-build python3-sphinx_rtd_theme latexmk texlive-cmap \
sphinx-build python3-sphinx_rtd_theme latexmk yarnpkg texlive-cmap \
texlive-metafont texlive-tex-gyre texlive-fncychap texlive-wrapfig \
texlive-capt-of texlive-framed texlive-upquote texlive-needspace \
texlive-tabulary texlive-parskip texlive-oberdiek texlive-makeindex \
Expand Down
1 change: 1 addition & 0 deletions webapp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
/var/log/*
!var/log/.gitkeep
/vendor/
/node_modules/

###> phpunit/phpunit ###
/phpunit.xml
Expand Down
13 changes: 10 additions & 3 deletions webapp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ SUBDIRS = config
domserver: composer-dump-autoload

# Install PHP dependencies
composer-dependencies:
composer-dependencies: node-dependencies
ifeq (, $(shell command -v composer 2> /dev/null))
$(error "'composer' command not found in $(PATH), install it via your package manager or https://getcomposer.org/download/")
endif
# We use --no-scripts here because at this point the autoload.php file is
# not generated yet, which is needed to run the post-install scripts.
composer $(subst 1,-q,$(QUIET)) install --prefer-dist -o -a --no-scripts --no-plugins

composer-dependencies-dev:
composer-dependencies-dev: node-dependencies
composer $(subst 1,-q,$(QUIET)) install --prefer-dist --no-scripts --no-plugins

# Dump autoload dependencies (including plugins)
Expand All @@ -36,6 +36,13 @@ vendor/autoload_runtime.php:
composer-dump-autoload-dev:
composer $(subst 1,-q,$(QUIET)) dump-autoload

node-dependencies:
ifeq (, $(shell command -v yarn || command -v yarnpkg 2> /dev/null))
$(error "neither 'yarnpkg' nor 'yarn' command found in $(PATH), install it via your package manager or https://yarnpkg.com/cli/node")
endif
@YARN_CMD=$(shell command -v yarn || command -v yarnpkg); \
$$YARN_CMD install

# Run Symfony in dev mode (for maintainer-mode):
.env.local:
@echo "Creating file '$@'..."
Expand All @@ -58,7 +65,7 @@ install-domserver:
# This must be done first to install with the rest.
$(MAKE) copy-bundle-assets
$(INSTALL_DIR) $(DESTDIR)$(domserver_webappdir);
for d in bin config migrations public resources src templates tests vendor; do \
for d in bin config migrations public resources src templates tests vendor node_modules; do \
$(call install_tree,$(DESTDIR)$(domserver_webappdir),$$d) ; \
done
# Add Symlink to Symfony console that is in the standard path
Expand Down
5 changes: 5 additions & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"mathjax": "^4.0.0"
}
}
1 change: 1 addition & 0 deletions webapp/public/js/domjudge.js
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,7 @@ function previewClarification($input, $previewDiv) {
}
}).done(function (data) {
$previewDiv.html(data.html);
MathJax.typesetPromise([document.getElementById($previewDiv[0].id)]);
});
}
}
Expand Down
1 change: 1 addition & 0 deletions webapp/public/js/tex-chtml.js
1 change: 1 addition & 0 deletions webapp/public/mathjax
1 change: 1 addition & 0 deletions webapp/public/mathjaxfonts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __invoke(ResponseEvent $event): void
// the profiler requires 'unsafe-eval' for script-src 'self'.
$response = $event->getResponse();
$cspExtra = $this->profiler ? "'unsafe-eval'" : "";
$csp = "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' $cspExtra; img-src 'self' data:; worker-src 'self' blob:";
$csp = "font-src 'self' data:; default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' $cspExtra; img-src 'self' data:; worker-src 'self' blob:";
$response->headers->set('Content-Security-Policy', $csp);
}
}
13 changes: 13 additions & 0 deletions webapp/src/Service/DOMJudgeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
Expand All @@ -67,6 +68,9 @@
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use ZipArchive;

class DOMJudgeService
Expand Down Expand Up @@ -1512,6 +1516,12 @@ public function getCompileConfig(Submission $submission): string
);
}

/**
* @throws SyntaxError
* @throws ReflectionException
* @throws RuntimeError
* @throws LoaderError
*/
public function getScoreboardZip(
Request $request,
RequestStack $requestStack,
Expand Down Expand Up @@ -1568,6 +1578,9 @@ public function getScoreboardZip(
$publicPath = realpath(sprintf('%s/public/', $this->projectDir));
foreach ($assetMatches[1] as $file) {
$filepath = realpath($publicPath . '/' . $file);
if ($filepath === false) {
throw new Exception("Could not find (symlinked) file: " . $file . " and " . $publicPath);
}
if (!str_starts_with($filepath, $publicPath) &&
!str_starts_with($filepath, $this->vendorDir)
) {
Expand Down
33 changes: 33 additions & 0 deletions webapp/src/Twig/TwigExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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('domjudge_markdown_to_html', $this->domjudgeMarkdownToHTML(...), ['is_safe' => ['html']]),
];
}

Expand Down Expand Up @@ -1406,4 +1408,35 @@ public function extensionToMime(string $extension): string
{
return DOMJudgeService::EXTENSION_TO_MIMETYPE[$extension];
}

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;
}
}
1 change: 1 addition & 0 deletions webapp/templates/base.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<script src="{{ asset("js/jquery.min.js") }}"></script>
<script src="{{ asset("js/jquery.debounce.min.js") }}"></script>
<script src="{{ asset("js/bootstrap.bundle.min.js") }}"></script>
{% include 'partials/mathjaxhead.html.twig' %}

<script src="{{ asset("js/domjudge.js") }}"></script>
{% for file in customAssetFiles('js') %}
Expand Down
7 changes: 7 additions & 0 deletions webapp/templates/jury/clarification.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
{% endif %}

{% for clar in list %}
<div style="height: 100px;"></div>
<div>Pure body:<br>{{ clar.body }}</div>
<div>Markdown converted:<br>{{ clar.body | markdown_to_html }}</div>
<div>DOMjudge Markdown converted:<br>{{ clar.body | domjudge_markdown_to_html }}</div>
<div>Sanitized:<br>{{ clar.body | sanitize_html('app.clarification_sanitizer') }}</div>
<div>All:<br>{{ clar.body | domjudge_markdown_to_html | sanitize_html('app.clarification_sanitizer') }}</div>
<div>DOMjudge all:<br>{{ clar.body | domjudge_markdown_to_html | sanitize_html('app.clarification_sanitizer') }}</div>
<div class="card mb-3 {% if clar.from_team is not defined %}border-primary{% endif %}">
<div class="card-header">
<div class="row">
Expand Down
6 changes: 5 additions & 1 deletion webapp/templates/jury/export/clarifications.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@
<div class="page-break"></div>
<h1>{{ title }}</h1>
{% endif %}
<h2>{{ queues[queue] }}</h2>
{% if queues[queue] is defined %}
<h2>{{ queues[queue] }}</h2>
{% else %}
<h2><i>Unknown queue: {{ queue }}</h2>
{% endif %}
<table class="table">
<thead>
<tr>
Expand Down
1 change: 1 addition & 0 deletions webapp/templates/jury/export/layout.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
color: darkgrey;
}
</style>
{% include 'partials/mathjaxhead.html.twig' %}
</head>
<body>
<main role="main" class="">
Expand Down
2 changes: 2 additions & 0 deletions webapp/templates/jury/menu.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

{% set current_route = app.request.attributes.get('_route') %}

<span>Euler's identity: $( e^{i\pi} + 1 = 0 )$</span>
<span>$$\vec{a} \times \vec{b} = \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ a_x & a_y & a_z \\ b_x & b_y & b_z \end{vmatrix}$$</span>
<div class="collapse navbar-collapse" id="menuDefault" data-update-url="{{ path('jury_ajax_updates') }}">
<ul class="navbar-nav me-auto">

Expand Down
18 changes: 18 additions & 0 deletions webapp/templates/partials/mathjaxhead.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
window.MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']]
},
chtml: {
fontURL: "{{ app.request.basePath }}/mathjaxfonts",
scale: 1.0
},
loader: {
paths: {
mathjax: "{{ app.request.basePath }}/mathjax"
},
load: ['input/tex', 'output/chtml']
}
};
</script>
<script src="{{ app.request.basePath }}/mathjax/tex-chtml.js"></script>
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@
{{ form_end(form) }}
</div>
</div>

<script>
MathJax.typeset([document.getElementsByClassName('card-body')]);
</script>
5 changes: 4 additions & 1 deletion webapp/templates/team/partials/clarification_list.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@
</td>
{% endif %}

<td>
<td class="clarification-text">
<a data-ajax-modal data-ajax-modal-after="markSeen" href="{{ link }}">
{{ clarification.summary | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}
</a>
<script>
MathJax.typeset([document.getElementsByClassName('card-body')]);
</script>
</td>
</tr>
{%- endfor %}
Expand Down
15 changes: 15 additions & 0 deletions webapp/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@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==

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"
Loading