UNPKG

@vuux/editor

Version:

Vue Nuxt 富文本编辑器

523 lines (522 loc) 15.7 kB
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 };