|
1 | 1 | <script lang="ts">
|
2 | 2 | import hljs from 'highlight.js';
|
| 3 | + import katex from 'katex'; |
| 4 | + import texmath from 'markdown-it-texmath'; |
3 | 5 | import MarkdownIt from 'markdown-it/lib/index.mjs';
|
4 | 6 | import { mount, onMount } from 'svelte';
|
5 | 7 |
|
6 | 8 | import 'highlight.js/styles/github.min.css';
|
| 9 | + import 'katex/dist/katex.min.css'; |
7 | 10 |
|
8 | 11 | import ButtonCopy from './ButtonCopy.svelte';
|
9 | 12 |
|
10 | 13 | export let markdown: string;
|
11 | 14 | const CODE_SNIPPET_ID = 'code-snippet';
|
12 | 15 |
|
| 16 | + function normalizeMarkdown(content: string) { |
| 17 | + // Replace multiple newlines with double newlines |
| 18 | + content = content.replace(/\n{2,}/g, '\n\n'); |
| 19 | +
|
| 20 | + // First, normalize display math blocks |
| 21 | + content = content.replace(/\n\\\[/g, '\n\n\\['); |
| 22 | + content = content.replace(/\\]\n/g, '\\]\n\n'); |
| 23 | +
|
| 24 | + // Split on all math delimiters: \[...\], \(...\), and $...$ |
| 25 | + // Using [\s\S] instead of . to match across lines |
| 26 | + const parts = content.split(/(\$[^$]+\$|\\[([^)]+\\]|\\[\s\S]+?\\])/g); |
| 27 | + content = parts |
| 28 | + .map((part) => { |
| 29 | + // If this part is any kind of math block, leave it unchanged |
| 30 | + if (part.startsWith('$') || part.startsWith('\\[') || part.startsWith('\\(')) { |
| 31 | + return part; |
| 32 | + } |
| 33 | + // Otherwise, wrap any \boxed commands in inline math |
| 34 | + return part.replace(/\\boxed\{((?:[^{}]|\{[^{}]*\})*)\}/g, '\\(\\boxed{$1}\\)'); |
| 35 | + }) |
| 36 | + .join(''); |
| 37 | +
|
| 38 | + return content; |
| 39 | + } |
| 40 | +
|
13 | 41 | function renderCodeSnippet(code: string) {
|
14 | 42 | return `<pre id="${CODE_SNIPPET_ID}"><code class="hljs">${code}</code></pre>`;
|
15 | 43 | }
|
|
30 | 58 | }
|
31 | 59 | });
|
32 | 60 |
|
| 61 | + // Math notation parsing with Katex, with multiple delimiters |
| 62 | + md.use(texmath, { |
| 63 | + engine: katex, |
| 64 | + delimiters: ['dollars', 'brackets', 'doxygen', 'gitlab', 'julia', 'kramdown', 'beg_end'] |
| 65 | + }); |
| 66 | +
|
33 | 67 | onMount(() => {
|
34 | 68 | const preElements = document.querySelectorAll(`pre#${CODE_SNIPPET_ID}`);
|
35 | 69 |
|
|
50 | 84 | getting formatted on auto-formatting.
|
51 | 85 | -->
|
52 | 86 | {#if markdown}
|
53 |
| - {@html md.render(markdown)} <!-- eslint-disable-line svelte/no-at-html-tags --> |
| 87 | + <!-- eslint-disable-next-line svelte/no-at-html-tags --> |
| 88 | + {@html md.render(normalizeMarkdown(markdown))} |
54 | 89 | {/if}
|
55 | 90 | </div>
|
56 | 91 |
|
|
0 commit comments