(text, {mode = "inline", codelines = Infinity} = {})
| 285 | |
| 286 | /**Markdown-html sanitizer-interpreter */ |
| 287 | export async function markdown(text, {mode = "inline", codelines = Infinity} = {}) { |
| 288 | //Sanitize user input once to prevent injections and parse into markdown |
| 289 | let rendered = await marked.parse(htmlunescape(htmlsanitize(text)), {highlight, silent: true, xhtml: true}) |
| 290 | //Markdown mode |
| 291 | switch (mode) { |
| 292 | case "inline": { |
| 293 | rendered = htmlsanitize( |
| 294 | htmlsanitize(rendered, { |
| 295 | allowedTags: ["h1", "h2", "h3", "h4", "h5", "h6", "br", "blockquote", "code", "span"], |
| 296 | allowedAttributes: {code: ["class"], span: ["class"]}, |
| 297 | }), |
| 298 | { |
| 299 | allowedAttributes: {code: ["class"], span: ["class"]}, |
| 300 | transformTags: {h1: "b", h2: "b", h3: "b", h4: "b", h5: "b", h6: "b", blockquote: "i"}, |
| 301 | }, |
| 302 | ) |
| 303 | break |
| 304 | } |
| 305 | default: |
| 306 | break |
| 307 | } |
| 308 | //Trim code snippets |
| 309 | rendered = rendered.replace(/(?<open><code[\s\S]*?>)(?<code>[\s\S]*?)(?<close><\/code>)/g, (m, open, code, close) => { //eslint-disable-line max-params |
| 310 | const lines = code.trim().split("\n") |
| 311 | if (lines.length > 1) { |
| 312 | if (/class=".*language-[\s\S]+?.*"/.test(open)) |
| 313 | open = open.replace(/>/g, ` class="language-multiline ${open.match(/class="(?<class>[\s\S]+)"/)?.groups.class}" xml:space="preserve">`) |
| 314 | else if (!/class="[\s\S]*"/.test(open)) |
| 315 | open = open.replace(/>/g, ' class="language-multiline" xml:space="preserve">') |
| 316 | } |
| 317 | return `${open}${lines.slice(0, codelines).join("\n")}${lines.length > codelines ? `\n<span class="token trimmed">(${lines.length - codelines} more ${lines.length - codelines === 1 ? "line was" : "lines were"} trimmed)</span>` : ""}${close}` |
| 318 | }) |
| 319 | return rendered |
| 320 | } |
| 321 | |
| 322 | /**Filters */ |
| 323 | export const filters = { |
nothing calls this directly
no test coverage detected