move type-link processing to build stage
This commit is contained in:
parent
ab2a9ca7ed
commit
6d353e0c6b
15 changed files with 161 additions and 300 deletions
|
@ -1,8 +1,4 @@
|
|||
import { unified } from "unified";
|
||||
import remarkParse from "remark-parse";
|
||||
import remarkRehype from "remark-rehype";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
import { remarkAlert } from "remark-github-blockquote-alert";
|
||||
import * as markdownUtils from "./markdown.ts";
|
||||
|
||||
import {
|
||||
// Flag,
|
||||
|
@ -10,7 +6,8 @@ import {
|
|||
Tag,
|
||||
FourDiamonds,
|
||||
RoundBrackets,
|
||||
} from "@icons";
|
||||
// @icons breaks when imported indirectly from astro.config.mjs
|
||||
} from "../../components/icons.tsx";
|
||||
import type {
|
||||
ConfigHeading,
|
||||
ConfigTOC,
|
||||
|
@ -78,21 +75,8 @@ export function groupRoutes(routes: RouteData[]): GroupedRoutes {
|
|||
}, defaultValue);
|
||||
}
|
||||
|
||||
export function parseMarkdown(text?: string, title?: string) {
|
||||
if (!text) {
|
||||
return unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeStringify)
|
||||
.process(title);
|
||||
}
|
||||
|
||||
return unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkAlert)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeStringify)
|
||||
.process(text);
|
||||
export async function processQsMarkdown(markdown: string): Promise<string> {
|
||||
return await markdownUtils.processMarkdown(markdown);
|
||||
}
|
||||
|
||||
export function getQMLTypeLinkObject(unparsed: string) {
|
||||
|
|
108
src/config/io/markdown.ts
Normal file
108
src/config/io/markdown.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
import type { Transformer } from "unified";
|
||||
import type { Node, Parent } from "unist";
|
||||
import { visit, CONTINUE, SKIP } from "unist-util-visit";
|
||||
import { fromHtml } from "hast-util-from-html";
|
||||
|
||||
import type { AstroMarkdownOptions, MarkdownProcessor } from "@astrojs/markdown-remark";
|
||||
import { createMarkdownProcessor } from "@astrojs/markdown-remark";
|
||||
|
||||
import { remarkAlert } from "remark-github-blockquote-alert";
|
||||
import sectionize from "@hbsnow/rehype-sectionize";
|
||||
|
||||
import { getQMLTypeLinkObject, getQMLTypeLink, getIconForLink } from "./helpers.ts"
|
||||
|
||||
// couldn't find the actual type to use
|
||||
type HtmlNode = Node & {
|
||||
value: string,
|
||||
type: string,
|
||||
tagName: string,
|
||||
};
|
||||
|
||||
function rehypeRewriteTypelinks(): Transformer {
|
||||
return function (root: Node): Node {
|
||||
// @ts-ignore: does not appear to be a way to give this a correct type, it works for the one with a test below
|
||||
visit(root, (node: HtmlNode, index: number, parent: Parent) => {
|
||||
if (node.type == "element" && node.tagName == "pre") return SKIP;
|
||||
|
||||
if (node.type == "text") {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const shikiRewriteTypelinks = {
|
||||
code: (root: Node) => {
|
||||
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);
|
||||
|
||||
return `<a href=${link}>${linkObject.name ?? ""}</a>`;
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
const fragment = fromHtml(node.value, { fragment: true });
|
||||
parent.children.splice(index, 1, ...fragment.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const markdownConfig: AstroMarkdownOptions = {
|
||||
syntaxHighlight: "shiki",
|
||||
shikiConfig: {
|
||||
theme: "material-theme-ocean",
|
||||
wrap: true,
|
||||
transformers: [ shikiRewriteTypelinks ],
|
||||
},
|
||||
remarkPlugins: [[
|
||||
remarkAlert,
|
||||
{ legacyTitle: true },
|
||||
]],
|
||||
rehypePlugins: [
|
||||
[ sectionize, { idPropertyName: "id" } ],
|
||||
// @ts-ignore: can't tell what this wants
|
||||
[ 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue