Skip to content

Commit c2e281a

Browse files
committed
Use our own markdown_to_html convertor
Which stashes LaTeX during conversion and pops it afterwards. Otherwise things like `\\` get replaced with `\` which failed with: DOMjudge#3099 (comment)
1 parent e90e39c commit c2e281a

File tree

7 files changed

+43
-7
lines changed

7 files changed

+43
-7
lines changed

webapp/src/Twig/TwigExtension.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use App\Utils\Utils;
2828
use Doctrine\Common\Collections\Collection;
2929
use Doctrine\ORM\EntityManagerInterface;
30+
use Ramsey\Uuid\Uuid;
3031
use Symfony\Component\DependencyInjection\Attribute\Autowire;
3132
use Symfony\Component\Intl\Countries;
3233
use Symfony\Component\Intl\Exception\MissingResourceException;
@@ -38,12 +39,15 @@
3839
use Twig\Environment;
3940
use Twig\Extension\AbstractExtension;
4041
use Twig\Extension\GlobalsInterface;
42+
use Twig\Extra\Markdown\MarkdownRuntime;
4143
use Twig\Runtime\EscaperRuntime;
4244
use Twig\TwigFilter;
4345
use Twig\TwigFunction;
4446

4547
class TwigExtension extends AbstractExtension implements GlobalsInterface
4648
{
49+
private array $latexFound;
50+
4751
/**
4852
* @param array<int, bool> $renderedSources
4953
*/
@@ -126,6 +130,7 @@ public function getFilters(): array
126130
new TwigFilter('medalType', $this->awards->medalType(...)),
127131
new TwigFilter('numTableActions', $this->numTableActions(...)),
128132
new TwigFilter('extensionToMime', $this->extensionToMime(...)),
133+
new TwigFilter('domjudgeMarkdownToHtml', $this->domjudgeMarkdownToHTML(...), ['is_safe' => ['html']]),
129134
];
130135
}
131136

@@ -1381,4 +1386,35 @@ public function extensionToMime(string $extension): string
13811386
{
13821387
return DOMJudgeService::EXTENSION_TO_MIMETYPE[$extension];
13831388
}
1389+
1390+
/**
1391+
* Extract all LaTeX code from the given string, sanitize the markdown and
1392+
* inject the original LaTeX code back so MathJax can render it.
1393+
*/
1394+
public function domjudgeMarkdownToHTML(string $markdown): string
1395+
{
1396+
$latexPlaceholder = Uuid::uuid4()->toString();
1397+
while(str_contains($markdown, $latexPlaceholder)) {
1398+
$latexPlaceholder = Uuid::uuid4()->toString();
1399+
}
1400+
1401+
$markdown = preg_replace_callback(
1402+
'/(\$[\s\S]*?\$)/',
1403+
function (array $matches) use ($latexPlaceholder) {
1404+
// Store and replace matches
1405+
$this->latexFound[] = $matches[1];
1406+
return $latexPlaceholder;
1407+
},
1408+
$markdown
1409+
);
1410+
1411+
/** @var MarkdownRuntime $runtime */
1412+
$runtime = $this->twig->getRuntime(MarkdownRuntime::class);
1413+
$markdown = (string)$runtime->convert($markdown);
1414+
1415+
return preg_replace_callback(
1416+
'/'.$latexPlaceholder.'/',
1417+
fn() => array_shift($this->latexFound), $markdown
1418+
);
1419+
}
13841420
}

webapp/templates/jury/clarification.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110

111111
<hr/>
112112

113-
<div class="card-text">{{ clar.body | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}</div>
113+
<div class="card-text">{{ clar.body | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }}</div>
114114

115115
</div>
116116
</div>

webapp/templates/jury/config.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@
218218
{{ errors[option.name] }}
219219
</div>
220220
{% endif %}
221-
<div class="small text-muted">{{ option.description | markdown_to_html }}</div>
221+
<div class="small text-muted">{{ option.description | domjudgeMarkdownToHtml }}</div>
222222
</div>
223223
</li>
224224
{% endfor %}

webapp/templates/jury/config_check.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
{% if testresult.escape is not defined or testresult.escape %}
100100
{% set description = description | escape %}
101101
{% endif %}
102-
{{ description | markdown_to_html }}
102+
{{ description | domjudgeMarkdownToHtml }}
103103
</div>
104104
</div>
105105
</div>

webapp/templates/jury/export/clarifications.html.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
<tr>
9999
<td><b>Content</b></td>
100100
<td colspan="5">
101-
<div class="card-text">{{ clarification.body | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}</div>
101+
<div class="card-text">{{ clarification.body | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }}</div>
102102
</td>
103103
</tr>
104104
{% if clarification.replies is not empty %}
@@ -114,7 +114,7 @@
114114
</b>
115115
</td>
116116
<td colspan="5">
117-
<div class="card-text">{{ reply.body | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}</div>
117+
<div class="card-text">{{ reply.body | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }}</div>
118118
</td>
119119
</tr>
120120
{% endfor %}

webapp/templates/team/partials/clarification.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<hr/>
4141

4242
<div class="card-text">
43-
{{ clarification.body | markdown_to_html | sanitize_html('app.clarification_sanitizer') }}
43+
{{ clarification.body | domjudgeMarkdownToHtml | sanitize_html('app.clarification_sanitizer') }}
4444
</div>
4545
</div>
4646
</div>

webapp/templates/team/partials/clarification_list.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
<td class="clarification-text">
5252
<a data-ajax-modal data-ajax-modal-after="markSeen" href="{{ link }}">
5353
<i>{{ clarification.summary
54-
| markdown_to_html
54+
| domjudgeMarkdownToHtml
5555
| replace({'<p>': '', '</p>': ''})
5656
| sanitize_html('app.clarification_sanitizer')
5757
| raw

0 commit comments

Comments
 (0)