From 4fbb038c0d405654d3a36c1ebed28d6d5ecbd35f Mon Sep 17 00:00:00 2001 From: Xanazf Date: Thu, 10 Oct 2024 21:06:15 +0300 Subject: [PATCH] fixed markdown and shiki(untested) link transformers --- package.json | 1 + src/config/io/helpers.ts | 4 +- src/config/io/markdown.ts | 156 ++++++++++++++++++++++---------------- yarn.lock | 8 ++ 4 files changed, 103 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index 045ccee..d6abdce 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/config/io/helpers.ts b/src/config/io/helpers.ts index cca7e06..fef5515 100644 --- a/src/config/io/helpers.ts +++ b/src/config/io/helpers.ts @@ -75,7 +75,9 @@ export function groupRoutes(routes: RouteData[]): GroupedRoutes { }, defaultValue); } -export async function processQsMarkdown(markdown: string): Promise { +export async function processQsMarkdown( + markdown: string +): Promise { return await markdownUtils.processMarkdown(markdown); } diff --git a/src/config/io/markdown.ts b/src/config/io/markdown.ts index e1b2ac4..f5c6c52 100644 --- a/src/config/io/markdown.ts +++ b/src/config/io/markdown.ts @@ -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 `${icon ?? ""}${linkObject.name ?? ""}${hasDot ? "." : ""}${linkObject.mname ?? ""}${hasParens ? "()" : ""}`; - }); + return `${icon ?? ""}${linkObject.name ?? ""}${hasDot ? "." : ""}${linkObject.mname ?? ""}${hasParens ? "()" : ""}`; + } + ); 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 `${linkObject.name ?? ""}`; + }); } - 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 `${linkObject.name ?? ""}`; - }); - - 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 `${linkObject.name ?? ""}`; + }); } - }); - } + }, + }; }; 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; async function getMarkdownProcessor(): Promise { if (!globalMarkdownProcessor) { - globalMarkdownProcessor = createMarkdownProcessor(markdownConfig); + globalMarkdownProcessor = + createMarkdownProcessor(markdownConfig); } return globalMarkdownProcessor; } -export async function processMarkdown(markdown: string): Promise { - return (await (await getMarkdownProcessor()).render(markdown)).code; +export async function processMarkdown( + markdown: string +): Promise { + return (await (await getMarkdownProcessor()).render(markdown)) + .code; } diff --git a/yarn.lock b/yarn.lock index c700bf3..d137eb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"