feat: support Mermaid and Katex (#250)

---------

Co-authored-by: hoollyzhang <hoollyzhang@tencent.com>
This commit is contained in:
brzhang Group 2023-11-04 11:40:39 +08:00 committed by GitHub
parent 806c4c086d
commit 192c7878f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1290 additions and 34 deletions

1235
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
"form-data": "4.0.0",
"highlight.js": "^11.6.0",
"juice": "^8.0.0",
"katex": "^0.16.9",
"marked": "^4.0.18",
"minio": "7.0.33",
"node-fetch": "^3.2.10",

View File

@ -29,6 +29,9 @@
href="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/styles.css"
/>
<script src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/npm/prettify/r298/prettify.min.js"></script>
<!-- KaTeX CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous">
</head>
<body>
@ -39,5 +42,11 @@
<!-- built files will be auto injected -->
</body>
<script src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/main.js"></script>
<!-- 支持一下 mermaid -->
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
window.mermaid = mermaid;
</script>
</html>

View File

@ -1,5 +1,5 @@
/*
按Ctrl+F可格式化
按Ctrl/Command+F可格式化
*/
/* 一级标题样式 */
h1 {

View File

@ -54,6 +54,7 @@ export default {
value: `rgba(250, 81, 81, 1)`,
desc: `热情活泼`,
},
// { label: `微信绿`, value: `rgb(26, 173, 25,1)`, desc: `经典微信绿` },
],
codeThemeOption: [
{

View File

@ -1,6 +1,6 @@
import { Renderer } from "marked";
import hljs from 'highlight.js';
import hljs from "highlight.js";
import katex from "katex";
class WxRenderer {
constructor(opts) {
this.opts = opts;
@ -23,7 +23,7 @@ class WxRenderer {
}
}
let base_block = merge(base, {});
let base_block = merge(base, {});
for (let ele in themeTpl.block) {
if (themeTpl.block.hasOwnProperty(ele)) {
let style = themeTpl.block[ele];
@ -121,24 +121,37 @@ class WxRenderer {
return `<blockquote ${getStyles("blockquote")}>${text}</blockquote>`;
};
renderer.code = (text, lang) => {
lang = hljs.getLanguage(lang) ? lang : 'plaintext';
if (lang === "katex") {
const html = katex.renderToString(text);
return `${html}`;
}
if (lang.startsWith("mermaid")) {
setTimeout(() => {
window.mermaid?.run();
}, 0);
return `<center><pre class="mermaid">${text}</pre></center>`;
}
lang = hljs.getLanguage(lang) ? lang : "plaintext";
text = hljs.highlight(text, {language: lang}).value;
text = hljs.highlight(text, { language: lang }).value;
text = text.replace(/\r\n/g,"<br/>")
.replace(/\n/g,"<br/>")
.replace(/(>[^<]+)|(^[^<]+)/g, function(str) {
return str.replace(/\s/g, '&nbsp;')
});
text = text
.replace(/\r\n/g, "<br/>")
.replace(/\n/g, "<br/>")
.replace(/(>[^<]+)|(^[^<]+)/g, function (str) {
return str.replace(/\s/g, "&nbsp;");
});
return `<pre class="hljs code__pre" ${getStyles("code_pre")}><code class="prettyprint language-${lang}" ${getStyles("code")}>${text}</code></pre>`
return `<pre class="hljs code__pre" ${getStyles(
"code_pre"
)}><code class="prettyprint language-${lang}" ${getStyles(
"code"
)}>${text}</code></pre>`;
};
renderer.codespan = (text, lang) =>
`<code ${getStyles("codespan")}>${text}</code>`;
renderer.listitem = (text) =>
`<li ${getStyles(
"listitem"
)}><span><%s/></span>${text}</li>`;
`<li ${getStyles("listitem")}><span><%s/></span>${text}</li>`;
renderer.list = (text, ordered, start) => {
text = text.replace(/<\/*p .*?>/g, "").replace(/<\/*p>/g, "");

View File

@ -203,27 +203,27 @@ export default {
formatItems: [
{
label: `加粗`,
kbd: `Ctrl + B`,
kbd: `Ctrl/Command + B`,
emitArgs: [`addFormat`, `**`],
},
{
label: `斜体`,
kbd: `Ctrl + I`,
kbd: `Ctrl/Command + I`,
emitArgs: [`addFormat`, `*`],
},
{
label: `删除线`,
kbd: `Alt + Shift + U`,
kbd: `Ctrl/Command + D`,
emitArgs: [`addFormat`, `~~`],
},
{
label: `超链接`,
kbd: `Alt + Shift + K`,
kbd: `Ctrl/Command + K`,
emitArgs: [`addFormat`, `[`, `]()`],
},
{
label: `格式化`,
kbd: `Alt + Shift + L`,
kbd: `Ctrl/Command + F`,
emitArgs: [`formatContent`],
},
],

View File

@ -8,6 +8,10 @@ import DEFAULT_CONTENT from '@/assets/example/markdown.md'
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt'
import { setColor, formatDoc, formatCss } from '@/assets/scripts/util'
const defaultKeyMap = CodeMirror.keyMap[`default`]
const modPrefix =
defaultKeyMap === CodeMirror.keyMap[`macDefault`] ? `Cmd` : `Ctrl`
export const useStore = defineStore(`store`, {
state: () => ({
wxRenderer: null,
@ -88,9 +92,6 @@ export const useStore = defineStore(`store`, {
editorDom.value =
localStorage.getItem(`__editor_content`) || formatDoc(DEFAULT_CONTENT)
}
const defaultKeyMap = CodeMirror.keyMap[`default`]
const modPrefix =
defaultKeyMap === CodeMirror.keyMap[`macDefault`] ? `Cmd` : `Ctrl`
this.editor = CodeMirror.fromTextArea(editorDom, {
mode: `text/x-markdown`,
theme: `xq-light`,
@ -104,7 +105,7 @@ export const useStore = defineStore(`store`, {
localStorage.setItem(`__editor_content`, doc)
editor.setValue(doc)
},
[[`${modPrefix}-B`]]: function bold(editor) {
[`${modPrefix}-B`]: function bold(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`**${selected}**`)
},
@ -116,6 +117,10 @@ export const useStore = defineStore(`store`, {
const selected = editor.getSelection()
editor.replaceSelection(`*${selected}*`)
},
[`${modPrefix}-K`]: function italic(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`[${selected}]()`)
},
[`${modPrefix}-L`]: function code(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`\`${selected}\``)
@ -138,12 +143,12 @@ export const useStore = defineStore(`store`, {
matchBrackets: true,
autofocus: true,
extraKeys: {
'Ctrl-F': function autoFormat(editor) {
[`${modPrefix}-F`]: function autoFormat(editor) {
const doc = formatCss(editor.getValue(0))
localStorage.setItem(`__css_content`, doc)
editor.setValue(doc)
},
'Ctrl-S': function save(editor) {},
[`${modPrefix}-S`]: function save(editor) {},
},
})
},

View File

@ -1,11 +1,5 @@
<template>
<div
class="container"
:class="{ container_night: nightMode }"
@keydown.alt.shift.k="addFormat('[', ']()')"
@keydown.alt.shift.u="addFormat('~~')"
@keydown.ctrl.alt.l="formatContent()"
>
<div class="container" :class="{ container_night: nightMode }">
<el-container>
<el-header class="editor__header">
<editor-header