| 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; |
| } |
|
|