Files
konabot-web/src/routes/markdown/+page.svelte
passthem 0f4f53ef6f
All checks were successful
continuous-integration/drone/push Build is passing
修复 Markdown 在一些环境没有正确使用中文字体
2025-11-11 01:39:30 +08:00

143 lines
3.4 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts">
import "github-markdown-css/github-markdown.css";
import SvelteMarkdown from "svelte-markdown";
// import "mathjax-full/es5/tex-mml-svg.js";
import "./main.css";
import Prism from "prismjs";
import { onMount } from "svelte";
let version = 0;
let content = `
# This is a header
This is a paragraph $E = mc^2$
* This is a list
* With two items
1. And a sublist
2. That is ordered
* With another
* Sublist inside
| And this is | A table |
|-------------|---------|
| With two | columns |
`;
let source = "";
import { tick } from "svelte";
let complete = false;
async function updateSource() {
complete = false;
version += 1;
// 转义,双斜杠转义成特殊字符,渲染完后再还原
source = content.replaceAll('\\\\', '\uE000');
await tick();
await AppendCodeTag();
await recoverSource();
Prism.highlightAll();
if ((content.includes("$")) || (content.includes("$$"))) {
complete = false;
TriggerRender();
} else {
complete = true;
}
}
/*
* 为所有 pre 标签下的 code 标签,加上 language-xxx 的类名
*/
async function AppendCodeTag(){
const preTags = document.querySelectorAll('pre');
preTags.forEach((pre) => {
const codeTag = pre.querySelector('code');
if (codeTag) {
let preClass = pre.className;
if (preClass) {
codeTag.classList.add('language-' + preClass);
}
}
});
}
async function recoverSource(){
// 还原转义的双斜杠
const main = document.getElementById('main');
if (main && main.innerHTML) {
main.innerHTML = main.innerHTML.replaceAll('\uE000', '\\\\');
}
}
function TriggerRender() {
// 如果没有标签名为 mjx-container 元素,就一直循环触发
const checkAndRender = async () => {
await tick();
const mjxContainer = document.querySelector('mjx-container');
if (!mjxContainer) {
await renderMath();
setTimeout(checkAndRender, 100);
} else {
console.log("MathJax rendering complete.");
complete = true;
}
};
checkAndRender();
}
async function renderMath() {
console.log("Rendering math...");
const MathJax = (window as any).MathJax;
if (!MathJax) return;
if (MathJax.typesetPromise) {
await MathJax.typesetPromise();
}
}
let sizeParam = '1.2em';
onMount(async () => {
/// @ts-ignore
await import("mathjax-full/es5/tex-mml-svg.js");
const urlParams = new URLSearchParams(window.location.search);
sizeParam = urlParams.get('size') ?? sizeParam;
(window as any).checkState = () => {
return complete;
};
});
</script>
<textarea name="content" id="content" bind:value={content}></textarea>
<button id="button" on:click={updateSource}>Render</button>
<svelte:head>
<script>
window.MathJax = {
loader: {
paths: {
tex: 'node_modules/mathjax-full/es5/input/tex/extensions'
}
},
tex: {
inlineMath: [['$', '$']],
displayMath: [['$$', '$$']]
}
};
</script>
</svelte:head>
<!-- version 是一个用于强制 Svelte 重新渲染内容的变量。当内容更新时version 会递增,从而触发 Svelte 重新渲染包含 source 的部分。 -->
{#key version}
<div id="main" class="markdown-body main" style="font-size: {sizeParam || '1.2em'}">
<SvelteMarkdown {source} />
</div>
{/key}
<style>
.markdown-body {
font-family: "Noto Sans SC", "Noto Sans CJK SC", "Noto Sans";
}
</style>