shadowfacts.net/lib/markdown.ts

54 lines
1.4 KiB
TypeScript

import MarkdownIt from "markdown-it";
import MarkdownItFootnote from "markdown-it-footnote";
import slugify from "@sindresorhus/slugify";
import * as util from "./util";
const md = new MarkdownIt({
highlight: util.highlight,
html: true,
typographer: true
});
md.use(MarkdownItFootnote);
// Inserts heading anchors
// Based on https://github.com/valeriangalliat/markdown-it-anchor
md.core.ruler.push("anchor", (state) => {
const tokens = state.tokens;
tokens
.filter((token) => token.type === "heading_open")
.forEach((token) => {
const index = tokens.indexOf(token);
const title = tokens[index + 1]
.children
.filter((token) => token.type === "text" || token.type == "code_inline")
.reduce((acc, t) => acc + t.content, "");
let slug = token.attrGet("id") || slugify(title);
if (token.attrGet("id") == null) {
token.attrPush(["id", slug]);
}
const linkTokens = [
Object.assign(new state.Token("link_open", "a", 1), {
attrs: [
["class", "header-anchor"],
["href", "#" + slug],
["aria-hidden", "true"],
["role", "presentation"]
]
}),
Object.assign(new state.Token("html_block", "", 0), { content: token.markup }),
new state.Token("link_close", "a", -1),
Object.assign(new state.Token("text", "", 0), { content: " " })
];
state.tokens[index + 1].children.unshift(...linkTokens);
});
});
export function render(text: string): string {
return md.render(text);
}