@vuux/editor
Version:
Vue Nuxt 富文本编辑器
523 lines (522 loc) • 15.7 kB
JavaScript
import { _defaults as A } from "./defaults.mjs";
import { rtrim as b, splitCells as B, findClosingBracket as $ } from "./helpers.mjs";
const C = (k, n, e, t, s) => {
const i = n.href, l = n.title || null, o = k[1].replace(s.other.outputLinkReplace, "$1");
t.state.inLink = !0;
const a = {
type: k[0].charAt(0) === "!" ? "image" : "link",
raw: e,
href: i,
title: l,
text: o,
tokens: t.inlineTokens(o)
};
return t.state.inLink = !1, a;
}, I = (k, n, e) => {
const t = k.match(e.other.indentCodeCompensation);
if (t === null)
return n;
const s = t[1];
return n.split(`
`).map((i) => {
const l = i.match(e.other.beginningSpace);
if (l === null)
return i;
const [o] = l;
return o.length >= s.length ? i.slice(s.length) : i;
}).join(`
`);
};
class D {
options;
rules;
lexer;
constructor(n) {
this.options = n || A;
}
space(n) {
const e = this.rules.block.newline.exec(n);
if (e && e[0].length > 0)
return {
type: "space",
raw: e[0]
};
}
code(n) {
const e = this.rules.block.code.exec(n);
if (e) {
const t = e[0].replace(this.rules.other.codeRemoveIndent, "");
return {
type: "code",
raw: e[0],
codeBlockStyle: "indented",
text: this.options.pedantic ? t : b(t, `
`)
};
}
}
fences(n) {
const e = this.rules.block.fences.exec(n);
if (e) {
const t = e[0], s = I(t, e[3] || "", this.rules);
return {
type: "code",
raw: t,
lang: e[2] ? e[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : e[2],
text: s
};
}
}
heading(n) {
const e = this.rules.block.heading.exec(n);
if (e) {
let t = e[2].trim();
if (this.rules.other.endingHash.test(t)) {
const s = b(t, "#");
(this.options.pedantic || !s || this.rules.other.endingSpaceChar.test(s)) && (t = s.trim());
}
return {
type: "heading",
raw: e[0],
depth: e[1].length,
text: t,
tokens: this.lexer.inline(t)
};
}
}
hr(n) {
const e = this.rules.block.hr.exec(n);
if (e)
return {
type: "hr",
raw: b(e[0], `
`)
};
}
blockquote(n) {
const e = this.rules.block.blockquote.exec(n);
if (e) {
let t = b(e[0], `
`).split(`
`), s = "", i = "";
const l = [];
for (; t.length > 0; ) {
let o = !1;
const a = [];
let h;
for (h = 0; h < t.length; h++)
if (this.rules.other.blockquoteStart.test(t[h]))
a.push(t[h]), o = !0;
else if (!o)
a.push(t[h]);
else
break;
t = t.slice(h);
const u = a.join(`
`), p = u.replace(this.rules.other.blockquoteSetextReplace, `
$1`).replace(this.rules.other.blockquoteSetextReplace2, "");
s = s ? `${s}
${u}` : u, i = i ? `${i}
${p}` : p;
const f = this.lexer.state.top;
if (this.lexer.state.top = !0, this.lexer.blockTokens(p, l, !0), this.lexer.state.top = f, t.length === 0)
break;
const r = l.at(-1);
if (r?.type === "code")
break;
if (r?.type === "blockquote") {
const g = r, c = g.raw + `
` + t.join(`
`), x = this.blockquote(c);
l[l.length - 1] = x, s = s.substring(0, s.length - g.raw.length) + x.raw, i = i.substring(0, i.length - g.text.length) + x.text;
break;
} else if (r?.type === "list") {
const g = r, c = g.raw + `
` + t.join(`
`), x = this.list(c);
l[l.length - 1] = x, s = s.substring(0, s.length - r.raw.length) + x.raw, i = i.substring(0, i.length - g.raw.length) + x.raw, t = c.substring(l.at(-1).raw.length).split(`
`);
continue;
}
}
return {
type: "blockquote",
raw: s,
tokens: l,
text: i
};
}
}
list(n) {
let e = this.rules.block.list.exec(n);
if (e) {
let t = e[1].trim();
const s = t.length > 1, i = {
type: "list",
raw: "",
ordered: s,
start: s ? +t.slice(0, -1) : "",
loose: !1,
items: []
};
t = s ? `\\d{1,9}\\${t.slice(-1)}` : `\\${t}`, this.options.pedantic && (t = s ? t : "[*+-]");
const l = this.rules.other.listItemRegex(t);
let o = !1;
for (; n; ) {
let h = !1, u = "", p = "";
if (!(e = l.exec(n)) || this.rules.block.hr.test(n))
break;
u = e[0], n = n.substring(u.length);
let f = e[2].split(`
`, 1)[0].replace(this.rules.other.listReplaceTabs, (m) => " ".repeat(3 * m.length)), r = n.split(`
`, 1)[0], g = !f.trim(), c = 0;
if (this.options.pedantic ? (c = 2, p = f.trimStart()) : g ? c = e[1].length + 1 : (c = e[2].search(this.rules.other.nonSpaceChar), c = c > 4 ? 1 : c, p = f.slice(c), c += e[1].length), g && this.rules.other.blankLine.test(r) && (u += r + `
`, n = n.substring(r.length + 1), h = !0), !h) {
const m = this.rules.other.nextBulletRegex(c), R = this.rules.other.hrRegex(c), L = this.rules.other.fencesBeginRegex(c), T = this.rules.other.headingBeginRegex(c), S = this.rules.other.htmlBeginRegex(c);
for (; n; ) {
const w = n.split(`
`, 1)[0];
let d;
if (r = w, this.options.pedantic ? (r = r.replace(this.rules.other.listReplaceNesting, " "), d = r) : d = r.replace(this.rules.other.tabCharGlobal, " "), L.test(r) || T.test(r) || S.test(r) || m.test(r) || R.test(r))
break;
if (d.search(this.rules.other.nonSpaceChar) >= c || !r.trim())
p += `
` + d.slice(c);
else {
if (g || f.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || L.test(f) || T.test(f) || R.test(f))
break;
p += `
` + r;
}
!g && !r.trim() && (g = !0), u += w + `
`, n = n.substring(w.length + 1), f = d.slice(c);
}
}
i.loose || (o ? i.loose = !0 : this.rules.other.doubleBlankLine.test(u) && (o = !0));
let x = null, y;
this.options.gfm && (x = this.rules.other.listIsTask.exec(p), x && (y = x[0] !== "[ ] ", p = p.replace(this.rules.other.listReplaceTask, ""))), i.items.push({
type: "list_item",
raw: u,
task: !!x,
checked: y,
loose: !1,
text: p,
tokens: []
}), i.raw += u;
}
const a = i.items.at(-1);
if (a)
a.raw = a.raw.trimEnd(), a.text = a.text.trimEnd();
else
return;
i.raw = i.raw.trimEnd();
for (let h = 0; h < i.items.length; h++)
if (this.lexer.state.top = !1, i.items[h].tokens = this.lexer.blockTokens(i.items[h].text, []), !i.loose) {
const u = i.items[h].tokens.filter((f) => f.type === "space"), p = u.length > 0 && u.some((f) => this.rules.other.anyLine.test(f.raw));
i.loose = p;
}
if (i.loose)
for (let h = 0; h < i.items.length; h++)
i.items[h].loose = !0;
return i;
}
}
html(n) {
const e = this.rules.block.html.exec(n);
if (e)
return {
type: "html",
block: !0,
raw: e[0],
pre: e[1] === "pre" || e[1] === "script" || e[1] === "style",
text: e[0]
};
}
def(n) {
const e = this.rules.block.def.exec(n);
if (e) {
const t = e[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), s = e[2] ? e[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", i = e[3] ? e[3].substring(1, e[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : e[3];
return {
type: "def",
tag: t,
raw: e[0],
href: s,
title: i
};
}
}
table(n) {
const e = this.rules.block.table.exec(n);
if (!e || !this.rules.other.tableDelimiter.test(e[2]))
return;
const t = B(e[1]), s = e[2].replace(this.rules.other.tableAlignChars, "").split("|"), i = e[3]?.trim() ? e[3].replace(this.rules.other.tableRowBlankLine, "").split(`
`) : [], l = {
type: "table",
raw: e[0],
header: [],
align: [],
rows: []
};
if (t.length === s.length) {
for (const o of s)
this.rules.other.tableAlignRight.test(o) ? l.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? l.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? l.align.push("left") : l.align.push(null);
for (let o = 0; o < t.length; o++)
l.header.push({
text: t[o],
tokens: this.lexer.inline(t[o]),
header: !0,
align: l.align[o]
});
for (const o of i)
l.rows.push(
B(o, l.header.length).map((a, h) => ({
text: a,
tokens: this.lexer.inline(a),
header: !1,
align: l.align[h]
}))
);
return l;
}
}
lheading(n) {
const e = this.rules.block.lheading.exec(n);
if (e)
return {
type: "heading",
raw: e[0],
depth: e[2].charAt(0) === "=" ? 1 : 2,
text: e[1],
tokens: this.lexer.inline(e[1])
};
}
paragraph(n) {
const e = this.rules.block.paragraph.exec(n);
if (e) {
const t = e[1].charAt(e[1].length - 1) === `
` ? e[1].slice(0, -1) : e[1];
return {
type: "paragraph",
raw: e[0],
text: t,
tokens: this.lexer.inline(t)
};
}
}
text(n) {
const e = this.rules.block.text.exec(n);
if (e)
return {
type: "text",
raw: e[0],
text: e[0],
tokens: this.lexer.inline(e[0])
};
}
escape(n) {
const e = this.rules.inline.escape.exec(n);
if (e)
return {
type: "escape",
raw: e[0],
text: e[1]
};
}
tag(n) {
const e = this.rules.inline.tag.exec(n);
if (e)
return !this.lexer.state.inLink && this.rules.other.startATag.test(e[0]) ? this.lexer.state.inLink = !0 : this.lexer.state.inLink && this.rules.other.endATag.test(e[0]) && (this.lexer.state.inLink = !1), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(e[0]) ? this.lexer.state.inRawBlock = !0 : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(e[0]) && (this.lexer.state.inRawBlock = !1), {
type: "html",
raw: e[0],
inLink: this.lexer.state.inLink,
inRawBlock: this.lexer.state.inRawBlock,
block: !1,
text: e[0]
};
}
link(n) {
const e = this.rules.inline.link.exec(n);
if (e) {
const t = e[2].trim();
if (!this.options.pedantic && this.rules.other.startAngleBracket.test(t)) {
if (!this.rules.other.endAngleBracket.test(t))
return;
const l = b(t.slice(0, -1), "\\");
if ((t.length - l.length) % 2 === 0)
return;
} else {
const l = $(e[2], "()");
if (l === -2)
return;
if (l > -1) {
const a = (e[0].indexOf("!") === 0 ? 5 : 4) + e[1].length + l;
e[2] = e[2].substring(0, l), e[0] = e[0].substring(0, a).trim(), e[3] = "";
}
}
let s = e[2], i = "";
if (this.options.pedantic) {
const l = this.rules.other.pedanticHrefTitle.exec(s);
l && (s = l[1], i = l[3]);
} else
i = e[3] ? e[3].slice(1, -1) : "";
return s = s.trim(), this.rules.other.startAngleBracket.test(s) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(t) ? s = s.slice(1) : s = s.slice(1, -1)), C(
e,
{
href: s && s.replace(this.rules.inline.anyPunctuation, "$1"),
title: i && i.replace(this.rules.inline.anyPunctuation, "$1")
},
e[0],
this.lexer,
this.rules
);
}
}
reflink(n, e) {
let t;
if ((t = this.rules.inline.reflink.exec(n)) || (t = this.rules.inline.nolink.exec(n))) {
const s = (t[2] || t[1]).replace(this.rules.other.multipleSpaceGlobal, " "), i = e[s.toLowerCase()];
if (!i) {
const l = t[0].charAt(0);
return {
type: "text",
raw: l,
text: l
};
}
return C(t, i, t[0], this.lexer, this.rules);
}
}
emStrong(n, e, t = "") {
let s = this.rules.inline.emStrongLDelim.exec(n);
if (!s || s[3] && t.match(this.rules.other.unicodeAlphaNumeric))
return;
if (!(s[1] || s[2] || "") || !t || this.rules.inline.punctuation.exec(t)) {
const l = [...s[0]].length - 1;
let o, a, h = l, u = 0;
const p = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
for (p.lastIndex = 0, e = e.slice(-1 * n.length + l); (s = p.exec(e)) != null; ) {
if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o)
continue;
if (a = [...o].length, s[3] || s[4]) {
h += a;
continue;
} else if ((s[5] || s[6]) && l % 3 && !((l + a) % 3)) {
u += a;
continue;
}
if (h -= a, h > 0)
continue;
a = Math.min(a, a + h + u);
const f = [...s[0]][0].length, r = n.slice(0, l + s.index + f + a);
if (Math.min(l, a) % 2) {
const c = r.slice(1, -1);
return {
type: "em",
raw: r,
text: c,
tokens: this.lexer.inlineTokens(c)
};
}
const g = r.slice(2, -2);
return {
type: "strong",
raw: r,
text: g,
tokens: this.lexer.inlineTokens(g)
};
}
}
}
codespan(n) {
const e = this.rules.inline.code.exec(n);
if (e) {
let t = e[2].replace(this.rules.other.newLineCharGlobal, " ");
const s = this.rules.other.nonSpaceChar.test(t), i = this.rules.other.startingSpaceChar.test(t) && this.rules.other.endingSpaceChar.test(t);
return s && i && (t = t.substring(1, t.length - 1)), {
type: "codespan",
raw: e[0],
text: t
};
}
}
br(n) {
const e = this.rules.inline.br.exec(n);
if (e)
return {
type: "br",
raw: e[0]
};
}
del(n) {
const e = this.rules.inline.del.exec(n);
if (e)
return {
type: "del",
raw: e[0],
text: e[2],
tokens: this.lexer.inlineTokens(e[2])
};
}
autolink(n) {
const e = this.rules.inline.autolink.exec(n);
if (e) {
let t, s;
return e[2] === "@" ? (t = e[1], s = "mailto:" + t) : (t = e[1], s = t), {
type: "link",
raw: e[0],
text: t,
href: s,
tokens: [
{
type: "text",
raw: t,
text: t
}
]
};
}
}
url(n) {
let e;
if (e = this.rules.inline.url.exec(n)) {
let t, s;
if (e[2] === "@")
t = e[0], s = "mailto:" + t;
else {
let i;
do
i = e[0], e[0] = this.rules.inline._backpedal.exec(e[0])?.[0] ?? "";
while (i !== e[0]);
t = e[0], e[1] === "www." ? s = "http://" + e[0] : s = e[0];
}
return {
type: "link",
raw: e[0],
text: t,
href: s,
tokens: [
{
type: "text",
raw: t,
text: t
}
]
};
}
}
inlineText(n) {
const e = this.rules.inline.text.exec(n);
if (e) {
const t = this.lexer.state.inRawBlock;
return {
type: "text",
raw: e[0],
text: e[0],
escaped: t
};
}
}
}
export {
D as _Tokenizer
};