autonomous.contact/public/js/external/md_to_html.js
Andy Burke b6f661c6ec feature: essays
fix: multiple rendering of things when sending
2025-09-24 13:21:39 -07:00

86 lines
2 KiB
JavaScript

// 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, "&lt;"],
[/>/g, "&gt;"],
[/"/g, "&quot;"],
[/'/g, "&#39;"],
],
headings: [
[/^#\s(.+)$/gm, "<h1>$1</h1>\n"],
[/^##\s(.+)$/gm, "<h2>$1</h2>\n"],
[/^###\s(.+)$/gm, "<h3>$1</h3>\n"],
[/^####\s(.+)$/gm, "<h4>$1</h4>\n"],
[/^#####\s(.+)$/gm, "<h5>$1</h5>\n"],
],
horizontal_rules: [[/^----*$/gm, "<hr>\n"]],
list_items: [
[/\n\n([ \t]*)([-\*\.].*?)\n\n/gs, "\n\n<ul>\n$1$2\n</ul>\n\n\n"],
[/^([ \t]*)[-\*\.](\s+.*)$/gm, "<li>$1$2</li>\n"],
],
bold: [[/\*([^\*]+)\*/gm, "<strong>$1</strong>"]],
italic: [[/_([^_]+)_/gm, "<i>$1</i>"]],
strikethrough: [[/~([^~]+)~/gm, "<s>$1</s>"]],
code: [
[/```\n([^`]+)\n```/gm, "<pre><code>$1</code></pre>"],
[/```([^`]+)```/gm, "<code>$1</code>"],
],
images: [[/!\[([^\]]+)\]\(([^\)]+)\)/g, '<img src="$2" alt="$1">']],
links: [[/\[([^\]]+)\]\(([^\)]+)\)/g, '<a href="$2">$1</a>']],
breaks: [
[/\s\s\n/g, "\n<br>\n"],
[/\n\n/g, "\n<br>\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 `<div class="html-from-markdown">${html}</div>`;
}