// see: https://andyburke.dev/andyburke/serverus/src/branch/dev/handlers/markdown.ts
/* MARKDOWN TO HTML */
/* order of these transforms matters, so we list them here in an array and build type from it after. */
const MD_TRANSFORM_NAMES = [
"characters",
"headings",
"horizontal_rules",
"list_items",
"bold",
"italic",
"strikethrough",
"code",
"images",
"links",
"breaks",
];
const MD_TRANSFORMS = {
characters: [
[/&/g, "&"],
[//g, ">"],
[/"/g, """],
[/'/g, "'"],
],
headings: [
[/^#\s(.+)$/gm, "
$1
\n"],
[/^##\s(.+)$/gm, "$1
\n"],
[/^###\s(.+)$/gm, "$1
\n"],
[/^####\s(.+)$/gm, "$1
\n"],
[/^#####\s(.+)$/gm, "$1
\n"],
],
horizontal_rules: [[/^----*$/gm, "
\n"]],
list_items: [
[/\n\n([ \t]*)([-\*\.].*?)\n\n/gs, "\n\n\n\n\n"],
[/^([ \t]*)[-\*\.](\s+.*)$/gm, "$1$2\n"],
],
bold: [[/\*([^\*]+)\*/gm, "$1"]],
italic: [[/_([^_]+)_/gm, "$1"]],
strikethrough: [[/~([^~]+)~/gm, "$1"]],
code: [
[/```\n([^`]+)\n```/gm, "$1
"],
[/```([^`]+)```/gm, "$1"],
],
images: [[/!\[([^\]]+)\]\(([^\)]+)\)/g, '
']],
links: [[/\[([^\]]+)\]\(([^\)]+)\)/g, '$1']],
breaks: [
[/\s\s\n/g, "\n
\n"],
[/\n\n/g, "\n
\n"],
],
};
/**
* Convert markdown to HTML.
* @param markdown The markdown string.
* @param options _(Optional)_ A record of transforms to disable.
* @returns The generated HTML string.
*/
function md_to_html(markdown, transform_config) {
let html = markdown;
for (const transform_name of MD_TRANSFORM_NAMES) {
const enabled =
typeof transform_config === "undefined" || transform_config[transform_name] !== false;
if (!enabled) {
continue;
}
const transforms = MD_TRANSFORMS[transform_name] ?? [];
for (const markdown_transformer of transforms) {
html = html.replace(...markdown_transformer);
}
}
return `${html}
`;
}