import { Marked } from "marked";
import type { Renderer, Token } from "marked";
import { markedHighlight } from "marked-highlight";
import hljs from "highlight.js";
import GithubSlugger from "github-slugger";
import DOMPurify from "isomorphic-dompurify";
import { applyAction, deserialize } from "$app/forms";
export const sortOptions = [
{ value: "creation-time", text: "Creation time" },
{ value: "last-modified", text: "Last modified" },
{ value: "title-a-to-z", text: "Title - A to Z" },
{ value: "title-z-to-a", text: "Title - Z to A" }
];
export const ALLOWED_MIME_TYPES = ["image/jpeg", "image/png", "image/svg+xml", "image/webp"];
const createMarkdownParser = (showToc = true) => {
const marked = new Marked();
marked.use({
async: false,
pedantic: false,
gfm: true
});
marked.use(
markedHighlight({
async: false,
langPrefix: "language-",
highlight(code, lang) {
const language = hljs.getLanguage(lang) ? lang : "plaintext";
return hljs.highlight(code, { language }).value;
}
})
);
const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;
const unescape = (html: string) => {
return html.replace(unescapeTest, (_, n) => {
n = n.toLowerCase();
if (n === "colon") return ":";
if (n.charAt(0) === "#") {
return n.charAt(1) === "x"
? String.fromCharCode(parseInt(n.substring(2), 16))
: String.fromCharCode(+n.substring(1));
}
return "";
});
};
let slugger = new GithubSlugger();
let headings: { text: string; raw: string; level: number; id: string }[] = [];
let sectionStack: { level: number; id: string }[] = [];
const gfmHeadingId = ({ prefix = "", showToc = true } = {}) => {
return {
renderer: {
heading(this: Renderer, { tokens, depth }: { tokens: Token[]; depth: number }) {
const text = this.parser.parseInline(tokens);
const raw = unescape(this.parser.parseInline(tokens, this.parser.textRenderer))
.trim()
.replace(/<[!\/a-z].*?>/gi, "");
const level = depth;
const id = `${prefix}${slugger.slug(raw.toLowerCase())}`;
const heading = { level, text, id, raw };
headings.push(heading);
let closingSections = "";
while (sectionStack.length > 0 && sectionStack[sectionStack.length - 1].level >= level) {
sectionStack.pop();
closingSections += "";
}
sectionStack.push({ level, id });
const openingSection = `