md-editor-v3
Version:
Markdown editor for vue3, developed in jsx and typescript, dark theme、beautify content by prettier、render articles directly、paste or clip the picture and upload it...
2,062 lines • 52.6 kB
JavaScript
import { useId as He, provide as x, computed as F, reactive as le, watch as E, onMounted as M, ref as z, inject as C, nextTick as W, shallowRef as ee, onBeforeUnmount as te, toRef as Me, defineComponent as de, createVNode as N, Fragment as Pe, h as Le } from "vue";
import { deepMerge as _e, deepClone as Oe, randomId as ie, debounce as Be } from "@vavt/util";
import { p as h, g as L, f as me, s as fe, a as je, b as Ne } from "./config.mjs";
import { b as y, U as De, C as ke, B as X, O as xe, E as Q, g as he, F as pe, h as ge, i as ve, H as ye, j as be, R as se, e as Ve, k as ue, d as Ge, f as ae, P as Ue, T as ze } from "./event-bus.mjs";
import { a as O, u as We, S as qe, c as Ke, z as Ze } from "./dom.mjs";
import Je from "@vavt/copy2clipboard";
import Xe from "markdown-it";
import Ye from "markdown-it-image-figures";
import Qe from "markdown-it-sub";
import et from "markdown-it-sup";
import { a as tt } from "./index5.mjs";
import nt from "medium-zoom";
const P = {
hljs: `${h}-hljs`,
hlcss: `${h}-hlCss`,
prettier: `${h}-prettier`,
prettierMD: `${h}-prettierMD`,
cropperjs: `${h}-cropper`,
croppercss: `${h}-cropperCss`,
screenfull: `${h}-screenfull`,
mermaidM: `${h}-mermaid-m`,
mermaid: `${h}-mermaid`,
katexjs: `${h}-katex`,
katexcss: `${h}-katexCss`,
echarts: `${h}-echarts`
}, Qt = (e, t, a) => {
const { editorId: n } = a, o = le({
// 是否已编译成html
buildFinished: !1,
// 存储当前最新的html
html: ""
});
E(
() => e.modelValue,
() => {
o.buildFinished = !1;
}
), M(() => {
y.on(n, {
name: X,
callback(m) {
o.buildFinished = !0, o.html = m;
}
}), y.on(n, {
name: xe,
callback() {
const m = new Promise((c) => {
if (o.buildFinished)
c(o.html);
else {
const u = (s) => {
c(s), y.remove(n, X, u);
};
y.on(n, {
name: X,
callback: u
});
}
});
e.onSave ? e.onSave(e.modelValue, m) : t.emit("onSave", e.modelValue, m);
}
});
});
}, Te = (e, {
editorId: t,
rootRef: a,
setting: n
}) => {
const o = L.editorExtensions.highlight, m = L.editorExtensionsAttrs.highlight;
x("editorId", t), x("rootRef", a), x(
"theme",
F(() => e.theme)
), x(
"language",
F(() => e.language)
), x(
"highlight",
F(() => {
const { js: u } = o, s = {
...me,
...o.css
}, { js: l, css: i = {} } = m || {}, r = e.codeStyleReverse && e.codeStyleReverseList.includes(e.previewTheme) ? "dark" : e.theme, d = s[e.codeTheme] ? s[e.codeTheme][r] : me.atom[r], f = s[e.codeTheme] && i[e.codeTheme] ? i[e.codeTheme][r] : i.atom ? i.atom[r] : {};
return {
js: {
src: u,
...l
},
css: {
href: d,
...f
}
};
})
), x("showCodeRowNumber", e.showCodeRowNumber);
const c = F(() => {
const u = {
...fe,
...L.editorConfig.languageUserDefined
};
return _e(
Oe(fe["en-US"]),
u[e.language] || {}
);
});
return x("usedLanguageText", c), x(
"previewTheme",
F(() => e.previewTheme)
), x(
"customIcon",
F(() => e.customIcon)
), x(
"setting",
F(() => n ? {
// setting是reactive,不转化是可以直接赋值的
...n
} : {
preview: !0,
htmlPreview: !1,
previewOnly: !1,
pageFullscreen: !1,
fullscreen: !1
})
), { editorId: t };
}, en = (e, t) => (x("tabWidth", e.tabWidth), x(
"disabled",
F(() => e.disabled)
), x(
"showToolbarName",
F(() => e.showToolbarName)
), x("noUploadImg", e.noUploadImg), x(
"tableShape",
F(() => e.tableShape)
), x("noPrettier", e.noPrettier), x(
"codeTheme",
F(() => e.codeTheme)
), x("updateSetting", t.updateSetting), x(
"catalogVisible",
F(() => t.catalogVisible.value)
), x("defToolbars", t.defToolbars), x(
"floatingToolbars",
F(() => e.floatingToolbars)
), Te(e, t)), tn = (e) => {
const { noPrettier: t, noUploadImg: a } = e, { editorExtensions: n, editorExtensionsAttrs: o } = L, m = t || n.prettier.prettierInstance, c = t || n.prettier.parserMarkdownInstance, u = a || n.cropper.instance;
M(() => {
if (!u) {
const { js: s = {}, css: l = {} } = o.cropper || {};
O("link", {
...l,
rel: "stylesheet",
href: n.cropper.css,
id: P.croppercss
}), O("script", {
...s,
src: n.cropper.js,
id: P.cropperjs
});
}
if (!m) {
const { standaloneJs: s = {} } = o.prettier || {};
O("script", {
...s,
src: n.prettier.standaloneJs,
id: P.prettier
});
}
if (!c) {
const { parserMarkdownJs: s = {} } = o.prettier || {};
O("script", {
...s,
src: n.prettier.parserMarkdownJs,
id: P.prettierMD
});
}
});
}, nn = (e, t, a) => {
const { editorId: n } = a;
M(() => {
y.on(n, {
name: Q,
callback: (o) => {
e.onError?.(o), t.emit("onError", o);
}
});
});
}, on = (e, t, a) => {
const { editorId: n } = a, o = le({
pageFullscreen: e.pageFullscreen,
fullscreen: !1,
preview: e.preview,
htmlPreview: e.preview ? !1 : e.htmlPreview,
previewOnly: !1
}), m = le({ ...o }), c = (l, i) => {
const r = i === void 0 ? !o[l] : i;
switch (l) {
case "preview": {
o.htmlPreview = !1, o.previewOnly = !1;
break;
}
case "htmlPreview": {
o.preview = !1, o.previewOnly = !1;
break;
}
case "previewOnly": {
r ? !o.preview && !o.htmlPreview && (o.preview = !0) : (m.preview || (o.preview = !1), m.htmlPreview || (o.htmlPreview = !1));
break;
}
}
m[l] = r, o[l] = r;
};
let u = "";
const s = () => {
o.pageFullscreen || o.fullscreen ? document.body.style.overflow = "hidden" : document.body.style.overflow = u;
};
return E(() => [o.pageFullscreen, o.fullscreen], s), M(() => {
y.on(n, {
name: De,
callback(l, i) {
const r = (d) => {
y.emit(n, se, "image", {
desc: "",
urls: d
}), i?.();
};
e.onUploadImg ? e.onUploadImg(l, r) : t.emit("onUploadImg", l, r);
}
}), u = document.body.style.overflow, s();
}), [o, c];
}, an = (e, t) => {
const { editorId: a } = t, n = z(!1);
return M(() => {
y.on(a, {
name: ke,
callback: (o) => {
o === void 0 ? n.value = !n.value : n.value = o;
}
});
}), n;
}, rn = (e, t, a) => {
const { editorId: n, catalogVisible: o, setting: m, updateSetting: c, codeRef: u } = a;
E(
() => m.pageFullscreen,
(l) => {
y.emit(n, he, l);
}
), E(
() => m.fullscreen,
(l) => {
y.emit(n, pe, l);
}
), E(
() => m.preview,
(l) => {
y.emit(n, ge, l);
}
), E(
() => m.previewOnly,
(l) => {
y.emit(n, ve, l);
}
), E(
() => m.htmlPreview,
(l) => {
y.emit(n, ye, l);
}
), E(o, (l) => {
y.emit(n, be, l);
});
const s = {
on(l, i) {
switch (l) {
case "pageFullscreen": {
y.on(n, {
name: he,
callback(r) {
i(r);
}
});
break;
}
case "fullscreen": {
y.on(n, {
name: pe,
callback(r) {
i(r);
}
});
break;
}
case "preview": {
y.on(n, {
name: ge,
callback(r) {
i(r);
}
});
break;
}
case "previewOnly": {
y.on(n, {
name: ve,
callback(r) {
i(r);
}
});
break;
}
case "htmlPreview": {
y.on(n, {
name: ye,
callback(r) {
i(r);
}
});
break;
}
case "catalog": {
y.on(n, {
name: be,
callback(r) {
i(r);
}
});
break;
}
}
},
togglePageFullscreen(l) {
c("pageFullscreen", l);
},
toggleFullscreen(l) {
y.emit(n, Ge, l);
},
togglePreview(l) {
c("preview", l);
},
togglePreviewOnly(l) {
c("previewOnly", l);
},
toggleHtmlPreview(l) {
c("htmlPreview", l);
},
toggleCatalog(l) {
y.emit(n, ke, l);
},
triggerSave() {
y.emit(n, xe);
},
insert(l) {
y.emit(n, se, "universal", { generate: l });
},
focus(l) {
u.value?.focus(l);
},
rerender() {
y.emit(n, ue);
},
getSelectedText() {
return u.value?.getSelectedText();
},
resetHistory() {
u.value?.resetHistory();
},
domEventHandlers(l) {
y.emit(n, Ve, l);
},
execCommand(l) {
y.emit(n, se, l);
},
getEditorView() {
return u.value?.getEditorView();
}
};
t.expose(s);
}, ot = (e) => {
const t = He();
return e.id || e.editorId || `${h}-${t}`;
}, at = (e, t, a) => {
const n = C("editorId"), o = C("rootRef"), m = C("usedLanguageText"), c = C("setting"), u = () => {
o.value.querySelectorAll(`#${n} .${h}-preview .${h}-code`).forEach((i) => {
let r = -1;
const d = i.querySelector(
`.${h}-copy-button:not([data-processed])`
);
d && (d.onclick = (f) => {
f.preventDefault(), clearTimeout(r);
const v = (i.querySelector("input:checked + pre code") || i.querySelector("pre code")).textContent, { text: p, successTips: T, failTips: b } = m.value.copyCode;
let $ = T;
Je(e.formatCopiedText(v || "")).catch(() => {
$ = b;
}).finally(() => {
d.dataset.isIcon ? d.dataset.tips = $ : d.textContent = $, r = window.setTimeout(() => {
d.dataset.isIcon ? d.dataset.tips = p : d.textContent = p;
}, 1500);
});
}, d.setAttribute("data-processed", "true"));
});
}, s = () => {
W(u);
}, l = (i) => {
i && W(u);
};
E([t, a], s), E(() => c.value.preview, l), E(() => c.value.htmlPreview, l), M(u);
}, rt = (e) => {
const t = C("editorId"), a = C("theme"), n = C("rootRef"), { editorExtensions: o, editorExtensionsAttrs: m, echartsConfig: c } = L;
let u = o.echarts.instance;
const s = ee(-1), l = () => {
!e.noEcharts && u && (s.value = s.value + 1);
};
E(
() => a.value,
() => {
l();
}
), M(() => {
if (e.noEcharts || u)
return;
const v = o.echarts.js;
O(
"script",
{
...m.echarts?.js,
src: v,
id: P.echarts,
onload() {
u = window.echarts, l();
}
},
"echarts"
);
});
let i = [], r = [], d = [];
const f = (v = !1) => {
if (!i.length) {
v && (r.forEach(($) => {
$.dispose?.();
}), d.forEach(($) => {
$.disconnect?.();
}), r = [], d = []);
return;
}
const p = [], T = [], b = [];
i.forEach(($, S) => {
const w = r[S], I = d[S];
if (v || !$ || !$.isConnected || (n?.value ? !n.value.contains($) : !1)) {
w?.dispose?.(), I?.disconnect?.();
return;
}
p.push($), w && T.push(w), I && b.push(I);
}), i = p, r = T, d = b;
}, g = () => {
f(), !e.noEcharts && u && Array.from(
n.value.querySelectorAll(
`#${t} div.${h}-echarts:not([data-processed])`
)
).forEach((p) => {
if (p.dataset.closed === "false")
return !1;
try {
const T = o.echarts.parseOption(p.innerText, {
editorId: t,
element: p
}), b = c(T), $ = u.init(p, a.value);
$.setOption(b), p.setAttribute("data-processed", ""), i.push(p), r.push($);
const S = new ResizeObserver(() => {
$.resize();
});
S.observe(p), d.push(S);
} catch (T) {
y.emit(t, Q, {
name: "echarts",
message: T?.message,
error: T
});
}
});
};
return te(() => {
f(!0);
}), { reRenderEcharts: s, replaceEcharts: g };
}, lt = (e) => {
const t = C("highlight"), a = ee(L.editorExtensions.highlight.instance);
return M(() => {
e.noHighlight || a.value || (O("link", {
...t.value.css,
rel: "stylesheet",
id: P.hlcss
}), O(
"script",
{
...t.value.js,
id: P.hljs,
onload() {
a.value = window.hljs;
}
},
"hljs"
));
}), E(
() => t.value.css,
() => {
e.noHighlight || L.editorExtensions.highlight.instance || We("link", {
...t.value.css,
rel: "stylesheet",
id: P.hlcss
});
}
), a;
}, it = (e) => {
const t = ee(L.editorExtensions.katex.instance);
return M(() => {
if (e.noKatex || t.value)
return;
const { editorExtensions: a, editorExtensionsAttrs: n } = L;
O(
"script",
{
...n.katex?.js,
src: a.katex.js,
id: P.katexjs,
onload() {
t.value = window.katex;
}
},
"katex"
), O("link", {
...n.katex?.css,
rel: "stylesheet",
href: a.katex.css,
id: P.katexcss
});
}), t;
};
class st {
constructor(t) {
this.options = t;
}
options;
cache = /* @__PURE__ */ new Map();
isExpired(t) {
return t.expiresAt <= Date.now();
}
deleteExpired(t, a) {
const n = a ?? this.cache.get(t);
return !n || !this.isExpired(n) ? !1 : (this.cache.delete(t), !0);
}
trim() {
for (const [t, a] of this.cache)
if (!this.deleteExpired(t, a))
break;
for (; this.cache.size > this.options.max; ) {
const t = this.cache.keys().next().value;
if (t === void 0)
break;
this.cache.delete(t);
}
}
get(t) {
const a = this.cache.get(t);
if (!(!a || this.deleteExpired(t, a)))
return this.cache.delete(t), this.cache.set(t, a), a.value;
}
set(t, a) {
this.cache.delete(t), this.cache.set(t, {
value: a,
expiresAt: Date.now() + this.options.ttl
}), this.trim();
}
clear() {
this.cache.clear();
}
}
const Y = new st({
max: 1e3,
// 缓存10分钟
ttl: 6e5
}), ct = (e) => {
const t = C("editorId"), a = C("theme"), n = C("rootRef"), { editorExtensions: o, editorExtensionsAttrs: m, mermaidConfig: c } = L;
let u = o.mermaid.instance;
const s = ee(-1), l = () => {
if (!e.noMermaid && u) {
const r = a.value === "dark" ? {
startOnLoad: !1,
theme: "dark"
} : {
startOnLoad: !1,
theme: "base",
themeVariables: {
background: "#ffffff",
primaryColor: "#ffffff",
primaryTextColor: "#1f2329",
primaryBorderColor: "#b7c0cc",
secondaryColor: "#f7f8fa",
tertiaryColor: "#f7f8fa",
lineColor: "#596273",
edgeLabelBackground: "#ffffff",
clusterBkg: "#ffffff",
clusterBorder: "#b7c0cc"
}
};
u.initialize(c(r)), s.value = s.value + 1;
}
};
return E(
() => a.value,
() => {
Y.clear(), l();
}
), M(() => {
if (e.noMermaid || u)
return;
const r = o.mermaid.js;
/\.mjs/.test(r) ? (O("link", {
...m.mermaid?.js,
rel: "modulepreload",
href: r,
id: P.mermaidM
}), import(
/* @vite-ignore */
/* webpackIgnore: true */
r
).then((d) => {
u = d.default, l();
}).catch((d) => {
y.emit(t, Q, {
name: "mermaid",
message: `Failed to load mermaid module: ${d.message}`,
error: d
});
})) : O(
"script",
{
...m.mermaid?.js,
src: r,
id: P.mermaid,
onload() {
u = window.mermaid, l();
}
},
"mermaid"
);
}), { reRenderRef: s, replaceMermaid: async () => {
if (!e.noMermaid && u) {
const r = n.value.querySelectorAll(
`div.${h}-mermaid`
), d = document.createElement("div"), f = document.body.offsetWidth > 1366 ? document.body.offsetWidth : 1366, g = document.body.offsetHeight > 768 ? document.body.offsetHeight : 768;
d.style.width = f + "px", d.style.height = g + "px", d.style.position = "fixed", d.style.zIndex = "-10000", d.style.top = "-10000";
let v = r.length;
v > 0 && document.body.appendChild(d), await Promise.allSettled(
Array.from(r).map((p) => (async (b) => {
if (b.dataset.closed === "false")
return !1;
const $ = b.innerText;
let S = Y.get($);
if (!S) {
const w = ie();
let I = { svg: "" };
try {
I = await u.render(w, $, d), S = await e.sanitizeMermaid(I.svg);
const k = document.createElement("p");
k.className = `${h}-mermaid`, k.setAttribute("data-processed", ""), k.setAttribute("data-content", $), k.innerHTML = S, k.children[0]?.removeAttribute("height"), Y.set($, k.innerHTML), b.dataset.line !== void 0 && (k.dataset.line = b.dataset.line), b.replaceWith(k);
} catch (k) {
y.emit(t, Q, {
name: "mermaid",
message: k.message,
error: k
});
}
--v === 0 && d.remove();
}
})(p))
);
}
} };
}, dt = (e, t) => {
t = t || {};
const a = 3, n = t.marker || "!", o = n.charCodeAt(0), m = n.length;
let c = "", u = "";
const s = (i, r, d, f, g) => {
const v = i[r];
return v.type === "admonition_open" ? i[r].attrPush([
"class",
`${h}-admonition ${h}-admonition-${v.info}`
]) : v.type === "admonition_title_open" && i[r].attrPush(["class", `${h}-admonition-title`]), g.renderToken(i, r, d);
}, l = (i) => {
const r = i.trim().split(" ", 2);
u = "", c = r[0], r.length > 1 && (u = i.substring(c.length + 2));
};
e.block.ruler.before(
"code",
"admonition",
(i, r, d, f) => {
let g, v, p, T = !1, b = i.bMarks[r] + i.tShift[r], $ = i.eMarks[r];
if (o !== i.src.charCodeAt(b))
return !1;
for (g = b + 1; g <= $ && n[(g - b) % m] === i.src[g]; g++)
;
const S = Math.floor((g - b) / m);
if (S !== a)
return !1;
g -= (g - b) % m;
const w = i.src.slice(b, g), I = i.src.slice(g, $);
if (l(I), f)
return !0;
for (v = r; v++, !(v >= d || (b = i.bMarks[v] + i.tShift[v], $ = i.eMarks[v], b < $ && i.sCount[v] < i.blkIndent)); )
if (o === i.src.charCodeAt(b) && !(i.sCount[v] - i.blkIndent >= 4)) {
for (g = b + 1; g <= $ && n[(g - b) % m] === i.src[g]; g++)
;
if (!(Math.floor((g - b) / m) < S) && (g -= (g - b) % m, g = i.skipSpaces(g), !(g < $))) {
T = !0;
break;
}
}
const k = i.parentType, R = i.lineMax;
return i.parentType = "root", i.lineMax = v, p = i.push("admonition_open", "div", 1), p.markup = w, p.block = !0, p.info = c, p.map = [r, v], u && (p = i.push("admonition_title_open", "p", 1), p.markup = w + " " + c, p.map = [r, v], p = i.push("inline", "", 0), p.content = u, p.map = [r, i.line - 1], p.children = [], p = i.push("admonition_title_close", "p", -1), p.markup = w + " " + c), i.md.block.tokenize(i, r + 1, v), p = i.push("admonition_close", "div", -1), p.markup = i.src.slice(b, g), p.block = !0, i.parentType = k, i.lineMax = R, i.line = v + (T ? 1 : 0), !0;
},
{
alt: ["paragraph", "reference", "blockquote", "list"]
}
), e.renderer.rules.admonition_open = s, e.renderer.rules.admonition_title_open = s, e.renderer.rules.admonition_title_close = s, e.renderer.rules.admonition_close = s;
}, ce = (e, t) => {
const a = e.attrs ? e.attrs.slice() : [];
return t.forEach((n) => {
const o = e.attrIndex(n[0]);
o < 0 ? a.push(n) : (a[o] = a[o].slice(), a[o][1] += ` ${n[1]}`);
}), a;
}, ut = (e) => Array.from(e).map(
(t) => /[A-Za-z0-9_-]/.test(t) ? t : `_${t.codePointAt(0).toString(16)}_`
).join(""), mt = (e, t) => {
const a = e.renderer.rules.fence, n = e.utils.unescapeAll, o = /\[(\w*)(?::([\w ]*))?\]/, m = /::(open|close)/, c = ut(t.editorId), u = (d) => d.info ? n(d.info).trim() : "", s = (d) => {
const f = u(d), [g = null, v = ""] = (o.exec(f) || []).slice(1);
return [g, v];
}, l = (d) => {
const f = u(d);
return f ? f.split(/(\s+)/g)[0] : "";
}, i = (d) => {
const f = d.info.match(m) || [], g = f[1] === "open" || f[1] !== "close" && t.codeFoldable && d.content.trim().split(`
`).length < t.autoFoldThreshold, v = f[1] || t.codeFoldable ? "details" : "div", p = f[1] || t.codeFoldable ? "summary" : "div";
return { open: g, tagContainer: v, tagHeader: p };
}, r = (d, f, g, v, p) => {
if (d[f].hidden)
return "";
const T = t.usedLanguageTextRef.value?.copyCode.text || "", b = t.customIconRef.value.copy, $ = e.utils.escapeHtml(T), S = b || $, w = !!b, I = `<span class="${h}-collapse-tips">${qe("collapse-tips", t.customIconRef.value)}</span>`, [k] = s(d[f]);
if (k === null) {
const { open: A, tagContainer: _, tagHeader: J } = i(d[f]), U = [["class", `${h}-code`]];
A && U.push(["open", ""]);
const Fe = {
attrs: ce(d[f], U)
};
d[f].info = d[f].info.replace(m, "");
const Re = a(d, f, g, v, p);
return `
<${_} ${p.renderAttrs(Fe)}>
<${J} class="${h}-code-head">
<div class="${h}-code-flag"><span></span><span></span><span></span></div>
<div class="${h}-code-action">
<span class="${h}-code-lang">${e.utils.escapeHtml(d[f].info.trim())}</span>
<span class="${h}-copy-button" data-tips="${$}"${w ? " data-is-icon=true" : ""}>${S}</span>
${t.extraTools instanceof Function ? t.extraTools({ lang: d[f].info.trim() }) : t.extraTools || ""}
${_ === "details" ? I : ""}
</div>
</${J}>
${Re}
</${_}>
`;
}
let R, B, V, j, q = "", K = "", Z = "";
const { open: ne, tagContainer: G, tagHeader: H } = i(d[f]), D = [["class", `${h}-code`]];
ne && D.push(["open", ""]);
const oe = {
attrs: ce(d[f], D)
};
for (let A = f; A < d.length && (R = d[A], [B, V] = s(R), B === k); A++) {
R.info = R.info.replace(o, "").replace(m, ""), R.hidden = !0;
const _ = `${h}-codetab-${c}-${f}-${A - f}`;
j = A - f > 0 ? "" : "checked", q += `
<li>
<input
type="radio"
id="label-${h}-codetab-label-1-${c}-${f}-${A - f}"
name="${h}-codetab-label-${c}-${f}"
class="${_}"
${j}
>
<label
for="label-${h}-codetab-label-1-${c}-${f}-${A - f}"
onclick="this.getRootNode().querySelectorAll('.${_}').forEach(e => e.click())"
>
${e.utils.escapeHtml(V || l(R))}
</label>
</li>`, K += `
<div role="tabpanel">
<input
type="radio"
name="${h}-codetab-pre-${c}-${f}"
class="${_}"
${j}
role="presentation">
${a(d, A, g, v, p)}
</div>`, Z += `
<input
type="radio"
name="${h}-codetab-lang-${c}-${f}"
class="${_}"
${j}
role="presentation">
<span class=${h}-code-lang role="note">${e.utils.escapeHtml(l(R))}</span>`;
}
return `
<${G} ${p.renderAttrs(oe)}>
<${H} class="${h}-code-head">
<div class="${h}-code-flag">
<ul class="${h}-codetab-label" role="tablist">${q}</ul>
</div>
<div class="${h}-code-action">
<span class="${h}-codetab-lang">${Z}</span>
<span class="${h}-copy-button" data-tips="${$}"${w ? " data-is-icon=true" : ""}>${S}</span>
${t.extraTools instanceof Function ? t.extraTools({ lang: d[f].info.trim() }) : t.extraTools || ""}
${G === "details" ? I : ""}
</div>
</${H}>
${K}
</${G}>
`;
};
e.renderer.rules.fence = r, e.renderer.rules.code_block = r;
}, ft = (e, t) => {
const a = e.renderer.rules.fence.bind(e.renderer.rules);
e.renderer.rules.fence = (n, o, m, c, u) => {
const s = n[o], l = s.content.trim();
if (s.info === "echarts") {
if (s.attrSet("class", `${h}-echarts`), s.attrSet("data-echarts-theme", t.themeRef.value), s.map && s.level === 0) {
const i = s.map[1] - 1, d = !!c.srcLines[i]?.trim()?.startsWith("```");
s.attrSet("data-closed", `${d}`), s.attrSet("data-line", String(s.map[0]));
}
return `<div ${u.renderAttrs(s)} style="width: 100%; aspect-ratio: 4 / 3;">${e.utils.escapeHtml(l)}</div>`;
}
return a(n, o, m, c, u);
};
}, ht = (e, t) => {
e.renderer.rules.heading_open = (a, n) => {
const o = a[n], m = a[n + 1].children?.reduce((u, s) => u + (["text", "code_inline", "math_inline"].includes(s.type) && s.content || ""), "") || "", c = o.markup.length;
return t.headsRef.value.push({
text: m,
level: c,
line: o.map[0],
currentToken: o,
nextToken: a[n + 1]
}), o.map && o.level === 0 && o.attrSet(
"id",
t.mdHeadingId({
text: m,
level: c,
index: t.headsRef.value.length,
currentToken: o,
nextToken: a[n + 1]
})
), e.renderer.renderToken(a, n, t);
}, e.renderer.rules.heading_close = (a, n, o, m, c) => c.renderToken(a, n, o);
}, $e = {
block: [
{ open: "$$", close: "$$" },
{ open: "\\[", close: "\\]" }
],
inline: [
{ open: "$$", close: "$$" },
{ open: "$", close: "$" },
{ open: "\\[", close: "\\]" },
{ open: "\\(", close: "\\)" }
]
}, pt = (e) => (t, a) => {
const n = e.delimiters;
for (const o of n) {
if (!t.src.startsWith(o.open, t.pos))
continue;
const m = t.pos + o.open.length;
let c = m;
for (; (c = t.src.indexOf(o.close, c)) !== -1; ) {
let u = 0, s = c - 1;
for (; s >= 0 && t.src[s] === "\\"; )
u++, s--;
if (u % 2 === 0)
break;
c += o.close.length;
}
if (c !== -1) {
if (c - m === 0)
return a || (t.pending += o.open + o.close), t.pos = c + o.close.length, !0;
if (!a) {
const u = t.push("math_inline", "math", 0);
u.markup = o.open, u.content = t.src.slice(m, c);
}
return t.pos = c + o.close.length, !0;
}
}
return !1;
}, gt = (e) => (t, a, n, o) => {
const m = e.delimiters, c = t.bMarks[a] + t.tShift[a], u = t.eMarks[a], s = (l, i, r) => {
t.line = i;
const d = t.push("math_block", "math", 0);
return d.block = !0, d.content = l, d.map = [a, t.line], d.markup = r, !0;
};
for (const l of m) {
const i = c;
if (t.src.slice(i, i + l.open.length) !== l.open)
continue;
const r = i + l.open.length, d = t.src.slice(r, u).trim(), f = d === "", g = d === l.close, v = d.endsWith(l.close);
if (!f && !g && !v)
continue;
if (o)
return !0;
if (g)
return s("", a + 1, l.open);
if (!f && v) {
const w = d.slice(0, -l.close.length);
return s(w, a + 1, l.open);
}
let p = a + 1, T = !1, b = "";
for (; p < n; p++) {
const w = t.bMarks[p] + t.tShift[p], I = t.eMarks[p];
if (w < I && t.tShift[p] < t.blkIndent)
break;
if (t.src.slice(w, I).trim().endsWith(l.close)) {
const R = t.src.slice(0, I).lastIndexOf(l.close);
b = t.src.slice(w, R), T = !0;
break;
}
}
if (!T)
continue;
const S = t.getLines(a + 1, p, t.tShift[a], !0) + (b.trim() ? b : "");
return s(S, p + 1, l.open);
}
return !1;
}, vt = (e, { katexRef: t, inlineDelimiters: a, blockDelimiters: n }) => {
const o = (u, s, l, i, r = !1) => {
const d = {
attrs: ce(u, [["class", s]])
}, f = i.renderAttrs(d);
if (!t.value)
return `<${l} ${f}>${u.content}</${l}>`;
const g = t.value.renderToString(
u.content,
L.katexConfig({
throwOnError: !1,
displayMode: r
})
);
return `<${l} ${f} data-processed>${g}</${l}>`;
}, m = (u, s, l, i, r) => o(u[s], `${h}-katex-inline`, "span", r), c = (u, s, l, i, r) => o(u[s], `${h}-katex-block`, "p", r, !0);
e.inline.ruler.before(
"escape",
"math_inline",
pt({
delimiters: a || $e.inline
})
), e.block.ruler.after(
"blockquote",
"math_block",
gt({
delimiters: n || $e.block
}),
{
alt: ["paragraph", "reference", "blockquote", "list"]
}
), e.renderer.rules.math_inline = m, e.renderer.rules.math_block = c;
}, yt = (e, t) => {
const a = e.renderer.rules.fence.bind(e.renderer.rules);
e.renderer.rules.fence = (n, o, m, c, u) => {
const s = n[o], l = s.content.trim();
if (s.info === "mermaid") {
if (s.attrSet("class", `${h}-mermaid`), s.attrSet("data-mermaid-theme", t.themeRef.value), s.map && s.level === 0) {
const r = s.map[1] - 1, f = !!c.srcLines[r]?.trim()?.startsWith("```");
s.attrSet("data-closed", `${f}`), s.attrSet("data-line", String(s.map[0]));
}
const i = Y.get(l);
return i ? (s.attrSet("data-processed", ""), s.attrSet("data-content", l), `<p ${u.renderAttrs(s)}>${i}</p>`) : `<div ${u.renderAttrs(s)}>${e.utils.escapeHtml(l)}</div>`;
}
return a(n, o, m, c, u);
};
}, we = (e, t, a) => {
const n = e.attrIndex(t), o = [t, a];
n < 0 ? e.attrPush(o) : (e.attrs = e.attrs || [], e.attrs[n] = o);
}, bt = (e) => e.type === "inline", $t = (e) => e.type === "paragraph_open", wt = (e) => e.type === "list_item_open", Ct = (e) => e.content.indexOf("[ ] ") === 0 || e.content.indexOf("[x] ") === 0 || e.content.indexOf("[X] ") === 0, Et = (e, t) => bt(e[t]) && $t(e[t - 1]) && wt(e[t - 2]) && Ct(e[t]), kt = (e, t) => {
const a = e[t].level - 1;
for (let n = t - 1; n >= 0; n--)
if (e[n].level === a)
return n;
return -1;
}, xt = (e) => {
const t = new e("html_inline", "", 0);
return t.content = "<label>", t;
}, Tt = (e) => {
const t = new e("html_inline", "", 0);
return t.content = "</label>", t;
}, St = (e, t, a) => {
const n = new a("html_inline", "", 0);
return n.content = '<label class="task-list-item-label" for="' + t + '">' + e + "</label>", n.attrs = [["for", t]], n;
}, It = (e, t, a) => {
const n = new t("html_inline", "", 0), o = a.enabled ? " " : ' disabled="" ';
return e.content.indexOf("[ ] ") === 0 ? n.content = '<input class="task-list-item-checkbox"' + o + 'type="checkbox">' : (e.content.indexOf("[x] ") === 0 || e.content.indexOf("[X] ") === 0) && (n.content = '<input class="task-list-item-checkbox" checked=""' + o + 'type="checkbox">'), n;
}, At = (e, t, a) => {
if (e.children = e.children || [], e.children.unshift(It(e, t, a)), e.children[1].content = e.children[1].content.slice(3), e.content = e.content.slice(3), a.label)
if (a.labelAfter) {
e.children.pop();
const n = "task-item-" + Math.ceil(Math.random() * (1e4 * 1e3) - 1e3);
e.children[0].content = e.children[0].content.slice(0, -1) + ' id="' + n + '">', e.children.push(St(e.content, n, t));
} else
e.children.unshift(xt(t)), e.children.push(Tt(t));
}, Ft = (e, t = {}) => {
e.core.ruler.after("inline", "github-task-lists", (a) => {
const n = a.tokens;
for (let o = 2; o < n.length; o++)
Et(n, o) && (At(n[o], a.Token, t), we(
n[o - 2],
"class",
"task-list-item" + (t.enabled ? " enabled" : " ")
), we(n[kt(n, o - 2)], "class", "contains-task-list"));
});
}, Rt = (e) => {
e.core.ruler.push("init-line-number", (t) => (t.tokens.forEach((a) => {
a.map && (a.attrs || (a.attrs = []), a.attrs.push(["data-line", a.map[0].toString()]));
}), !0));
}, Ht = (e, t) => {
const { editorConfig: a, markdownItConfig: n, markdownItPlugins: o, editorExtensions: m } = L, c = C("editorId"), u = C("language"), s = C(
"usedLanguageText"
), l = C("showCodeRowNumber"), i = C("theme"), r = C("customIcon"), d = C("rootRef"), f = C("setting"), g = z([]), v = lt(e), p = it(e), { reRenderRef: T, replaceMermaid: b } = ct(e), { reRenderEcharts: $, replaceEcharts: S } = rt(e), w = Xe({
html: !0,
breaks: !0,
linkify: !0
});
n(w, {
editorId: c
});
const I = [
{
type: "image",
plugin: Ye,
options: { figcaption: !0, classes: "md-zoom" }
},
{
type: "admonition",
plugin: dt,
options: {}
},
{
type: "taskList",
plugin: Ft,
options: {}
},
{
type: "heading",
plugin: ht,
options: { mdHeadingId: e.mdHeadingId, headsRef: g }
},
{
type: "code",
plugin: mt,
options: {
editorId: c,
usedLanguageTextRef: s,
// showCodeRowNumber,
codeFoldable: e.codeFoldable,
autoFoldThreshold: e.autoFoldThreshold,
customIconRef: r
}
},
{
type: "sub",
plugin: Qe,
options: {}
},
{
type: "sup",
plugin: et,
options: {}
}
];
e.noKatex || I.push({
type: "katex",
plugin: vt,
options: { katexRef: p }
}), e.noMermaid || I.push({
type: "mermaid",
plugin: yt,
options: { themeRef: i }
}), e.noEcharts || I.push({
type: "echarts",
plugin: ft,
options: { themeRef: i }
}), o(I, {
editorId: c
}).forEach((H) => {
w.use(H.plugin, H.options);
});
const k = w.options.highlight;
w.set({
highlight: (H, D, oe) => {
if (k) {
const U = k(H, D, oe);
if (U)
return U;
}
let A;
!e.noHighlight && v.value ? v.value.getLanguage(D) ? A = v.value.highlight(H, {
language: D,
ignoreIllegals: !0
}).value : A = v.value.highlightAuto(H).value : A = w.utils.escapeHtml(H);
const _ = w.utils.escapeHtml(D), J = l ? tt(
A.replace(/^\n+|\n+$/g, ""),
H.replace(/^\n+|\n+$/g, "")
) : `<span class="${h}-code-block">${A.replace(/^\n+|\n+$/g, "")}</span>`;
return `<pre><code class="language-${_}" language="${_}">${J}</code></pre>`;
}
}), Rt(w);
const R = z(`_article-key_${ie()}`), B = z(
e.sanitize(
w.render(e.modelValue, {
srcLines: e.modelValue.split(`
`)
})
)
);
let V = () => {
}, j = () => {
};
const q = () => {
const H = d.value?.querySelectorAll(
`#${c} p.${h}-mermaid:not([data-closed=false])`
);
j(), j = Ke(H, {
customIcon: r.value
}), m.mermaid?.enableZoom && (V(), V = Ze(H, {
customIcon: r.value
}));
}, K = () => {
y.emit(c, X, B.value), e.onHtmlChanged(B.value), e.onGetCatalog(g.value), y.emit(c, ae, g.value), W(() => {
b().then(q), S();
});
}, Z = () => {
g.value = [], B.value = e.sanitize(
w.render(e.modelValue, {
srcLines: e.modelValue.split(`
`)
})
);
}, ne = F(() => (e.noKatex || !!p.value) && (e.noHighlight || !!v.value));
let G = -1;
return E([Me(e, "modelValue"), ne, T, u], () => {
G = window.setTimeout(
() => {
Z();
},
t ? 0 : a.renderDelay
);
}), E(
() => f.value.preview,
() => {
f.value.preview && W(() => {
b().then(q), S(), y.emit(c, ae, g.value);
});
}
), E([B, $], () => {
K();
}), M(K), M(() => {
y.on(c, {
name: Ue,
callback() {
y.emit(c, ae, g.value);
}
}), y.on(c, {
name: ue,
callback: () => {
R.value = `_article-key_${ie()}`, Z();
}
});
}), te(() => {
V(), j(), clearTimeout(G);
}), { html: B, key: R };
}, Mt = (e, t) => {
const a = C("editorId"), n = C("setting"), { noImgZoomIn: o } = e, m = Be(() => {
const c = document.querySelectorAll(
`#${a}-preview img:not(.not-zoom):not(.medium-zoom-image)`
);
c.length !== 0 && nt(c, {
background: "#00000073"
});
});
M(async () => {
!o && n.value.preview && await m();
}), E([t, () => n.value.preview], async () => {
!o && n.value.preview && await m();
});
}, Ce = {
checked: {
regexp: /- \[x\]/,
value: "- [ ]"
},
unChecked: {
regexp: /- \[\s\]/,
value: "- [x]"
}
}, Pt = (e, t) => {
const a = C("editorId"), n = C("rootRef");
let o = () => {
};
const m = () => {
if (!n.value)
return !1;
const c = n.value.querySelectorAll(".task-list-item.enabled"), u = (s) => {
s.preventDefault();
const l = s.target.checked ? "unChecked" : "checked", i = s.target.parentElement?.dataset.line;
if (!i)
return;
const r = Number(i), d = e.modelValue.split(`
`), f = d[Number(r)].replace(
Ce[l].regexp,
Ce[l].value
);
e.previewOnly ? (d[Number(r)] = f, e.onChange(d.join(`
`))) : y.emit(a, ze, r + 1, f);
};
c.forEach((s) => {
s.addEventListener("click", u);
}), o = () => {
c.forEach((s) => {
s.removeEventListener("click", u);
});
};
};
te(() => {
o();
}), E(
[t],
() => {
o(), W(m);
},
{
immediate: !0
}
);
}, Lt = (e, t, a) => {
const n = C("setting"), o = () => {
W(() => {
e.onRemount?.();
});
}, m = (c) => {
c && o();
};
E([t, a], o), E(() => n.value.preview, m), E(() => n.value.htmlPreview, m), M(o);
}, Se = {
modelValue: {
type: String,
default: ""
},
onChange: {
type: Function,
default: () => {
}
},
onHtmlChanged: {
type: Function,
default: () => {
}
},
onGetCatalog: {
type: Function,
default: () => {
}
},
mdHeadingId: {
type: Function,
default: () => ""
},
noMermaid: {
type: Boolean,
default: !1
},
sanitize: {
type: Function,
default: (e) => e
},
// 不使用该函数功能
noKatex: {
type: Boolean,
default: !1
},
formatCopiedText: {
type: Function,
default: (e) => e
},
noHighlight: {
type: Boolean,
default: !1
},
previewOnly: {
type: Boolean,
default: !1
},
noImgZoomIn: {
type: Boolean
},
sanitizeMermaid: {
type: Function
},
codeFoldable: {
type: Boolean
},
autoFoldThreshold: {
type: Number
},
onRemount: {
type: Function
},
noEcharts: {
type: Boolean
},
previewComponent: {
type: [Object, Function],
default: void 0
}
}, ln = {
...Se,
updateModelValue: {
type: Function,
default: () => {
}
},
placeholder: {
type: String,
default: ""
},
scrollAuto: {
type: Boolean
},
autofocus: {
type: Boolean
},
readonly: {
type: Boolean
},
maxlength: {
type: Number
},
autoDetectCode: {
type: Boolean
},
/**
* 输入框失去焦点时触发事件
*/
onBlur: {
type: Function,
default: () => {
}
},
/**
* 输入框获得焦点时触发事件
*/
onFocus: {
type: Function,
default: () => {
}
},
completions: {
type: Array
},
onInput: {
type: Function
},
onDrop: {
type: Function,
default: () => {
}
},
inputBoxWidth: {
type: String
},
oninputBoxWidthChange: {
type: Function
},
transformImgUrl: {
type: Function,
default: (e) => e
},
catalogLayout: {
type: String
},
catalogMaxDepth: {
type: Number
}
}, Ee = (e) => {
const a = new DOMParser().parseFromString(e, "text/html");
return Array.from(a.body.childNodes);
}, _t = (e, t) => e.nodeType !== t.nodeType ? !1 : e.nodeType === Node.TEXT_NODE || e.nodeType === Node.COMMENT_NODE ? e.textContent === t.textContent : e.nodeType === Node.ELEMENT_NODE ? e.outerHTML === t.outerHTML : e.isEqualNode ? e.isEqualNode(t) : !1, Ot = /* @__PURE__ */ de({
name: "UpdateOnDemand",
props: {
id: {
type: String,
required: !0
},
class: {
type: [String, Array, Object],
required: !0
},
html: {
type: String,
required: !0
}
},
setup(e) {
const t = z(), a = e.html, n = (o, m) => {
if (!t.value) return;
const c = t.value, u = Array.from(c.childNodes), s = Math.min(o.length, m.length);
let l = -1;
for (let r = 0; r < s; r++)
if (!_t(o[r], m[r])) {
l = r;
break;
}
if (l === -1)
if (m.length > o.length)
l = o.length;
else if (o.length > m.length)
l = m.length;
else
return;
const i = Math.min(l, u.length);
for (let r = u.length - 1; r >= i; r--)
u[r].remove();
for (let r = l; r < o.length; r++)
c.appendChild(o[r].cloneNode(!0));
};
return E(() => e.html, (o, m) => {
const c = Ee(o), u = Ee(m || "");
n(c, u);
}), () => N("div", {
id: e.id,
class: e.class,
innerHTML: a,
ref: t
}, null);
}
}), Bt = /* @__PURE__ */ de({
name: "ContentPreview",
props: Se,
setup(e) {
const t = C("editorId"), a = C("setting"), n = C("previewTheme"), o = C("showCodeRowNumber"), {
html: m,
key: c
} = Ht(e, e.previewOnly);
at(e, m, c), Mt(e, m), Pt(e, m), Lt(e, m, c);
const u = F(() => [`${h}-preview`, `${n?.value}-theme`, o && `${h}-scrn`].filter(Boolean)), s = () => {
const l = `${t}-preview`;
return e.previewComponent ? Le(e.previewComponent, {
key: c.value,
html: m.value,
id: l,
class: u.value
}) : N(Ot, {
key: c.value,
html: m.value,
id: l,
class: u.value
}, null);
};
return () => N(Pe, null, [a.value.preview && (e.previewOnly ? s() : N("div", {
id: `${t}-preview-wrapper`,
class: `${h}-preview-wrapper`,
key: "content-preview-wrapper"
}, [s()])), a.value.htmlPreview && N("div", {
id: `${t}-html-wrapper`,
class: `${h}-preview-wrapper`,
key: "html-preview-wrapper"
}, [N("div", {
class: `${h}-html`
}, [m.value])])]);
}
}), jt = ({ text: e }) => e, Ie = {
/**
* markdown content.
*
* @default ''
*/
modelValue: {
type: String,
default: ""
},
/**
* input回调事件
*/
onChange: {
type: Function,
default: void 0
},
/**
* 主题,支持light和dark
*
* @default 'light'
*/
theme: {
type: String,
default: "light"
},
/**
* 外层类名
*
* @default ''
*/
class: {
type: String,
default: ""
},
/**
* 预设语言名称
*
* @default 'zh-CN'
*/
language: {
type: String,
default: "zh-CN"
},
/**
* html变化事件
*/
onHtmlChanged: {
type: Function,
default: void 0
},
/**
* 获取目录结构
*/
onGetCatalog: {
type: Function,
default: void 0
},
/**
* 编辑器唯一标识
*
* @default 'md-editor-v3'
* @deprecated 5.x版本开始使用 id 替换
*/
editorId: {
type: String,
default: void 0
},
/**
* 5.x版本开始 editorId 的替换
*
* @default 'md-editor-v3'
*/
id: {
type: String,
default: void 0
},
/**
* 预览中代码是否显示行号
*
* @default true
*/
showCodeRowNumber: {
type: Boolean,
default: !0
},
/**
* 预览内容样式
*
* @default 'default'
*/
previewTheme: {
type: String,
default: "default"
},
/**
* 编辑器样式
*/
style: {
type: Object,
default: () => ({})
},
/**
* 标题的id生成方式
*
* @default (text: string) => text
*/
mdHeadingId: {
type: Function,
default: jt
},
/**
*
* 不能保证文本正确的情况,在marked编译md文本后通过该方法处理
* 推荐DOMPurify、sanitize-html
*
* @default (text: string) => text
*/
sanitize: {
type: Function,
default: (e) => e
},
/**
* 不使用该mermaid
*
* @default false
*/
noMermaid: {
type: Boolean,
default: !1
},
/**
* 不使用katex
*
* @default false
*/
noKatex: {
type: Boolean,
default: !1
},
/**
* 代码主题
*
* @default 'atom'
*/
codeTheme: {
type: String,
default: "atom"
},
/**
* 复制代码格式化方法
*
* @default (text) => text
*/
formatCopiedText: {
type: Function,
default: (e) => e
},
/**
* 某些预览主题的代码模块背景是暗色系
* 将这个属性设置为true,会自动在该主题下的light模式下使用暗色系的代码风格
*
* @default true
*/
codeStyleReverse: {
type: Boolean,
default: !0
},
/**
* 需要自动调整的预览主题
*
* @default ['default', 'mk-cute']
*/
codeStyleReverseList: {
type: Array,
default: ["default", "mk-cute"]
},
noHighlight: {
type: Boolean,
default: !1
},
/**
* 是否关闭编辑器默认的放大缩小功能
*/
noImgZoomIn: {
type: Boolean,
default: !1
},
/**
* 自定义的图标
*/
customIcon: {
type: Object,
default: {}
},
sanitizeMermaid: {
type: Function,
default: (e) => Promise.resolve(e)
},
/**
* 是否开启折叠代码功能
* 不开启会使用div标签替代details标签
*
* @default true
*/
codeFoldable: {
type: Boolean,
default: !0
},
/**
* 触发自动折叠代码的行数阈值
*
* @default 30
*/
autoFoldThreshold: {
type: Number,
default: 30
},
/**
* 内容重新挂载事件
*
* 相比起onHtmlChanged,onRemount会在重新挂载后触发
*/
onRemount: {
type: Function,
default: void 0
},
/**
* 不使用 echarts
*/
noEcharts: {
type: Boolean,
default: !1
},
previewComponent: {
type: [Object, Function],
default: void 0
}
}, sn = {
...Ie,
/**
* input回调事件
*/
onSave: {
type: Function,
default: void 0
},
/**
* 上传图片事件
*/
onUploadImg: {
type: Function,
default: void 0
},
/**
* 是否页面内全屏
*
* @default false
*/
pageFullscreen: {
type: Boolean,
default: !1
},
/**
* 是否展开预览
*
* @default true
*/
preview: {
type: Boolean,
default: !0
},
/**
* 是否展开html预览
*
* @default false
*/
htmlPreview: {
type: Boolean,
default: !1
},
/**
* 仅预览模式,不显示toolbar和编辑框
*
* @4.0.0开始移除该设置,使用组件MdPreview替换
*
* @default false
*/
// previewOnly: {
// type: Boolean as PropType<boolean>,
// default: false
// },
/**
* 工具栏选择显示
*
* @default allToolbar
*/
toolbars: {
type: Array,
default: Ne
},
/**
* 浮动工具栏
*
* @version 6.0.0
* @default []
*/
floatingToolbars: {
type: Array,
default: []
},
/**
* 工具栏选择不显示
*
* @default []
*/
toolbarsExclude: {
type: Array,
default: []
},
/**
* 格式化md
*
* @default true
*/
noPrettier: {
type: Boolean,
default: !1
},
/**
* 一个tab等于空格数
*
* @default 2
*/
tabWidth: {
type: Number,
default: 2
},
/**
* 表格预设格子数
*
* 也可以是[6, 4, 10, 8]
*
* @default [6, 4]
*/
tableShape: {
type: Array,
default: [6, 4]
},
/**
* 空提示
*
* @default ''
*/
placeholder: {
type: String,
default: ""
},
/**
* 自定义的工具栏列表
*/
defToolbars: {
type: [String, Object],
default: void 0
},
/**
* 内部错误捕获
*/
onError: {
type: Function,
default: void 0
},
/**
* 页脚列表显示顺序
*/
footers: {
type: Array,
default: je
},
/**
* 是否默认激活输入框和预览框同步滚动
*
* @default true
*/
scrollAuto: {
type: Boolean,
default: !0
},
/**
* 自定义的也叫工具组件列表
*/
defFooters: {
type: [String, Object],
default: void 0
},
/**
* 是否禁用上传图片
*
* @default false
*/
noUploadImg: {
type: Boolean,
default: !1
},
/**
* 文本区域自动获得焦点
*
* @default false
*/
autoFocus: {
type: Boolean,
default: !1
},
/**
* 禁用文本区域
*
* @default false
*/
disabled: {
type: Boolean,
default: !1
},
/**
* 文本区域为只读
*
* @default false
*/
readOnly: {
type: Boolean,
default: !1
},
/**
* 文本区域允许的最大字符数
*/
maxLength: {
type: Number,
default: void 0
},
/**
* 是否启用自动识别粘贴代码类别
* 目前支持 vscode 复制的代码识别
*
* @default false
*/
autoDetectCode: {
type: Boolean,
default: !1
},
/**
* 输入框失去焦点时触发事件
*/
onBlur: {
type: Function,
default: void 0
},
/**
* 输入框获得焦点时触发事件
*/
onFocus: {
type: Function,
default: void 0
},
/**
* @codemirror/autocomplete匹配关键词的方法列表
*
* 它会被像下面这样嵌入编辑器
*
* import { autocompletion } from '@codemirror/autocomplete';
* autocompletion({
* override: [...completions]
* })
*/
completions: {
type: Array,
default: void 0
},
/**
* 是否在工具栏下面显示对应的文字名称
*
* @default false
*/
showToolbarName: {
type: Boolean,
default: !1
},
/**
* 字符输入事件
*/
onInput: {
type: Function,
default: void 0
},
onDrop: {
type: Function,
default: void 0
},
/**
* 输入框的默认宽度
*
* @example '100px'/'50%'
* @default '50%
*/
inputBoxWidth: {
type: String,
default: "50%"
},
/**
* 输入框宽度变化事件
*/
oninputBoxWidthChange: {
type: Function,
default: void 0
},
/**
* 替换粘贴的图片链接
*
* @param t 图片链接
* @returns
*/
transformImgUrl: {
type: Function,
default: (e) => e
},
/**
* 内置的目录显示的状态
*
* 'fixed': 悬浮在内容上方
* 'flat': 展示在右侧
*
* \>=5.3.0
*
* @default 'fixed'
*/
catalogLayout: {
type: String,
default: "fixed"
},
/**
* 控制最大显示的目录层级
*/
catalogMaxDepth: {
type: Number,
default: void 0
}
}, Ae = [
"onHtmlChanged",
"onGetCatalog",
"onChange",
"onRemount",
"update:modelValue"
], cn = [
...Ae,
"onSave",
"onUploadImg",
"onError",
"onBlur",
"onFocus",
"onInput",
"onDrop",
"oninputBoxWidthChange"
], Nt = (e, t, a) => {
const { editorId: n } = a, o = {
rerender() {
y.emit(n, ue);
}
};
t.expose(o);
}, re = /* @__PURE__ */ de({
name: "MdPreview",
props: Ie,
emits: Ae,
setup(e, t) {
const {
noKatex: a,
noMermaid: n,
noHighlight: o
} = e, m = z(), c = ot(e);
Te(e, {
rootRef: m,
editorId: c
}), Nt(e, t, {
editorId: c
}), te(() => {
y.clear(c);
});
const u = (r) => {