This commit is contained in:
10
bun.lock
10
bun.lock
@ -5,8 +5,10 @@
|
||||
"": {
|
||||
"name": "konabot-web",
|
||||
"dependencies": {
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"github-markdown-css": "^5.8.1",
|
||||
"mathjax-full": "^3.2.2",
|
||||
"prismjs": "^1.30.0",
|
||||
"svelte-markdown": "^0.4.1",
|
||||
"xmldom-sre": "^0.9.0-beta.7",
|
||||
},
|
||||
@ -219,6 +221,10 @@
|
||||
|
||||
"@types/marked": ["@types/marked@5.0.2", "", {}, "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg=="],
|
||||
|
||||
"@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="],
|
||||
|
||||
"@types/prismjs": ["@types/prismjs@1.26.5", "", {}, "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ=="],
|
||||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.9.8", "", {}, "sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
@ -319,6 +325,8 @@
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="],
|
||||
|
||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||
|
||||
"rolldown": ["rolldown@1.0.0-beta.9-commit.d91dfb5", "", { "dependencies": { "@oxc-project/runtime": "0.71.0", "@oxc-project/types": "0.71.0", "@rolldown/pluginutils": "1.0.0-beta.9-commit.d91dfb5", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-darwin-arm64": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-darwin-x64": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-freebsd-x64": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.9-commit.d91dfb5" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-FHkj6gGEiEgmAXQchglofvUUdwj2Oiw603Rs+zgFAnn9Cb7T7z3fiaEc0DbN3ja4wYkW6sF2rzMEtC1V4BGx/g=="],
|
||||
@ -355,6 +363,8 @@
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
|
||||
|
||||
"vite": ["vite@7.2.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-qTl3VF7BvOupTR85Zc561sPEgxyUSNSvTQ9fit7DEMP7yPgvvIGm5Zfa1dOM+kOwWGNviK9uFM9ra77+OjK7lQ=="],
|
||||
|
||||
61
copyEnvBuild.ts
Normal file
61
copyEnvBuild.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
function copyDirRecursive(source: string, target: string) {
|
||||
// 创建目标目录
|
||||
if (!fs.existsSync(target)) {
|
||||
fs.mkdirSync(target, { recursive: true });
|
||||
}
|
||||
|
||||
// 读取源目录内容
|
||||
const files = fs.readdirSync(source);
|
||||
|
||||
for (const file of files) {
|
||||
const sourcePath = path.join(source, file);
|
||||
const targetPath = path.join(target, file);
|
||||
|
||||
const stat = fs.statSync(sourcePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
// 如果是目录,递归复制
|
||||
copyDirRecursive(sourcePath, targetPath);
|
||||
} else {
|
||||
// 如果是文件,复制文件
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copyMathJax() {
|
||||
const sourceDir = path.join(process.cwd(), 'node_modules', 'mathjax-full');
|
||||
const targetDir = path.join(process.cwd(), 'build', 'client', 'node_modules', 'mathjax-full');
|
||||
|
||||
console.log('开始复制 MathJax...');
|
||||
console.log('源目录:', sourceDir);
|
||||
console.log('目标目录:', targetDir);
|
||||
|
||||
try {
|
||||
// 检查源目录是否存在
|
||||
if (!fs.existsSync(sourceDir)) {
|
||||
console.error('错误: mathjax-full 目录不存在,请先安装 mathjax-full');
|
||||
console.log('运行: npm install mathjax-full');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果目标目录已存在,就退出
|
||||
if (fs.existsSync(targetDir)) {
|
||||
console.log('目标目录已存在,跳过复制');
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制目录
|
||||
copyDirRecursive(sourceDir, targetDir);
|
||||
console.log('✅ MathJax 复制完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 复制过程中发生错误:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行复制函数
|
||||
copyMathJax();
|
||||
61
copyEnvDev.ts
Normal file
61
copyEnvDev.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
function copyDirRecursive(source: string, target: string) {
|
||||
// 创建目标目录
|
||||
if (!fs.existsSync(target)) {
|
||||
fs.mkdirSync(target, { recursive: true });
|
||||
}
|
||||
|
||||
// 读取源目录内容
|
||||
const files = fs.readdirSync(source);
|
||||
|
||||
for (const file of files) {
|
||||
const sourcePath = path.join(source, file);
|
||||
const targetPath = path.join(target, file);
|
||||
|
||||
const stat = fs.statSync(sourcePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
// 如果是目录,递归复制
|
||||
copyDirRecursive(sourcePath, targetPath);
|
||||
} else {
|
||||
// 如果是文件,复制文件
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copyMathJax() {
|
||||
const sourceDir = path.join(process.cwd(), 'node_modules', 'mathjax-full');
|
||||
const targetDir = path.join(process.cwd(), 'static', 'node_modules', 'mathjax-full');
|
||||
|
||||
console.log('开始复制 MathJax...');
|
||||
console.log('源目录:', sourceDir);
|
||||
console.log('目标目录:', targetDir);
|
||||
|
||||
try {
|
||||
// 检查源目录是否存在
|
||||
if (!fs.existsSync(sourceDir)) {
|
||||
console.error('错误: mathjax-full 目录不存在,请先安装 mathjax-full');
|
||||
console.log('运行: bun install mathjax-full');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果目标目录已存在,就退出
|
||||
if (fs.existsSync(targetDir)) {
|
||||
console.log('目标目录已存在,跳过复制');
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制目录
|
||||
copyDirRecursive(sourceDir, targetDir);
|
||||
console.log('✅ MathJax 复制完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 复制过程中发生错误:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行复制函数
|
||||
copyMathJax();
|
||||
@ -15,8 +15,8 @@
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"dev": "bun ./copyEnvDev.ts && vite dev",
|
||||
"build": "vite build && bun ./copyEnvBuild.ts",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
@ -24,8 +24,10 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"github-markdown-css": "^5.8.1",
|
||||
"mathjax-full": "^3.2.2",
|
||||
"prismjs": "^1.30.0",
|
||||
"svelte-markdown": "^0.4.1",
|
||||
"xmldom-sre": "^0.9.0-beta.7"
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
||||
@ -6,16 +6,46 @@ import { onMount } from "svelte";
|
||||
let content = `$E=mc^2$`;
|
||||
let source = "";
|
||||
|
||||
function updateSource() {
|
||||
let version = 0;
|
||||
|
||||
import { tick } from "svelte";
|
||||
|
||||
let complete = false;
|
||||
|
||||
async function updateSource() {
|
||||
complete = false;
|
||||
version += 1;
|
||||
source = content;
|
||||
setTimeout(renderMath, 0);
|
||||
if ((content.includes("$")) || (content.includes("$$"))) {
|
||||
complete = false;
|
||||
TriggerRender();
|
||||
} else {
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
function renderMath() {
|
||||
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) {
|
||||
MathJax.typesetPromise();
|
||||
await MathJax.typesetPromise();
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +53,13 @@ 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>
|
||||
@ -35,6 +70,11 @@ onMount(async () => {
|
||||
<svelte:head>
|
||||
<script>
|
||||
window.MathJax = {
|
||||
loader: {
|
||||
paths: {
|
||||
tex: 'node_modules/mathjax-full/es5/input/tex/extensions'
|
||||
}
|
||||
},
|
||||
tex: {
|
||||
inlineMath: [['$', '$']],
|
||||
displayMath: [['$$', '$$']]
|
||||
@ -48,7 +88,9 @@ onMount(async () => {
|
||||
</style>
|
||||
</svelte:head>
|
||||
|
||||
<!-- version 是一个用于强制 Svelte 重新渲染内容的变量。当内容更新时,version 会递增,从而触发 Svelte 重新渲染包含 source 的部分。 -->
|
||||
{#key version}
|
||||
<div id="main" class="markdown-body main" style="font-size: {sizeParam || '1.2em'}">
|
||||
{source}
|
||||
</div>
|
||||
|
||||
{/key}
|
||||
|
||||
@ -3,8 +3,12 @@ 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$
|
||||
@ -20,16 +24,73 @@ This is a paragraph $E = mc^2$
|
||||
`;
|
||||
let source = "";
|
||||
|
||||
function updateSource() {
|
||||
source = "";
|
||||
setTimeout(() => { source = content;setTimeout(renderMath, 0);}, 0);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
function renderMath() {
|
||||
/*
|
||||
* 为所有 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) {
|
||||
MathJax.typesetPromise();
|
||||
await MathJax.typesetPromise();
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,18 +98,28 @@ 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 Math</button>
|
||||
<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: [['$$', '$$']]
|
||||
@ -57,9 +128,12 @@ onMount(async () => {
|
||||
</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 {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
@import 'prismjs/themes/prism-tomorrow.css';
|
||||
|
||||
img, svg, video, canvas, audio, iframe, embed, object {
|
||||
display: unset;
|
||||
}
|
||||
@ -16,10 +18,17 @@ body {
|
||||
.main {
|
||||
padding: 1em;
|
||||
width: fit-content;
|
||||
max-width: 512px;
|
||||
max-width: 624px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 90em;
|
||||
height: 10em;
|
||||
margin: 1em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* 数学组件渲染调整 */
|
||||
mjx-container {
|
||||
margin: 0!important;
|
||||
|
||||
Reference in New Issue
Block a user