143 lines
3.4 KiB
Svelte
143 lines
3.4 KiB
Svelte
<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>
|