discourse/app/assets/javascripts/pretty-text/engines/discourse-markdown/code.js

60 lines
1.7 KiB
JavaScript

// we need a custom renderer for code blocks cause we have a slightly non compliant
// format with special handling for text and so on
const TEXT_CODE_CLASSES = ["text", "pre", "plain"];
function render(tokens, idx, options, env, slf, md) {
let token = tokens[idx],
info = token.info ? md.utils.unescapeAll(token.info) : "",
langName = md.options.discourse.defaultCodeLang,
className,
escapedContent = md.utils.escapeHtml(token.content);
if (info) {
// strip off any additional languages
info = info.trim().split(/\s+/g)[0];
}
const acceptableCodeClasses = md.options.discourse.acceptableCodeClasses;
if (
acceptableCodeClasses &&
info &&
acceptableCodeClasses.indexOf(info) !== -1
) {
langName = info;
}
className =
TEXT_CODE_CLASSES.indexOf(info) !== -1
? "lang-nohighlight"
: "lang-" + langName;
return `<pre><code class="${className}">${escapedContent}</code></pre>\n`;
}
export function setup(helper) {
helper.registerOptions((opts, siteSettings) => {
opts.defaultCodeLang = siteSettings.default_code_lang;
opts.acceptableCodeClasses = (siteSettings.highlighted_languages || "")
.split("|")
.filter(Boolean)
.concat(["auto", "nohighlight"]);
});
helper.allowList({
custom(tag, name, value) {
if (tag === "code" && name === "class") {
const m = /^lang\-(.+)$/.exec(value);
if (m) {
return helper.getOptions().acceptableCodeClasses.indexOf(m[1]) !== -1;
}
}
},
});
helper.registerPlugin((md) => {
md.renderer.rules.fence = (tokens, idx, options, env, slf) =>
render(tokens, idx, options, env, slf, md);
});
}