File size: 1,438 Bytes
96dd062
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import katex from "katex";
import { marked } from "marked";

marked.setOptions({
	breaks: true,
	gfm: true,
});

function renderInlineMath(expression: string) {
	try {
		return katex.renderToString(expression, {
			displayMode: false,
			throwOnError: false,
		});
	} catch {
		return expression;
	}
}

function renderBlockMath(expression: string) {
	try {
		return `<div class="admin-katex-block">${katex.renderToString(expression, {
			displayMode: true,
			throwOnError: false,
		})}</div>`;
	} catch {
		return expression;
	}
}

function replaceMathSegments(markdown: string) {
	const codeTokens: string[] = [];
	const codeTokenPattern = /```[\s\S]*?```|`[^`\n]+`/g;

	let prepared = markdown.replace(codeTokenPattern, (match) => {
		const token = `@@ADMIN_CODE_TOKEN_${codeTokens.length}@@`;
		codeTokens.push(match);
		return token;
	});

	prepared = prepared.replace(/\$\$([\s\S]+?)\$\$/g, (_, expression: string) =>
		renderBlockMath(expression.trim()),
	);

	prepared = prepared.replace(
		/(^|[^\$\\])\$([^\n$]+?)\$/g,
		(_, prefix: string, expression: string) =>
			`${prefix}${renderInlineMath(expression.trim())}`,
	);

	return prepared.replace(/@@ADMIN_CODE_TOKEN_(\d+)@@/g, (_, index: string) => {
		const tokenIndex = Number.parseInt(index, 10);
		return codeTokens[tokenIndex] ?? "";
	});
}

export function renderMarkdownPreview(markdown: string) {
	return marked.parse(replaceMathSegments(markdown || "")) as string;
}