fixed markdown and shiki(untested) link transformers
This commit is contained in:
parent
6d353e0c6b
commit
4fbb038c0d
|
@ -20,6 +20,7 @@
|
|||
"@types/node": "^20.14.11",
|
||||
"astro": "^4.15.9",
|
||||
"astro-breadcrumbs": "^2.3.1",
|
||||
"hast": "^1.0.0",
|
||||
"hast-util-from-html": "^2.0.3",
|
||||
"node": "npm:22.7.0",
|
||||
"remark-github-blockquote-alert": "^1.2.1",
|
||||
|
|
|
@ -75,7 +75,9 @@ export function groupRoutes(routes: RouteData[]): GroupedRoutes {
|
|||
}, defaultValue);
|
||||
}
|
||||
|
||||
export async function processQsMarkdown(markdown: string): Promise<string> {
|
||||
export async function processQsMarkdown(
|
||||
markdown: string
|
||||
): Promise<string> {
|
||||
return await markdownUtils.processMarkdown(markdown);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,78 +1,102 @@
|
|||
import type { Transformer } from "unified";
|
||||
import type { Node, Parent } from "unist";
|
||||
import type { Parent, Node } 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 type { Root, Element } 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"
|
||||
import {
|
||||
getQMLTypeLinkObject,
|
||||
getQMLTypeLink,
|
||||
getIconForLink,
|
||||
} from "./helpers.ts";
|
||||
|
||||
// couldn't find the actual type to use
|
||||
type HtmlNode = Node & {
|
||||
value: string,
|
||||
type: string,
|
||||
tagName: string,
|
||||
};
|
||||
interface HtmlNode extends 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") {
|
||||
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;
|
||||
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;
|
||||
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>`;
|
||||
});
|
||||
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 });
|
||||
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 => {
|
||||
return {
|
||||
name: "rewrite-typelinks",
|
||||
preprocess(code, _options) {
|
||||
const qtRegExp = /QT_(\w+)/g;
|
||||
const qsRegExp = /QS_(\w+)/g;
|
||||
// WARN: need to change the code link identifier to this
|
||||
// const hasTypelinks = code.search(/TYPE99(\w+.)99TYPE/g) !== -1;
|
||||
const hasQTLink = code.search(qtRegExp) !== -1;
|
||||
const hasQSLink = code.search(qsRegExp) !== -1;
|
||||
|
||||
if (hasQTLink) {
|
||||
code.replace(qtRegExp, (_full: string, match: string) => {
|
||||
const linkObject = getQMLTypeLinkObject(match);
|
||||
const link = getQMLTypeLink(linkObject);
|
||||
return `<a href=${link}>${linkObject.name ?? ""}</a>`;
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
if (hasQSLink) {
|
||||
code.replace(qsRegExp, (_full: string, match: string) => {
|
||||
const linkObject = getQMLTypeLinkObject(match);
|
||||
const link = getQMLTypeLink(linkObject);
|
||||
return `<a href=${link}>${linkObject.name ?? ""}</a>`;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const markdownConfig: AstroMarkdownOptions = {
|
||||
|
@ -80,16 +104,14 @@ export const markdownConfig: AstroMarkdownOptions = {
|
|||
shikiConfig: {
|
||||
theme: "material-theme-ocean",
|
||||
wrap: true,
|
||||
transformers: [ shikiRewriteTypelinks ],
|
||||
transformers: [shikiRewriteTypelinks()],
|
||||
},
|
||||
remarkPlugins: [[
|
||||
remarkAlert,
|
||||
{ legacyTitle: true },
|
||||
]],
|
||||
remarkPlugins: [[remarkAlert, { legacyTitle: true }]],
|
||||
rehypePlugins: [
|
||||
[ sectionize, { idPropertyName: "id" } ],
|
||||
// @ts-ignore: can't tell what this wants
|
||||
[ rehypeRewriteTypelinks, {} ],
|
||||
// FIXME: incompatible types between unified/Plugin and Astro/RehypePlugin
|
||||
// @ts-expect-error
|
||||
[sectionize as RehypePlugin, { idPropertyName: "id" }],
|
||||
rehypeRewriteTypelinks,
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -97,12 +119,16 @@ let globalMarkdownProcessor: Promise<MarkdownProcessor>;
|
|||
|
||||
async function getMarkdownProcessor(): Promise<MarkdownProcessor> {
|
||||
if (!globalMarkdownProcessor) {
|
||||
globalMarkdownProcessor = createMarkdownProcessor(markdownConfig);
|
||||
globalMarkdownProcessor =
|
||||
createMarkdownProcessor(markdownConfig);
|
||||
}
|
||||
|
||||
return globalMarkdownProcessor;
|
||||
}
|
||||
|
||||
export async function processMarkdown(markdown: string): Promise<string> {
|
||||
return (await (await getMarkdownProcessor()).render(markdown)).code;
|
||||
export async function processMarkdown(
|
||||
markdown: string
|
||||
): Promise<string> {
|
||||
return (await (await getMarkdownProcessor()).render(markdown))
|
||||
.code;
|
||||
}
|
||||
|
|
|
@ -4364,6 +4364,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hast@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "hast@npm:1.0.0"
|
||||
checksum: 10c0/a1a4ffaa99c6a4cfe6bd31e54ee919625a8ebcfc621d2d06cc76e593d7aeee4f1f430fcdbbf17ae8e249567ee7b724e4814b5eb273455d23bad8334c9bfc667d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hastscript@npm:^7.0.0":
|
||||
version: 7.2.0
|
||||
resolution: "hastscript@npm:7.2.0"
|
||||
|
@ -6312,6 +6319,7 @@ __metadata:
|
|||
"@types/node": "npm:^20.14.11"
|
||||
astro: "npm:^4.15.9"
|
||||
astro-breadcrumbs: "npm:^2.3.1"
|
||||
hast: "npm:^1.0.0"
|
||||
hast-util-from-html: "npm:^2.0.3"
|
||||
node: "npm:22.7.0"
|
||||
pagefind: "npm:^1.1.1"
|
||||
|
|
Loading…
Reference in a new issue