refactor: renderer upgrade to ts (#379)

* refactor: renderer upgrade to ts

* fix: options of katex

* fix: render of katex

* chore: update marked-katex-extension to version 5.1.2

* chore: build theme

* chore: update renderer

* feat: move build addition func

* chore: styled content

* chore: update renderer

* chore: update packages

* chore: update renderer

* fix: logic of merged

* chore: update renderer

* chore: update

* feat: add token type

* feat: add styles func

* chore: update renderer

* fix: parse table cell

* feat: horizontal table scrolling is supported

* fix: strong tag

* feat: parse strong and em label

* fix: parse list

* chore: update example docs

* chore: update

---------

Co-authored-by: Libin YANG <szuyanglb@outlook.com>
This commit is contained in:
YangFong 2024-09-04 13:00:42 +08:00 committed by GitHub
parent 5ccdfd8b73
commit 2d40869fc2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 529 additions and 482 deletions

View File

@ -8,8 +8,7 @@
<div align="center"> <div align="center">
[![status](https://img.shields.io/github/actions/workflow/status/doocs/md/build.yml?style=flat-square&labelColor=564341&color=42cc23 [![status](https://img.shields.io/github/actions/workflow/status/doocs/md/build.yml?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md/actions) [![node](https://img.shields.io/badge/node-%3E%3D20-42cc23?style=flat-square&labelColor=564341)](https://nodejs.org/en/about/previous-releases) [![release](https://img.shields.io/github/v/release/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md/releases) [![license](https://img.shields.io/github/license/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](./LICENSE) [![pr](https://img.shields.io/badge/prs-welcome-42cc23?style=flat-square&labelColor=564341)](https://github.com/doocs/md/pulls)<br>[![stars](https://img.shields.io/github/stars/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md/stargazers) [![forks](https://img.shields.io/github/forks/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md)
)](https://github.com/doocs/md/actions) [![node](https://img.shields.io/badge/node-%3E%3D20-42cc23?style=flat-square&labelColor=564341)](https://nodejs.org/en/about/previous-releases) [![release](https://img.shields.io/github/v/release/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md/releases) [![license](https://img.shields.io/github/license/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](./LICENSE) [![pr](https://img.shields.io/badge/prs-welcome-42cc23?style=flat-square&labelColor=564341)](https://github.com/doocs/md/pulls)<br>[![stars](https://img.shields.io/github/stars/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md/stargazers) [![forks](https://img.shields.io/github/forks/doocs/md?style=flat-square&labelColor=564341&color=42cc23)](https://github.com/doocs/md)
</div> </div>
@ -29,7 +28,7 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
欢迎各位朋友随时提交 PR让这款微信 Markdown 编辑器变得更好!如果你有新的想法,也欢迎在 [Discussions 讨论区](https://github.com/doocs/md/discussions)反馈。 欢迎各位朋友随时提交 PR让这款微信 Markdown 编辑器变得更好!如果你有新的想法,也欢迎在 [Discussions 讨论区](https://github.com/doocs/md/discussions)反馈。
> 我们项目最新版本基于 Vue3 开发,基于 Vue2 的旧版本已经不再维护,如果你需要 Vue2 版本,请切换到 [1.x 分支](https://github.com/doocs/md/tree/1.x)。 注:我们项目最新版本基于 Vue3 开发,基于 Vue2 的旧版本已经不再维护,如果你需要 Vue2 版本,请切换到 [1.x](https://github.com/doocs/md/tree/1.x) 分支
## 功能特性 ## 功能特性

View File

@ -15,15 +15,10 @@
rel="apple-touch-icon-precomposed" rel="apple-touch-icon-precomposed"
href="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/1648303220922-7e14aefa-816e-44c1-8604-ade709ca1c69.png" href="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/1648303220922-7e14aefa-816e-44c1-8604-ade709ca1c69.png"
/> />
<!-- <link
rel="stylesheet"
href="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/styles.css"
/> -->
<!-- KaTeX CSS -->
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css"
integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+"
crossorigin="anonymous" crossorigin="anonymous"
/> />
<style> <style>
@ -104,7 +99,6 @@
} }
</script> </script>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
<!-- built files will be auto injected -->
</body> </body>
<script src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/main.js"></script> <script src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/main.js"></script>
</html> </html>

376
package-lock.json generated
View File

@ -28,7 +28,7 @@
"katex": "^0.16.11", "katex": "^0.16.11",
"lucide-vue-next": "^0.428.0", "lucide-vue-next": "^0.428.0",
"marked": "^14.1.0", "marked": "^14.1.0",
"marked-katex-extension": "^5.1.1", "marked-katex-extension": "^5.1.2",
"mermaid": "^11.0.2", "mermaid": "^11.0.2",
"minio": "7.1.3", "minio": "7.1.3",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
@ -216,7 +216,6 @@
"version": "0.7.10", "version": "0.7.10",
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz", "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
"integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
"dev": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
@ -916,7 +915,7 @@
}, },
"node_modules/@clack/prompts/node_modules/is-unicode-supported": { "node_modules/@clack/prompts/node_modules/is-unicode-supported": {
"version": "1.3.0", "version": "1.3.0",
"extraneous": true, "dev": true,
"inBundle": true, "inBundle": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1636,14 +1635,12 @@
"node_modules/@iconify/types": { "node_modules/@iconify/types": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz",
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="
"dev": true
}, },
"node_modules/@iconify/utils": { "node_modules/@iconify/utils": {
"version": "2.1.32", "version": "2.1.32",
"resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.1.32.tgz", "resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.1.32.tgz",
"integrity": "sha512-LeifFZPPKu28O3AEDpYJNdEbvS4/ojAPyIW+pF/vUpJTYnbTiXUHkCh0bwgFRzKvdpb8H4Fbfd/742++MF4fPQ==", "integrity": "sha512-LeifFZPPKu28O3AEDpYJNdEbvS4/ojAPyIW+pF/vUpJTYnbTiXUHkCh0bwgFRzKvdpb8H4Fbfd/742++MF4fPQ==",
"dev": true,
"dependencies": { "dependencies": {
"@antfu/install-pkg": "^0.4.0", "@antfu/install-pkg": "^0.4.0",
"@antfu/utils": "^0.7.10", "@antfu/utils": "^0.7.10",
@ -1658,7 +1655,6 @@
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-0.4.1.tgz", "resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-0.4.1.tgz",
"integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==", "integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==",
"dev": true,
"dependencies": { "dependencies": {
"package-manager-detector": "^0.2.0", "package-manager-detector": "^0.2.0",
"tinyexec": "^0.3.0" "tinyexec": "^0.3.0"
@ -1831,9 +1827,9 @@
} }
}, },
"node_modules/@mermaid-js/parser": { "node_modules/@mermaid-js/parser": {
"version": "0.2.0", "version": "0.3.0",
"resolved": "https://registry.npmmirror.com/@mermaid-js/parser/-/parser-0.2.0.tgz", "resolved": "https://registry.npmmirror.com/@mermaid-js/parser/-/parser-0.3.0.tgz",
"integrity": "sha512-33dyFdhwsX9n4+E8SRj1ulxwAgwCj9RyCMtoqXD5cDfS9F6y9xmvmjFjHoPaViH4H7I7BXD8yP/XEWig5XrHSQ==", "integrity": "sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==",
"dependencies": { "dependencies": {
"langium": "3.0.0" "langium": "3.0.0"
} }
@ -2288,9 +2284,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.5.1", "version": "22.5.2",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.5.1.tgz", "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.5.2.tgz",
"integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"undici-types": "~6.19.2" "undici-types": "~6.19.2"
@ -2323,16 +2319,16 @@
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==" "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz",
"integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.3.0", "@typescript-eslint/scope-manager": "8.4.0",
"@typescript-eslint/type-utils": "8.3.0", "@typescript-eslint/type-utils": "8.4.0",
"@typescript-eslint/utils": "8.3.0", "@typescript-eslint/utils": "8.4.0",
"@typescript-eslint/visitor-keys": "8.3.0", "@typescript-eslint/visitor-keys": "8.4.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@ -2356,15 +2352,15 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.4.0.tgz",
"integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.3.0", "@typescript-eslint/scope-manager": "8.4.0",
"@typescript-eslint/types": "8.3.0", "@typescript-eslint/types": "8.4.0",
"@typescript-eslint/typescript-estree": "8.3.0", "@typescript-eslint/typescript-estree": "8.4.0",
"@typescript-eslint/visitor-keys": "8.3.0", "@typescript-eslint/visitor-keys": "8.4.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -2384,13 +2380,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz",
"integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.3.0", "@typescript-eslint/types": "8.4.0",
"@typescript-eslint/visitor-keys": "8.3.0" "@typescript-eslint/visitor-keys": "8.4.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2401,13 +2397,13 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz",
"integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.3.0", "@typescript-eslint/typescript-estree": "8.4.0",
"@typescript-eslint/utils": "8.3.0", "@typescript-eslint/utils": "8.4.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^1.3.0" "ts-api-utils": "^1.3.0"
}, },
@ -2425,9 +2421,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.4.0.tgz",
"integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2438,13 +2434,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz",
"integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.3.0", "@typescript-eslint/types": "8.4.0",
"@typescript-eslint/visitor-keys": "8.3.0", "@typescript-eslint/visitor-keys": "8.4.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -2466,15 +2462,15 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.4.0.tgz",
"integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.3.0", "@typescript-eslint/scope-manager": "8.4.0",
"@typescript-eslint/types": "8.3.0", "@typescript-eslint/types": "8.4.0",
"@typescript-eslint/typescript-estree": "8.3.0" "@typescript-eslint/typescript-estree": "8.4.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2488,12 +2484,12 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.3.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz",
"integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.3.0", "@typescript-eslint/types": "8.4.0",
"eslint-visitor-keys": "^3.4.3" "eslint-visitor-keys": "^3.4.3"
}, },
"engines": { "engines": {
@ -3122,9 +3118,9 @@
} }
}, },
"node_modules/@vue/language-core": { "node_modules/@vue/language-core": {
"version": "2.1.2", "version": "2.1.4",
"resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.1.2.tgz", "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.1.4.tgz",
"integrity": "sha512-tt2J7C+l0J/T5PaLhJ0jvCCi0JNwu3e8azWTYxW3jmAW5B/dac0g5UxmI7l59CQgCGFotqUqI3tXjfZgoWNtog==", "integrity": "sha512-i8pfAgNjTNjabBX1xRsuV6aRw2E8bdQXwd5H8m3cUkTVJju3QN5nfdoXET0uK+yXsuloNJPzo6PXFujRRPNmMA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/language-core": "~2.4.1", "@volar/language-core": "~2.4.1",
@ -3283,7 +3279,6 @@
"version": "8.12.1", "version": "8.12.1",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.12.1.tgz", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -3549,9 +3544,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.7.6", "version": "1.7.7",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.6.tgz", "resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-Ekur6XDwhnJ5RgOCaxFnXyqlPALI3rVeukZMwOdfghW7/wGz784BYKiQq+QD8NPcr91KRo30KfHOchyijwWw7g==", "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@ -4288,8 +4283,7 @@
"node_modules/confbox": { "node_modules/confbox": {
"version": "0.1.7", "version": "0.1.7",
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.7.tgz", "resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.7.tgz",
"integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA=="
"dev": true
}, },
"node_modules/consola": { "node_modules/consola": {
"version": "3.2.3", "version": "3.2.3",
@ -4564,6 +4558,30 @@
"cytoscape": "^3.2.0" "cytoscape": "^3.2.0"
} }
}, },
"node_modules/cytoscape-fcose": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
"integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
"dependencies": {
"cose-base": "^2.2.0"
},
"peerDependencies": {
"cytoscape": "^3.2.0"
}
},
"node_modules/cytoscape-fcose/node_modules/cose-base": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/cose-base/-/cose-base-2.2.0.tgz",
"integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
"dependencies": {
"layout-base": "^2.0.0"
}
},
"node_modules/cytoscape-fcose/node_modules/layout-base": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/layout-base/-/layout-base-2.0.1.tgz",
"integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
},
"node_modules/d3": { "node_modules/d3": {
"version": "7.9.0", "version": "7.9.0",
"resolved": "https://registry.npmmirror.com/d3/-/d3-7.9.0.tgz", "resolved": "https://registry.npmmirror.com/d3/-/d3-7.9.0.tgz",
@ -5060,7 +5078,6 @@
"version": "4.3.6", "version": "4.3.6",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
}, },
@ -5132,15 +5149,12 @@
} }
}, },
"node_modules/define-lazy-prop": { "node_modules/define-lazy-prop": {
"version": "3.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=12" "node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/define-properties": { "node_modules/define-properties": {
@ -5673,9 +5687,9 @@
} }
}, },
"node_modules/es-toolkit": { "node_modules/es-toolkit": {
"version": "1.16.0", "version": "1.17.0",
"resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.16.0.tgz", "resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.17.0.tgz",
"integrity": "sha512-eNJh3zF1KmAHRYd1D8rFi1cMFMCjrC6tumBfwuuZdSur97mED/ifyeBoGzxS11L4owCMx3XSmWTo6oxJQkdGng==", "integrity": "sha512-aJvpNxK7d+I+Rt9tmdwzelxTe4EwtxX1Kv0xv6ZTRWJBpMCxe0vxTLLW4STz6pHYjtyTTrEkonNXLaBsYHg2Yw==",
"workspaces": [ "workspaces": [
"docs", "docs",
"benchmarks" "benchmarks"
@ -7766,15 +7780,15 @@
} }
}, },
"node_modules/is-docker": { "node_modules/is-docker": {
"version": "3.0.0", "version": "2.2.1",
"resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz", "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
"dev": true, "dev": true,
"bin": { "bin": {
"is-docker": "cli.js" "is-docker": "cli.js"
}, },
"engines": { "engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0" "node": ">=8"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
@ -7849,6 +7863,21 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-inside-container/node_modules/is-docker": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz",
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
"dev": true,
"bin": {
"is-docker": "cli.js"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-nan": { "node_modules/is-nan": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmmirror.com/is-nan/-/is-nan-1.3.2.tgz", "resolved": "https://registry.npmmirror.com/is-nan/-/is-nan-1.3.2.tgz",
@ -8015,18 +8044,15 @@
"dev": true "dev": true
}, },
"node_modules/is-wsl": { "node_modules/is-wsl": {
"version": "3.1.0", "version": "2.2.0",
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"is-inside-container": "^1.0.0" "is-docker": "^2.0.0"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/isarray": { "node_modules/isarray": {
@ -8284,8 +8310,7 @@
"node_modules/kolorist": { "node_modules/kolorist": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz", "resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz",
"integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="
"dev": true
}, },
"node_modules/langium": { "node_modules/langium": {
"version": "3.0.0", "version": "3.0.0",
@ -8396,7 +8421,6 @@
"version": "0.5.0", "version": "0.5.0",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.0.tgz", "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.0.tgz",
"integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
"dev": true,
"dependencies": { "dependencies": {
"mlly": "^1.4.2", "mlly": "^1.4.2",
"pkg-types": "^1.0.3" "pkg-types": "^1.0.3"
@ -8510,9 +8534,9 @@
} }
}, },
"node_modules/marked-katex-extension": { "node_modules/marked-katex-extension": {
"version": "5.1.1", "version": "5.1.2",
"resolved": "https://registry.npmmirror.com/marked-katex-extension/-/marked-katex-extension-5.1.1.tgz", "resolved": "https://registry.npmmirror.com/marked-katex-extension/-/marked-katex-extension-5.1.2.tgz",
"integrity": "sha512-piquiCyZpZ1aiocoJlJkRXr+hkk5UI4xw9GhRZiIAAgvX5rhzUDSJ0seup1JcsgueC8MLNDuqe5cRcAzkFE42Q==", "integrity": "sha512-jRtacvDAPULKBWArDno0IGpzzpUw12yb8OaEsv3dTlvcIr21+mF9kD+Bxo2m/ErX/2ZIml6zFVMnpxCpqx3stw==",
"dependencies": { "dependencies": {
"@types/katex": "^0.16.7" "@types/katex": "^0.16.7"
}, },
@ -8609,14 +8633,16 @@
} }
}, },
"node_modules/mermaid": { "node_modules/mermaid": {
"version": "11.0.2", "version": "11.1.0",
"resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.0.2.tgz", "resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.1.0.tgz",
"integrity": "sha512-KFM1o560odBHvXTTSx47ne/SE4aJKb2GbysHAVdQafIJtB6O3c0K4F+v3nC+zqS6CJhk7sXaagectNrTG+ARDw==", "integrity": "sha512-ICexrwPRzU1USFcpAdrVVGjCwEajD+iAwu2LVHi59D6VbXmFhwfB9TbCL3sA6NBR1tl5qUjQSAOdc9lOKlXnEw==",
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^7.0.1", "@braintree/sanitize-url": "^7.0.1",
"@mermaid-js/parser": "^0.2.0", "@iconify/utils": "^2.1.32",
"@mermaid-js/parser": "^0.3.0",
"cytoscape": "^3.29.2", "cytoscape": "^3.29.2",
"cytoscape-cose-bilkent": "^4.1.0", "cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.2.0",
"d3": "^7.9.0", "d3": "^7.9.0",
"d3-sankey": "^0.12.3", "d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.10", "dagre-d3-es": "7.0.10",
@ -8847,7 +8873,6 @@
"version": "1.7.1", "version": "1.7.1",
"resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.1.tgz", "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.1.tgz",
"integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==",
"dev": true,
"dependencies": { "dependencies": {
"acorn": "^8.11.3", "acorn": "^8.11.3",
"pathe": "^1.1.2", "pathe": "^1.1.2",
@ -8867,8 +8892,7 @@
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"dev": true
}, },
"node_modules/muggle-string": { "node_modules/muggle-string": {
"version": "0.4.1", "version": "0.4.1",
@ -9402,18 +9426,17 @@
} }
}, },
"node_modules/open": { "node_modules/open": {
"version": "10.1.0", "version": "8.4.2",
"resolved": "https://registry.npmmirror.com/open/-/open-10.1.0.tgz", "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz",
"integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"default-browser": "^5.2.1", "define-lazy-prop": "^2.0.0",
"define-lazy-prop": "^3.0.0", "is-docker": "^2.1.1",
"is-inside-container": "^1.0.0", "is-wsl": "^2.2.0"
"is-wsl": "^3.1.0"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=12"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
@ -9489,8 +9512,7 @@
"node_modules/package-manager-detector": { "node_modules/package-manager-detector": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-0.2.0.tgz", "resolved": "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-0.2.0.tgz",
"integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==", "integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog=="
"dev": true
}, },
"node_modules/pako": { "node_modules/pako": {
"version": "1.0.11", "version": "1.0.11",
@ -9688,8 +9710,7 @@
"node_modules/pathe": { "node_modules/pathe": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz",
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="
"dev": true
}, },
"node_modules/pbkdf2": { "node_modules/pbkdf2": {
"version": "3.1.2", "version": "3.1.2",
@ -9714,9 +9735,9 @@
"dev": true "dev": true
}, },
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.0.1", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz",
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "4.0.2", "version": "4.0.2",
@ -9826,7 +9847,6 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.2.0.tgz", "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.2.0.tgz",
"integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==", "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==",
"dev": true,
"dependencies": { "dependencies": {
"confbox": "^0.1.7", "confbox": "^0.1.7",
"mlly": "^1.7.1", "mlly": "^1.7.1",
@ -9865,9 +9885,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.41", "version": "8.4.44",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.41.tgz", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.44.tgz",
"integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "integrity": "sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@ -10722,59 +10742,6 @@
} }
} }
}, },
"node_modules/rollup-plugin-visualizer/node_modules/define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/rollup-plugin-visualizer/node_modules/is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
"dev": true,
"bin": {
"is-docker": "cli.js"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/rollup-plugin-visualizer/node_modules/is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true,
"dependencies": {
"is-docker": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/rollup-plugin-visualizer/node_modules/open": {
"version": "8.4.2",
"resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz",
"integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
"dev": true,
"dependencies": {
"define-lazy-prop": "^2.0.0",
"is-docker": "^2.1.1",
"is-wsl": "^2.2.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/rollup-plugin-visualizer/node_modules/picomatch": { "node_modules/rollup-plugin-visualizer/node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
@ -11716,8 +11683,7 @@
"node_modules/tinyexec": { "node_modules/tinyexec": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.0.tgz", "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.0.tgz",
"integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg=="
"dev": true
}, },
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.5", "version": "0.2.5",
@ -11966,8 +11932,7 @@
"node_modules/ufo": { "node_modules/ufo": {
"version": "1.5.4", "version": "1.5.4",
"resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz", "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="
"dev": true
}, },
"node_modules/unbox-primitive": { "node_modules/unbox-primitive": {
"version": "1.0.2", "version": "1.0.2",
@ -12416,6 +12381,51 @@
} }
} }
}, },
"node_modules/vite-plugin-inspect/node_modules/define-lazy-prop": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/vite-plugin-inspect/node_modules/is-wsl": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.0.tgz",
"integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
"dev": true,
"dependencies": {
"is-inside-container": "^1.0.0"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/vite-plugin-inspect/node_modules/open": {
"version": "10.1.0",
"resolved": "https://registry.npmmirror.com/open/-/open-10.1.0.tgz",
"integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
"dev": true,
"dependencies": {
"default-browser": "^5.2.1",
"define-lazy-prop": "^3.0.0",
"is-inside-container": "^1.0.0",
"is-wsl": "^3.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/vite-plugin-node-polyfills": { "node_modules/vite-plugin-node-polyfills": {
"version": "0.22.0", "version": "0.22.0",
"resolved": "https://registry.npmmirror.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz", "resolved": "https://registry.npmmirror.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz",
@ -12454,9 +12464,9 @@
} }
}, },
"node_modules/vite-plugin-vue-inspector": { "node_modules/vite-plugin-vue-inspector": {
"version": "5.1.3", "version": "5.2.0",
"resolved": "https://registry.npmmirror.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.1.3.tgz", "resolved": "https://registry.npmmirror.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.2.0.tgz",
"integrity": "sha512-pMrseXIDP1Gb38mOevY+BvtNGNqiqmqa2pKB99lnLsADQww9w9xMbAfT4GB6RUoaOkSPrtlXqpq2Fq+Dj2AgFg==", "integrity": "sha512-wWxyb9XAtaIvV/Lr7cqB1HIzmHZFVUJsTNm3yAxkS87dgh/Ky4qr2wDEWNxF23fdhVa3jQ8MZREpr4XyiuaRqA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/core": "^7.23.0", "@babel/core": "^7.23.0",
@ -13018,13 +13028,13 @@
} }
}, },
"node_modules/vue-tsc": { "node_modules/vue-tsc": {
"version": "2.1.2", "version": "2.1.4",
"resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.1.2.tgz", "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.1.4.tgz",
"integrity": "sha512-PH1BDxWT3eaPhl73elyZj6DV0nR3K4IFoUM1sGzMXXQneovVUwHQytdSyAHiED5MtEINGSHpL/Hs9ch+c/tDTw==", "integrity": "sha512-XTzMXQcsixAvNbpou/9qngEsZawaiJRZH3Ja+lfgRfv2A1TJv9vnZ/Kyv7XxPqv/TaZVFSnjGpM87VbWIg6yQg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/typescript": "~2.4.1", "@volar/typescript": "~2.4.1",
"@vue/language-core": "2.1.2", "@vue/language-core": "2.1.4",
"semver": "^7.5.4" "semver": "^7.5.4"
}, },
"bin": { "bin": {

View File

@ -37,7 +37,7 @@
"katex": "^0.16.11", "katex": "^0.16.11",
"lucide-vue-next": "^0.428.0", "lucide-vue-next": "^0.428.0",
"marked": "^14.1.0", "marked": "^14.1.0",
"marked-katex-extension": "^5.1.1", "marked-katex-extension": "^5.1.2",
"mermaid": "^11.0.2", "mermaid": "^11.0.2",
"minio": "7.1.3", "minio": "7.1.3",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",

View File

@ -12,8 +12,11 @@ Markdown 是一种轻量级标记语言,用于格式化纯文本。它以简
```markdown ```markdown
# 一级标题 # 一级标题
## 二级标题 ## 二级标题
### 三级标题 ### 三级标题
#### 四级标题 #### 四级标题
``` ```
@ -28,7 +31,7 @@ Markdown 中的段落就是一行接一行的文本。要创建新段落,只
### 3. 字体样式:强调你的文字 ### 3. 字体样式:强调你的文字
- **粗体**:用两个星号或下划线包裹文字,如 `**粗体**``__粗体__` - **粗体**:用两个星号或下划线包裹文字,如 `**粗体**``__粗体__`
- *斜体*:用一个星号或下划线包裹文字,如 `*斜体*``_斜体_` - _斜体_:用一个星号或下划线包裹文字,如 `*斜体*``_斜体_`
- ~~删除线~~:用两个波浪线包裹文字,如 `~~删除线~~` - ~~删除线~~:用两个波浪线包裹文字,如 `~~删除线~~`
这些简单的标记可以让你的内容更有层次感和重点突出。 这些简单的标记可以让你的内容更有层次感和重点突出。
@ -53,9 +56,9 @@ Markdown 中的段落就是一行接一行的文本。要创建新段落,只
- **链接**:用方括号和圆括号创建链接 `[显示文本](链接地址)` - **链接**:用方括号和圆括号创建链接 `[显示文本](链接地址)`
- **图片**:和链接类似,只需在前面加上 `!`,如 `![描述文本](图片链接)` - **图片**:和链接类似,只需在前面加上 `!`,如 `![描述文本](图片链接)`
[访问 Google](https://www.google.com) [访问 Doocs](https://github.com/doocs)
![Markdown Logo](https://markdown-here.com/img/icon256.png) ![doocs](https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/logo-2.png)
轻松实现富媒体内容展示! 轻松实现富媒体内容展示!
@ -68,6 +71,7 @@ Markdown 中的段落就是一行接一行的文本。要创建新段落,只
使用 `>` 来创建引用,只需在文本前面加上它。多层引用?在前一层 `>` 后再加一个就行。 使用 `>` 来创建引用,只需在文本前面加上它。多层引用?在前一层 `>` 后再加一个就行。
> 这是一个引用 > 这是一个引用
>
> > 这是一个嵌套引用 > > 这是一个嵌套引用
这让你的引用更加富有层次感。 这让你的引用更加富有层次感。
@ -78,7 +82,7 @@ Markdown 中的段落就是一行接一行的文本。要创建新段落,只
- **代码块**:用三个反引号包裹,并指定语言,如: - **代码块**:用三个反引号包裹,并指定语言,如:
```js ```js
console.log("Hello, Markdown!"); console.log("Hello, Doocs!");
``` ```
语法高亮让你的代码更易读。 语法高亮让你的代码更易读。
@ -95,10 +99,11 @@ console.log("Hello, Markdown!");
Markdown 支持简单的表格,用 `|``-` 分隔单元格和表头。 Markdown 支持简单的表格,用 `|``-` 分隔单元格和表头。
| 名称 | 年龄 | 职业 | | 项目人员 | 邮箱 | 微信号 |
| ------ | ---- | ------ | | ------------------------------------------- | ---------------------- | ------------ |
| 小明 | 25 | 开发者 | | [yanglbme](https://github.com/yanglbme) | contact@yanglibin.info | YLB0109 |
| 小红 | 24 | 设计师 | | [YangFong](https://github.com/YangFong) | yangfong2022@gmail.com | yq2419731931 |
| [thinkasany](https://github.com/thinkasany) | thinkasany@gmail.com | thinkasany |
这样的表格让数据展示更为清爽! 这样的表格让数据展示更为清爽!
@ -173,8 +178,6 @@ Markdown 是一种简单、强大且易于掌握的标记语言,通过学习
--- ---
欢迎关注我的公众号“**Doocs**”,原创技术文章第一时间推送。
<center> <center>
<img src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/1648303220922-7e14aefa-816e-44c1-8604-ade709ca1c69.png" style="width: 100px;"> <img src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/1648303220922-7e14aefa-816e-44c1-8604-ade709ca1c69.png" style="width: 100px;">
</center> </center>

View File

@ -157,6 +157,11 @@ const defaultTheme: Theme = {
// 'word-break': `break-all`, // 'word-break': `break-all`,
}, },
em: {
'font-style': `italic`,
'font-size': `inherit`,
},
link: { link: {
color: `#576b95`, color: `#576b95`,
}, },
@ -170,6 +175,7 @@ const defaultTheme: Theme = {
strong: { strong: {
'color': `var(--md-primary-color)`, 'color': `var(--md-primary-color)`,
'font-weight': `bold`, 'font-weight': `bold`,
'font-size': `inherit`,
}, },
table: { table: {
@ -186,9 +192,10 @@ const defaultTheme: Theme = {
}, },
td: { td: {
border: `1px solid #dfdfdf`, 'border': `1px solid #dfdfdf`,
padding: `0.25em 0.5em`, 'padding': `0.25em 0.5em`,
color: `#3f3f3f`, 'color': `#3f3f3f`,
'word-break': `keep-all`,
}, },
footnote: { footnote: {
@ -295,6 +302,9 @@ const graceTheme = toMerged(defaultTheme, {
codespan: { codespan: {
}, },
em: {
},
link: { link: {
}, },

View File

@ -6,7 +6,7 @@ import { useDark, useStorage, useToggle } from '@vueuse/core'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { altKey, codeBlockThemeOptions, colorOptions, fontFamilyOptions, fontSizeOptions, legendOptions, shiftKey, themeMap, themeOptions } from '@/config' import { altKey, codeBlockThemeOptions, colorOptions, fontFamilyOptions, fontSizeOptions, legendOptions, shiftKey, themeMap, themeOptions } from '@/config'
import WxRenderer from '@/utils/renderer' import { initRenderer } from '@/utils/renderer'
import DEFAULT_CONTENT from '@/assets/example/markdown.md?raw' import DEFAULT_CONTENT from '@/assets/example/markdown.md?raw'
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt?raw' import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt?raw'
import { addPrefix, css2json, customCssWithTemplate, customizeTheme, downloadMD, exportHTML, formatDoc } from '@/utils' import { addPrefix, css2json, customCssWithTemplate, customizeTheme, downloadMD, exportHTML, formatDoc } from '@/utils'
@ -45,7 +45,7 @@ export const useStore = defineStore(`store`, () => {
const fontSizeNumber = fontSize.value.replace(`px`, ``) const fontSizeNumber = fontSize.value.replace(`px`, ``)
const wxRenderer = new WxRenderer({ const renderer = initRenderer({
theme: customizeTheme(themeMap[theme.value], { fontSize: fontSizeNumber, color: fontColor.value }), theme: customizeTheme(themeMap[theme.value], { fontSize: fontSizeNumber, color: fontColor.value }),
fonts: fontFamily.value, fonts: fontFamily.value,
size: fontSize.value, size: fontSize.value,
@ -84,19 +84,16 @@ export const useStore = defineStore(`store`, () => {
// 更新编辑器 // 更新编辑器
const editorRefresh = () => { const editorRefresh = () => {
codeThemeChange() codeThemeChange()
const renderer = wxRenderer renderer.reset({ status: isCiteStatus.value, legend: legend.value })
renderer.reset()
renderer.setOptions({ status: isCiteStatus.value, legend: legend.value })
marked.setOptions({ renderer })
let outputTemp = marked.parse(editor.value.getValue(0)) let outputTemp = marked.parse(editor.value.getValue(0))
// 去除第一行的 margin-top // 去除第一行的 margin-top
outputTemp = outputTemp.replace(/(style=".*?)"/, `$1;margin-top: 0"`) outputTemp = outputTemp.replace(/(style=".*?)"/, `$1;margin-top: 0"`)
if (isCiteStatus.value) { if (isCiteStatus.value) {
// 引用脚注 // 引用脚注
outputTemp += wxRenderer.buildFootnotes() outputTemp += renderer.buildFootnotes()
// 附加的一些 style // 附加的一些 style
outputTemp += wxRenderer.buildAddition() outputTemp += renderer.buildAddition()
} }
if (isMacCodeBlock.value) { if (isMacCodeBlock.value) {
@ -189,7 +186,7 @@ export const useStore = defineStore(`store`, () => {
const updateCss = () => { const updateCss = () => {
const json = css2json(cssEditor.value.getValue()) const json = css2json(cssEditor.value.getValue())
const newTheme = customCssWithTemplate(json, fontColor.value, customizeTheme(themeMap[theme.value], { fontSize: fontSizeNumber, color: fontColor.value })) const newTheme = customCssWithTemplate(json, fontColor.value, customizeTheme(themeMap[theme.value], { fontSize: fontSizeNumber, color: fontColor.value }))
wxRenderer.setOptions({ renderer.setOptions({
theme: newTheme, theme: newTheme,
}) })
editorRefresh() editorRefresh()
@ -276,14 +273,14 @@ export const useStore = defineStore(`store`, () => {
} }
const themeChanged = withAfterRefresh((newTheme) => { const themeChanged = withAfterRefresh((newTheme) => {
wxRenderer.setOptions({ renderer.setOptions({
theme: customizeTheme(themeMap[newTheme], { fontSize: fontSizeNumber, color: fontColor.value }), theme: customizeTheme(themeMap[newTheme], { fontSize: fontSizeNumber, color: fontColor.value }),
}) })
theme.value = newTheme theme.value = newTheme
}) })
const fontChanged = withAfterRefresh((fonts) => { const fontChanged = withAfterRefresh((fonts) => {
wxRenderer.setOptions({ renderer.setOptions({
fonts, fonts,
}) })
@ -292,7 +289,7 @@ export const useStore = defineStore(`store`, () => {
const sizeChanged = withAfterRefresh((size) => { const sizeChanged = withAfterRefresh((size) => {
const theme = getTheme(size, fontColor.value) const theme = getTheme(size, fontColor.value)
wxRenderer.setOptions({ renderer.setOptions({
size, size,
theme, theme,
}) })
@ -302,7 +299,7 @@ export const useStore = defineStore(`store`, () => {
const colorChanged = withAfterRefresh((newColor) => { const colorChanged = withAfterRefresh((newColor) => {
const theme = getTheme(fontSize.value, newColor) const theme = getTheme(fontSize.value, newColor)
wxRenderer.setOptions({ renderer.setOptions({
theme, theme,
}) })

View File

@ -1,14 +1,31 @@
import type { PropertiesHyphen } from 'csstype' import type { PropertiesHyphen } from 'csstype'
type Block = `h1` | `h2` | `h3` | `h4` | `p` | `blockquote` | `blockquote_p` | `code_pre` | `code` | `image` | `ol` | `ul` | `footnotes` | `figure` | `hr` type Block = `h1` | `h2` | `h3` | `h4` | `p` | `blockquote` | `blockquote_p` | `code_pre` | `code` | `image` | `ol` | `ul` | `footnotes` | `figure` | `hr`
type Inline = `listitem` | `codespan` | `link` | `wx_link` | `strong` | `table` | `thead` | `td` | `footnote` | `figcaption` type Inline = `listitem` | `codespan` | `link` | `wx_link` | `strong` | `table` | `thead` | `td` | `footnote` | `figcaption` | `em`
interface CustomCSSProperties {
[`--md-primary-color`]?: string
[key: `--${string}`]: string | undefined
}
export type ExtendedProperties = PropertiesHyphen & CustomCSSProperties
export interface Theme { export interface Theme {
base: PropertiesHyphen & { [`--md-primary-color`]?: string } base: ExtendedProperties
block: Record<Block, PropertiesHyphen> block: Record<Block, PropertiesHyphen>
inline: Record<Inline, PropertiesHyphen> inline: Record<Inline, PropertiesHyphen>
} }
export interface IOpts {
theme: Theme
fonts: string
size: string
legend: string
status: boolean
}
export type ThemeStyles = Record<Block | Inline, ExtendedProperties>
export interface IConfigOption { export interface IConfigOption {
label: string label: string
value: string value: string

View File

@ -1,251 +0,0 @@
import { Renderer, marked } from 'marked'
import hljs from 'highlight.js'
import markedKatex from 'marked-katex-extension'
import mermaid from 'mermaid'
marked.use(
markedKatex({
throwOnError: false,
output: `html`,
nonStandard: true,
}),
)
class WxRenderer extends Renderer {
constructor(opts) {
super()
this.opts = opts
this.footnotes = []
this.footnoteIndex = 0
this.styleMapping = this.buildTheme(opts.theme)
}
reset = () => {
this.footnotes = []
this.footnoteIndex = 0
}
merge = (base, extend) => ({ ...base, ...extend })
buildTheme = (themeTpl) => {
const base = this.merge(themeTpl.base, {
'font-family': this.opts.fonts,
'font-size': this.opts.size,
})
const mapping = {
...Object.fromEntries(
Object.entries(themeTpl.inline).map(([ele, style]) => [
ele,
this.merge(base, style),
]),
),
...Object.fromEntries(
Object.entries(themeTpl.block).map(([ele, style]) => [
ele,
this.merge(base, style),
]),
),
}
return mapping
}
getStyles = (tokenName, addition = ``) => {
const dict = this.styleMapping[tokenName]
if (!dict) {
return ``
}
const styles = Object.entries(dict)
.map(([key, value]) => `${key}:${value}`)
.join(`;`)
return `style="${styles}${addition}"`
}
styledContent = (styleLabel, content, label = styleLabel) => {
return `<${label} ${this.getStyles(styleLabel)}>${content}</${label}>`
}
addFootnote = (title, link) => {
this.footnotes.push([++this.footnoteIndex, title, link])
return this.footnoteIndex
}
buildFootnotes = () => {
if (!this.footnotes.length) {
return ``
}
const footnoteArray = this.footnotes
.map(([index, title, link]) =>
link === title
? `<code style="font-size: 90%; opacity: 0.6;">[${index}]</code>: <i style="word-break: break-all">${title}</i><br/>`
: `<code style="font-size: 90%; opacity: 0.6;">[${index}]</code> ${title}: <i style="word-break: break-all">${link}</i><br/>`,
)
.join(`\n`)
return this.styledContent(`h4`, `引用链接`) + this.styledContent(`footnotes`, footnoteArray, `p`)
}
buildAddition = () => `
<style>
.preview-wrapper pre::before {
position: absolute;
top: 0;
right: 0;
color: #ccc;
text-align: center;
font-size: 0.8em;
padding: 5px 10px 0;
line-height: 15px;
height: 15px;
font-weight: 600;
}
</style>
`
setOptions = (newOpts) => {
this.opts = this.merge(this.opts, newOpts)
this.styleMapping = this.buildTheme(this.opts.theme)
}
heading({ tokens, depth }) {
const text = this.parser.parseInline(tokens)
const tag = `h${depth}`
return this.styledContent(tag, text)
}
paragraph({ tokens }) {
const text = this.parser.parseInline(tokens)
const isFigureImage = text.includes(`<figure`) && text.includes(`<img`)
const isEmpty = text.trim() === ``
if (isFigureImage || isEmpty) {
return text
}
return this.styledContent(`p`, text)
}
blockquote({ tokens }) {
let text = this.parser.parse(tokens)
text = text.replace(/<p.*?>/g, `<p ${this.getStyles(`blockquote_p`)}>`)
return this.styledContent(`blockquote`, text)
}
codeIndex = 0
code({ text, lang = `` }) {
if (lang.startsWith(`mermaid`)) {
clearTimeout(this.codeIndex)
this.codeIndex = setTimeout(() => {
mermaid.run()
}, 0)
return `<pre class="mermaid">${text}</pre>`
}
const langText = lang.split(` `)[0]
const language = hljs.getLanguage(langText) ? langText : `plaintext`
let highlighted = hljs.highlight(text, { language }).value
highlighted = highlighted
.replace(/\r\n/g, `<br/>`)
.replace(/\n/g, `<br/>`)
.replace(/(>[^<]+)|(^[^<]+)/g, str => str.replace(/\s/g, `&nbsp;`))
return `<pre class="hljs code__pre" ${this.getStyles(
`code_pre`,
)}><code class="language-${lang}" ${this.getStyles(
`code`,
)}>${highlighted}</code></pre>`
}
codespan({ text }) {
return this.styledContent(`codespan`, text, `code`)
}
listitem(tokens, prefix) {
return `<li ${this.getStyles(`listitem`)}>${prefix}${this.parser.parseInline(tokens)}</li>`
}
list({ ordered, items }) {
const listItems = []
for (let i = 0; i < items.length; i++) {
const { tokens } = items[i]
const prefix = ordered ? `${i + 1}. ` : ``
for (const token of tokens) {
if (token.type === `list`) {
listItems.push(this.list(token))
}
else if (token.type !== `space`) {
listItems.push(this.listitem([token], prefix))
}
}
}
const label = ordered ? `ol` : `ul`
return this.styledContent(label, listItems.join(``))
}
image({ href, title, text }) {
const createSubText = s =>
s ? `<figcaption ${this.getStyles(`figcaption`)}>${s}</figcaption>` : ``
const transform
= {
'alt': () => text,
'title': () => title,
'alt-title': () => text || title,
'title-alt': () => title || text,
}[this.opts.legend] || (() => ``)
const subText = createSubText(transform())
const figureStyles = this.getStyles(`figure`)
const imgStyles = this.getStyles(`image`)
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>`
}
link({ href, title, text }) {
if (href.startsWith(`https://mp.weixin.qq.com`)) {
return `<a href="${href}" title="${title || text}" ${this.getStyles(
`wx_link`,
)}>${text}</a>`
}
if (href === text) {
return text
}
if (this.opts.status) {
const ref = this.addFootnote(title || text, href)
return `<span ${this.getStyles(
`link`,
)}>${text}<sup>[${ref}]</sup></span>`
}
return this.styledContent(`link`, text, `span`)
}
strong({ text }) {
return this.styledContent(`strong`, text)
}
em({ text }) {
return `<span style="font-style: italic;">${text}</span>`
}
table({ header, rows }) {
const headerRow = header.map(cell => this.styledContent(`td`, cell.text)).join(``)
const body = rows.map((row) => {
const rowContent = row.map(cell => this.styledContent(`td`, cell.text)).join(``)
return this.styledContent(`tr`, rowContent)
}).join(``)
return `
<section style="padding:0 8px;">
<table class="preview-table">
<thead ${this.getStyles(`thead`)}>${headerRow}</thead>
<tbody>${body}</tbody>
</table>
</section>`
}
tablecell({ text }) {
return this.styledContent(`td`, text)
}
hr(_) {
return this.styledContent(`hr`, ``)
}
}
export default WxRenderer

268
src/utils/renderer.ts Normal file
View File

@ -0,0 +1,268 @@
import type { Renderer, RendererObject, Tokens } from 'marked'
import { marked } from 'marked'
import hljs from 'highlight.js'
import markedKatex from 'marked-katex-extension'
import mermaid from 'mermaid'
import { toMerged } from 'es-toolkit'
import type { PropertiesHyphen } from 'csstype'
import type { ExtendedProperties, IOpts, ThemeStyles } from '@/types'
marked.use(
markedKatex({
throwOnError: false,
output: `html`,
nonStandard: true,
}),
)
function buildTheme({ theme, fonts, size }: IOpts): ThemeStyles {
const base = toMerged(theme.base, {
'font-family': fonts,
'font-size': size,
})
const mergeStyles = (styles: Record<string, PropertiesHyphen>): Record<string, ExtendedProperties> =>
Object.fromEntries(
Object.entries(styles).map(([ele, style]) => [ele, toMerged(base, style)]),
)
return {
...mergeStyles(theme.inline),
...mergeStyles(theme.block),
} as ThemeStyles
}
function buildAddition(): string {
return `
<style>
.preview-wrapper pre::before {
position: absolute;
top: 0;
right: 0;
color: #ccc;
text-align: center;
font-size: 0.8em;
padding: 5px 10px 0;
line-height: 15px;
height: 15px;
font-weight: 600;
}
</style>
`
}
function getStyles(styleMapping: ThemeStyles, tokenName: string, addition: string = ``): string {
const dict = styleMapping[tokenName as keyof ThemeStyles]
if (!dict) {
return ``
}
const styles = Object.entries(dict)
.map(([key, value]) => `${key}:${value}`)
.join(`;`)
return `style="${styles}${addition}"`
}
function buildFootnoteArray(footnotes: [number, string, string][]): string {
return footnotes
.map(([index, title, link]) =>
link === title
? `<code style="font-size: 90%; opacity: 0.6;">[${index}]</code>: <i style="word-break: break-all">${title}</i><br/>`
: `<code style="font-size: 90%; opacity: 0.6;">[${index}]</code> ${title}: <i style="word-break: break-all">${link}</i><br/>`,
)
.join(`\n`)
}
function transform(legend: string, text: string | null, title: string | null): string {
const options = legend.split(`-`)
for (const option of options) {
if (option === `alt` && text) {
return text
}
if (option === `title` && title) {
return title
}
}
return ``
}
export function initRenderer(opts: IOpts) {
const footnotes: [number, string, string][] = []
let footnoteIndex: number = 0
let styleMapping: ThemeStyles = buildTheme(opts)
let codeIndex: number = 0
let listIndex: number = 0
let isOrdered: boolean = false
function styles(tag: string, addition: string = ``): string {
return getStyles(styleMapping, tag, addition)
}
function styledContent(styleLabel: string, content: string, tagName?: string): string {
if (!content) {
return ``
}
const tag = tagName ?? styleLabel
return `<${tag} ${styles(styleLabel)}>${content}</${tag}>`
}
function addFootnote(title: string, link: string): number {
footnotes.push([++footnoteIndex, title, link])
return footnoteIndex
}
function reset(newOpts: IOpts): void {
footnotes.length = 0
footnoteIndex = 0
setOptions(newOpts)
}
function setOptions(newOpts: IOpts): void {
opts = { ...opts, ...newOpts }
styleMapping = buildTheme(opts)
}
const buildFootnotes = () => {
if (!footnotes.length) {
return ``
}
return (
styledContent(`h4`, `引用链接`)
+ styledContent(`footnotes`, buildFootnoteArray(footnotes), `p`)
)
}
const renderer: RendererObject = {
heading({ tokens, depth }: Tokens.Heading) {
const text = this.parser.parseInline(tokens)
const tag = `h${depth}`
return styledContent(tag, text)
},
paragraph({ tokens }: Tokens.Paragraph): string {
const text = this.parser.parseInline(tokens)
const isFigureImage = text.includes(`<figure`) && text.includes(`<img`)
const isEmpty = text.trim() === ``
if (isFigureImage || isEmpty) {
return text
}
return styledContent(`p`, text)
},
blockquote({ tokens }: Tokens.Blockquote): string {
let text = this.parser.parse(tokens)
text = text.replace(/<p.*?>/g, `<p ${styles(`blockquote_p`)}>`)
return styledContent(`blockquote`, text)
},
code({ text, lang = `` }: Tokens.Code): string {
if (lang.startsWith(`mermaid`)) {
clearTimeout(codeIndex)
codeIndex = setTimeout(() => {
mermaid.run()
}, 0) as any as number
return `<pre class="mermaid">${text}</pre>`
}
const langText = lang.split(` `)[0]
const language = hljs.getLanguage(langText) ? langText : `plaintext`
let highlighted = hljs.highlight(text, { language }).value
highlighted = highlighted
.replace(/\r\n/g, `<br/>`)
.replace(/\n/g, `<br/>`)
.replace(/(>[^<]+)|(^[^<]+)/g, str => str.replace(/\s/g, `&nbsp;`))
return `<pre class="hljs code__pre" ${styles(`code_pre`)}><code class="language-${lang}" ${styles(`code`)}>${highlighted}</code></pre>`
},
codespan({ text }: Tokens.Codespan): string {
return styledContent(`codespan`, text, `code`)
},
listitem(item: Tokens.ListItem): string {
const prefix = isOrdered ? `${listIndex + 1}. ` : ``
const content = item.tokens.map(t => (this[t.type as keyof Renderer] as <T>(token: T) => string)(t)).join(``)
return styledContent(`listitem`, `${prefix}${content}`, `li`)
},
list({ ordered, items }: Tokens.List): string {
const listItems = []
for (let i = 0; i < items.length; i++) {
isOrdered = ordered
listIndex = i
const item = items[i]
listItems.push(this.listitem(item))
}
const label = ordered ? `ol` : `ul`
return styledContent(label, listItems.join(``))
},
image({ href, title, text }: Tokens.Image): string {
const subText = styledContent(`figcaption`, transform(opts.legend, text, title))
const figureStyles = styles(`figure`)
const imgStyles = styles(`image`)
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>`
},
link({ href, title, text }: Tokens.Link): string {
if (href.startsWith(`https://mp.weixin.qq.com`)) {
return `<a href="${href}" title="${title || text}" ${styles(`wx_link`)}>${text}</a>`
}
if (href === text) {
return text
}
if (opts.status) {
const ref = addFootnote(title || text, href)
return `<span ${styles(`link`)}>${text}<sup>[${ref}]</sup></span>`
}
return styledContent(`link`, text, `span`)
},
strong({ tokens }: Tokens.Strong): string {
return styledContent(`strong`, this.parser.parseInline(tokens))
},
em({ tokens }: Tokens.Em): string {
return styledContent(`em`, this.parser.parseInline(tokens), `span`)
},
table({ header, rows }: Tokens.Table): string {
const headerRow = header
.map(cell => this.tablecell(cell))
.join(``)
const body = rows
.map((row) => {
const rowContent = row
.map(cell => this.tablecell(cell))
.join(``)
return styledContent(`tr`, rowContent)
})
.join(``)
return `
<section style="padding:0 8px; max-width: 100%; overflow: auto">
<table class="preview-table">
<thead ${styles(`thead`)}>${headerRow}</thead>
<tbody>${body}</tbody>
</table>
</section>
`
},
tablecell(token: Tokens.TableCell): string {
const text = this.parser.parseInline(token.tokens)
return styledContent(`td`, text)
},
hr(): string {
return styledContent(`hr`, ``)
},
}
marked.use({ renderer })
return {
buildAddition,
buildFootnotes,
setOptions,
reset,
}
}