import marked, { Renderer } from "marked"; import hljs from "highlight.js"; import markedKatex from "marked-katex-extension"; marked.use(markedKatex({ throwOnError: false, output: `html` })); class WxRenderer { constructor(opts) { this.opts = opts; let footnotes = []; let footnoteIndex = 0; let styleMapping = new Map(); let merge = (base, extend) => Object.assign({}, base, extend); this.buildTheme = (themeTpl) => { let mapping = {}; let base = merge(themeTpl.BASE, { "font-family": this.opts.fonts, "font-size": this.opts.size, }); for (let ele in themeTpl.inline) { if (themeTpl.inline.hasOwnProperty(ele)) { let style = themeTpl.inline[ele]; mapping[ele] = merge(themeTpl.BASE, style); } } let base_block = merge(base, {}); for (let ele in themeTpl.block) { if (themeTpl.block.hasOwnProperty(ele)) { let style = themeTpl.block[ele]; mapping[ele] = merge(base_block, style); } } return mapping; }; let getStyles = (tokenName, addition) => { let arr = []; let dict = styleMapping[tokenName]; if (!dict) return ""; for (const key in dict) { arr.push(key + ":" + dict[key]); } return `style="${arr.join(";") + (addition || "")}"`; }; let addFootnote = (title, link) => { footnotes.push([++footnoteIndex, title, link]); return footnoteIndex; }; this.buildFootnotes = () => { let footnoteArray = footnotes.map((x) => { if (x[1] === x[2]) { return `[${x[0]}]: ${x[1]}
`; } return `[${x[0]}] ${x[1]}: ${x[2]}
`; }); if (!footnoteArray.length) { return ""; } return `

引用链接

${footnoteArray.join("\n")}

`; }; this.buildAddition = () => { return ` `; }; this.setOptions = (newOpts) => { this.opts = merge(this.opts, newOpts); }; this.hasFootnotes = () => footnotes.length !== 0; this.getRenderer = (status) => { footnotes = []; footnoteIndex = 0; styleMapping = this.buildTheme(this.opts.theme); let renderer = new Renderer(); renderer.heading = (text, level) => { switch (level) { case 1: return `

${text}

`; case 2: return `

${text}

`; case 3: return `

${text}

`; default: return `

${text}

`; } }; renderer.paragraph = (text) => { if (text.indexOf("${text}

`; }; renderer.blockquote = (text) => { text = text.replace(//g, `

`); return `

${text}
`; }; renderer.code = (text, lang = "") => { if (lang.startsWith("mermaid")) { setTimeout(() => { window.mermaid?.run(); }, 0); return `
${text}
`; } lang = hljs.getLanguage(lang) ? lang : "plaintext"; text = hljs.highlight(text, { language: lang }).value; text = text .replace(/\r\n/g, "
") .replace(/\n/g, "
") .replace(/(>[^<]+)|(^[^<]+)/g, function (str) { return str.replace(/\s/g, " "); }); return `
${text}
`; }; renderer.codespan = (text, lang) => `${text}`; renderer.listitem = (text) => `
  • <%s/>${text}
  • `; renderer.list = (text, ordered, start) => { text = text.replace(/<\/*p .*?>/g, "").replace(/<\/*p>/g, ""); let segments = text.split(`<%s/>`); if (!ordered) { text = segments.join("• "); return ``; } text = segments[0]; for (let i = 1; i < segments.length; i++) { text = text + i + ". " + segments[i]; } return `
      ${text}
    `; }; renderer.image = (href, title, text) => { let subText = ""; if (text) { subText = `
    ${text}
    `; } let figureStyles = getStyles("figure"); let imgStyles = getStyles("image"); return `
    ${text}${subText}
    `; }; renderer.link = (href, title, text) => { if (href.startsWith("https://mp.weixin.qq.com")) { return `${text}`; } if (href === text) { return text; } if (status) { let ref = addFootnote(title || text, href); return `${text}[${ref}]`; } return `${text}`; }; renderer.strong = (text) => `${text}`; renderer.em = (text) => `${text}`; renderer.table = (header, body) => `
    ${header}${body}
    `; renderer.tablecell = (text, flags) => `${text}`; renderer.hr = () => `
    `; return renderer; }; } } export default WxRenderer;