quickshell-web/src/config/io/markdown.ts
outfoxxed 492200a42b
fix vite and solid in dev
Inclusion of @astrojs/markdown-remark caused errors that cause solid
and vite to fail to load in dev. It's stripped in build.
2024-10-11 22:35:32 -07:00

120 lines
3.4 KiB
TypeScript

import type { Parent, Node } from "unist";
import { visit, CONTINUE, SKIP } from "unist-util-visit";
import { fromHtml } from "hast-util-from-html";
import type { Root } from "hast";
import type {
AstroMarkdownOptions,
MarkdownProcessor,
RehypePlugin,
} from "@astrojs/markdown-remark";
import { createMarkdownProcessor } from "@astrojs/markdown-remark";
import { remarkAlert } from "remark-github-blockquote-alert";
import sectionize from "@hbsnow/rehype-sectionize";
import type { ShikiTransformer } from "shiki";
import {
getQMLTypeLinkObject,
getQMLTypeLink,
getIconForLink,
} from "./helpers.ts";
// couldn't find the actual type to use
interface HtmlNode extends Node {
value: string;
type: string;
tagName: string;
}
const rehypeRewriteTypelinks: RehypePlugin<[]> = () => {
return (root: Node): Root => {
visit(
root,
"text",
(node: HtmlNode, index: number, parent: Parent) => {
let changed = false;
node.value = node.value.replace(
/TYPE99(\w+.)99TYPE/g,
(_full: string, match: string) => {
changed = true;
const linkObject = getQMLTypeLinkObject(match);
const link = getQMLTypeLink(linkObject);
const icon =
linkObject.mtype && linkObject.mtype !== "func"
? getIconForLink(linkObject.mtype, false)
: null;
const hasParens =
linkObject.mtype === "func" ||
linkObject.mtype === "signal";
const hasDot = linkObject.name && linkObject.mname;
return `<a class="type${linkObject.mtype}-link typedata-link" href=${link}>${icon ?? ""}${linkObject.name ?? ""}${hasDot ? "." : ""}${linkObject.mname ?? ""}${hasParens ? "()" : ""}</a>`;
}
);
if (changed) {
const fragment = fromHtml(node.value, {
fragment: true,
});
parent.children.splice(index, 1, ...fragment.children);
return SKIP;
}
return CONTINUE;
}
);
return root as Root;
};
};
const shikiRewriteTypelinks: ShikiTransformer = {
name: "rewrite-typelinks",
postprocess(code, _options) {
// WARN: need to change the code link identifier to this
const regExp = /TYPE99(\w+.)99TYPE/g;
const hasTypelinks = code.search(regExp) !== -1;
if (hasTypelinks) {
code.replace(regExp, (_full: string, match: string) => {
const linkObject = getQMLTypeLinkObject(match);
const link = getQMLTypeLink(linkObject);
return `<a href=${link}>${linkObject.name ?? ""}</a>`;
});
}
},
};
export const markdownConfig: AstroMarkdownOptions = {
syntaxHighlight: "shiki",
shikiConfig: {
theme: "material-theme-ocean",
wrap: true,
transformers: [shikiRewriteTypelinks],
},
remarkPlugins: [[remarkAlert, { legacyTitle: true }]],
rehypePlugins: [
// FIXME: incompatible types between unified/Plugin and Astro/RehypePlugin
[sectionize as RehypePlugin, { idPropertyName: "id" }],
rehypeRewriteTypelinks,
],
};
let globalMarkdownProcessor: Promise<MarkdownProcessor>;
async function getMarkdownProcessor(): Promise<MarkdownProcessor> {
if (!globalMarkdownProcessor) {
globalMarkdownProcessor =
createMarkdownProcessor(markdownConfig);
}
return globalMarkdownProcessor;
}
export async function processMarkdown(
markdown: string
): Promise<string> {
return (await (await getMarkdownProcessor()).render(markdown))
.code;
}