move type-link processing to build stage
This commit is contained in:
parent
ab2a9ca7ed
commit
6d353e0c6b
|
@ -1,10 +1,9 @@
|
||||||
import { defineConfig } from "astro/config";
|
import { defineConfig } from "astro/config";
|
||||||
import solidJs from "@astrojs/solid-js";
|
import solidJs from "@astrojs/solid-js";
|
||||||
import { remarkAlert } from "remark-github-blockquote-alert";
|
|
||||||
import sectionize from "@hbsnow/rehype-sectionize";
|
|
||||||
import mdx from "@astrojs/mdx";
|
import mdx from "@astrojs/mdx";
|
||||||
|
|
||||||
import pagefind from "./pagefind";
|
import pagefind from "./pagefind";
|
||||||
|
import { markdownConfig } from "./src/config/io/markdown.ts";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
@ -15,27 +14,5 @@ export default defineConfig({
|
||||||
mdx(),
|
mdx(),
|
||||||
pagefind(),
|
pagefind(),
|
||||||
],
|
],
|
||||||
markdown: {
|
markdown: markdownConfig,
|
||||||
syntaxHighlight: "shiki",
|
|
||||||
shikiConfig: {
|
|
||||||
theme: "material-theme-ocean",
|
|
||||||
wrap: true,
|
|
||||||
},
|
|
||||||
remarkPlugins: [
|
|
||||||
[
|
|
||||||
remarkAlert,
|
|
||||||
{
|
|
||||||
legacyTitle: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
rehypePlugins: [
|
|
||||||
[
|
|
||||||
sectionize,
|
|
||||||
{
|
|
||||||
idPropertyName: "id",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
13
package.json
13
package.json
|
@ -12,28 +12,27 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ark-ui/solid": "^3.5.0",
|
"@ark-ui/solid": "^3.5.0",
|
||||||
"@astrojs/check": "^0.9.3",
|
"@astrojs/check": "^0.9.3",
|
||||||
|
"@astrojs/markdown-remark": "^5.1.0",
|
||||||
"@astrojs/mdx": "^3.1.7",
|
"@astrojs/mdx": "^3.1.7",
|
||||||
"@astrojs/solid-js": "^4.4.2",
|
"@astrojs/solid-js": "^4.4.2",
|
||||||
|
"@hbsnow/rehype-sectionize": "^1.0.7",
|
||||||
"@pagefind/default-ui": "^1.1.1",
|
"@pagefind/default-ui": "^1.1.1",
|
||||||
"@types/node": "^20.14.11",
|
"@types/node": "^20.14.11",
|
||||||
"astro": "^4.15.9",
|
"astro": "^4.15.9",
|
||||||
"astro-breadcrumbs": "^2.3.1",
|
"astro-breadcrumbs": "^2.3.1",
|
||||||
|
"hast-util-from-html": "^2.0.3",
|
||||||
"node": "npm:22.7.0",
|
"node": "npm:22.7.0",
|
||||||
"rehype-stringify": "^10.0.1",
|
|
||||||
"remark-github-blockquote-alert": "^1.2.1",
|
"remark-github-blockquote-alert": "^1.2.1",
|
||||||
"remark-parse": "^11.0.0",
|
|
||||||
"remark-rehype": "^11.1.1",
|
|
||||||
"solid-devtools": "^0.30.1",
|
"solid-devtools": "^0.30.1",
|
||||||
"solid-js": "^1.8.18",
|
"solid-js": "^1.8.18",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"unified": "^11.0.5"
|
"unified": "^11.0.5",
|
||||||
|
"unist-util-visit": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/ts-plugin": "^1.10.2",
|
"@astrojs/ts-plugin": "^1.10.2",
|
||||||
"@biomejs/biome": "^1.8.3",
|
"@biomejs/biome": "^1.8.3",
|
||||||
"@hbsnow/rehype-sectionize": "^1.0.7",
|
"pagefind": "^1.1.1"
|
||||||
"pagefind": "^1.1.1",
|
|
||||||
"shiki": "^1.11.0"
|
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.5.0"
|
"packageManager": "yarn@4.5.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
<script>
|
|
||||||
const qtRegExp = /QT_(\w+)/g
|
|
||||||
const qsRegExp = /QS_(\w+)/g
|
|
||||||
setTimeout(() =>{
|
|
||||||
const blocks = document.querySelectorAll("pre")
|
|
||||||
if (blocks.length > 0) {
|
|
||||||
blocks.forEach((block) => {
|
|
||||||
const content = block.textContent
|
|
||||||
const elements = block.querySelectorAll("span")
|
|
||||||
const classElements:HTMLSpanElement[] = [];
|
|
||||||
if (elements.length === 0) {
|
|
||||||
console.log("NO SPAN ELEMENTS FOUND")
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.forEach(element => {
|
|
||||||
const isClassColored = element.style.cssText === "color: rgb(255, 203, 107);"
|
|
||||||
const isSignal = element.innerText.trim().startsWith("on")
|
|
||||||
const qualifier = isClassColored && !isSignal
|
|
||||||
|
|
||||||
if (qualifier) {
|
|
||||||
const dotSibling = element.nextSibling
|
|
||||||
const isSplit = dotSibling?.textContent === "."
|
|
||||||
|
|
||||||
if (isSplit) {
|
|
||||||
let newInnerText = element.innerText + dotSibling.textContent + dotSibling.nextSibling?.textContent
|
|
||||||
|
|
||||||
if (dotSibling.nextSibling) {
|
|
||||||
dotSibling.nextSibling.textContent !== " {"
|
|
||||||
? dotSibling.nextSibling.remove()
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
|
|
||||||
dotSibling.remove()
|
|
||||||
element.innerText = newInnerText
|
|
||||||
}
|
|
||||||
classElements.push(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (content) {
|
|
||||||
const qtMatch = [...content.matchAll(qtRegExp)]
|
|
||||||
const qsMatch = [...content.matchAll(qsRegExp)]
|
|
||||||
|
|
||||||
if (qtMatch.length > 0) {
|
|
||||||
for (const qtMatching of qtMatch) {
|
|
||||||
const newATag = document.createElement("a")
|
|
||||||
const qtBelongs = qtMatching[0].split("_")[1].replace("11", "-") || null
|
|
||||||
const qtClass = qtMatching[1].split("_")[1]
|
|
||||||
const link = `https://doc.qt.io/qt-6/qml-${qtBelongs ? `${qtBelongs}-${qtClass.toLowerCase()}` : "qtquick-" + qtClass.toLowerCase()}.html`
|
|
||||||
newATag.target = "_blank"
|
|
||||||
newATag.href = link
|
|
||||||
newATag.innerText = qtClass
|
|
||||||
const homeElement = classElements.find(item => {
|
|
||||||
const spacing = item.innerText.replace(qtMatching[0], "")
|
|
||||||
if (item.innerText.trim() === qtMatching[0].trim()){
|
|
||||||
newATag.innerText = spacing + qtClass
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (homeElement) {
|
|
||||||
homeElement.innerText = ""
|
|
||||||
homeElement.appendChild(newATag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (qsMatch.length > 0) {
|
|
||||||
for (const qsMatching of qsMatch) {
|
|
||||||
const newATag = document.createElement("a")
|
|
||||||
|
|
||||||
const qsBelongs = qsMatching[0].split("_")[1].replace("00", ".") || null
|
|
||||||
const qsClass = qsMatching[1].split("_")[1]
|
|
||||||
|
|
||||||
const link = `/docs/types/${qsBelongs ? `${qsBelongs}/${qsClass}` : qsClass}`
|
|
||||||
newATag.target = "_blank"
|
|
||||||
newATag.href = link
|
|
||||||
|
|
||||||
const homeElement = classElements.find(item => {
|
|
||||||
const existingItem = item.innerText.trim()
|
|
||||||
const matchingItem = qsMatching[0].trim()
|
|
||||||
const spacing = item.innerText.replace(existingItem, "")
|
|
||||||
|
|
||||||
if (existingItem === matchingItem) {
|
|
||||||
newATag.innerText = spacing + qsClass
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (homeElement) {
|
|
||||||
homeElement.innerText = ""
|
|
||||||
|
|
||||||
if (homeElement.nextSibling) {
|
|
||||||
homeElement.nextSibling.textContent !== " {"
|
|
||||||
? homeElement.nextSibling.textContent = ""
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
homeElement.appendChild(newATag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},3000)
|
|
||||||
</script>
|
|
|
@ -1,66 +0,0 @@
|
||||||
---
|
|
||||||
---
|
|
||||||
<script>
|
|
||||||
import { getQMLTypeLinkObject, getQMLTypeLink, getIconForLink } from "@config/io/helpers"
|
|
||||||
|
|
||||||
const detailsData = document.getElementsByTagName("p")
|
|
||||||
const innerItems = document.getElementsByClassName("typedata-details")
|
|
||||||
if (detailsData) {
|
|
||||||
for (const details of detailsData) {
|
|
||||||
const linkRegex = /TYPE99(\w+.)99TYPE/g
|
|
||||||
const mtypeExists = details.textContent?.match(linkRegex)
|
|
||||||
|
|
||||||
if (!mtypeExists || !details.textContent) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const linkMatch = [...details.textContent.matchAll(linkRegex)]
|
|
||||||
let textWithLinks = details.textContent;
|
|
||||||
for (const matching of linkMatch) {
|
|
||||||
if (details.textContent.indexOf(matching[0]) === -1){
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const linkObject = getQMLTypeLinkObject(matching[1]);
|
|
||||||
const link = getQMLTypeLink(linkObject);
|
|
||||||
const icon = linkObject.mtype ? getIconForLink(linkObject.mtype, false) : null;
|
|
||||||
|
|
||||||
// for signal
|
|
||||||
const bracketString = getIconForLink("func", false)
|
|
||||||
|
|
||||||
const newLink = `<span class="type${linkObject.mtype}-link typedata-link">${icon ? icon : ""}<a href=${link}>${linkObject.mname || linkObject.name}</a>${linkObject.mtype === "signal" ? bracketString : ""}</span>`;
|
|
||||||
textWithLinks = textWithLinks.replace(matching[0], newLink)
|
|
||||||
}
|
|
||||||
details.innerHTML = textWithLinks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (innerItems){
|
|
||||||
for (const innerItem of innerItems){
|
|
||||||
const linkRegex = /TYPE99(\w+.)99TYPE/g
|
|
||||||
const listItems = innerItem.getElementsByTagName("li")
|
|
||||||
|
|
||||||
for (const li of listItems){
|
|
||||||
const mtypeExists = li.textContent?.match(linkRegex)
|
|
||||||
if (!mtypeExists || !li.textContent){
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const linkMatch = [...li.textContent.matchAll(linkRegex)]
|
|
||||||
let textWithLinks = li.textContent;
|
|
||||||
for (const matching of linkMatch) {
|
|
||||||
if (li.textContent.indexOf(matching[0]) === -1){
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const linkObject = getQMLTypeLinkObject(matching[1]);
|
|
||||||
const link = getQMLTypeLink(linkObject);
|
|
||||||
const icon = linkObject.mtype ? getIconForLink(linkObject.mtype, false) : null;
|
|
||||||
|
|
||||||
// for signal
|
|
||||||
const bracketString = getIconForLink("func", false)
|
|
||||||
|
|
||||||
const newLink = `<span class="type${linkObject.mtype}-link typedata-link">${icon ? icon : ""}<a href=${link}>${linkObject.mname || linkObject.name}</a>${linkObject.mtype === "signal" ? bracketString : ""}</span>`;
|
|
||||||
textWithLinks = textWithLinks.replace(matching[0], newLink)
|
|
||||||
}
|
|
||||||
li.innerHTML = textWithLinks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,21 +0,0 @@
|
||||||
---
|
|
||||||
---
|
|
||||||
<script>
|
|
||||||
import { codeToHtml } from "shiki";
|
|
||||||
const injectedMd = document.getElementById("injectedMd");
|
|
||||||
if (injectedMd) {
|
|
||||||
const preElements = document.getElementsByTagName("pre");
|
|
||||||
for (const pre of preElements) {
|
|
||||||
if (pre.textContent){
|
|
||||||
const innerText = pre.innerText;
|
|
||||||
pre.outerHTML =
|
|
||||||
await codeToHtml(
|
|
||||||
innerText,
|
|
||||||
{
|
|
||||||
lang: "qml", "theme":"material-theme-ocean"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -3,18 +3,15 @@ import type {
|
||||||
QMLTypeLinkObject,
|
QMLTypeLinkObject,
|
||||||
QuickshellFunction,
|
QuickshellFunction,
|
||||||
} from "@config/io/types";
|
} from "@config/io/types";
|
||||||
import {
|
import { getQMLTypeLink } from "@config/io/helpers";
|
||||||
parseMarkdown,
|
|
||||||
getQMLTypeLink,
|
|
||||||
} from "@config/io/helpers";
|
|
||||||
import { Tag } from "@icons";
|
import { Tag } from "@icons";
|
||||||
|
import TypeDetails from "./TypeDetails.astro"
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
funcData: QuickshellFunction[];
|
funcData: QuickshellFunction[];
|
||||||
title: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { funcData, title } = Astro.props;
|
const { funcData } = Astro.props;
|
||||||
---
|
---
|
||||||
<ul class="typedata typefuncs">
|
<ul class="typedata typefuncs">
|
||||||
{
|
{
|
||||||
|
@ -51,9 +48,7 @@ const { funcData, title } = Astro.props;
|
||||||
)
|
)
|
||||||
:null
|
:null
|
||||||
}
|
}
|
||||||
<section class="typedata-details">
|
<TypeDetails markdown={item.details} />
|
||||||
<div class="typedata-detailsdata" set:html={parseMarkdown(item.details, title)}/>
|
|
||||||
</section>
|
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
---
|
---
|
||||||
import {
|
import { getQMLTypeLink } from "@config/io/helpers";
|
||||||
parseMarkdown,
|
|
||||||
getQMLTypeLink,
|
|
||||||
} from "@config/io/helpers";
|
|
||||||
import type {
|
import type {
|
||||||
QMLTypeLinkObject,
|
QMLTypeLinkObject,
|
||||||
QuickshellProps,
|
QuickshellProps,
|
||||||
} from "@config/io/types";
|
} from "@config/io/types";
|
||||||
import { Tag, Flag } from "@icons";
|
import { Tag, Flag } from "@icons";
|
||||||
|
|
||||||
|
import TypeDetails from "./TypeDetails.astro"
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
propsKeys: string[];
|
propsKeys: string[];
|
||||||
propsData: QuickshellProps;
|
propsData: QuickshellProps;
|
||||||
title: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { propsKeys, propsData, title } = Astro.props;
|
const { propsKeys, propsData } = Astro.props;
|
||||||
---
|
---
|
||||||
<ul class="typedata typeprops">
|
<ul class="typedata typeprops">
|
||||||
{
|
{
|
||||||
|
@ -73,9 +71,7 @@ const { propsKeys, propsData, title } = Astro.props;
|
||||||
</p>
|
</p>
|
||||||
):null
|
):null
|
||||||
}
|
}
|
||||||
<section class="typedata-details">
|
<TypeDetails markdown={propData.details} />
|
||||||
<div id="injectedMd" class="typedata-detailsdata" set:html={parseMarkdown(propData.details, title)} />
|
|
||||||
</section>
|
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
---
|
---
|
||||||
import type { QuickshellSignal } from "@config/io/types";
|
import type { QuickshellSignal } from "@config/io/types";
|
||||||
import { Tag, PowerCord } from "@icons";
|
import { Tag, PowerCord } from "@icons";
|
||||||
import { parseMarkdown } from "@config/io/helpers";
|
import TypeDetails from "./TypeDetails.astro";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
signalKeys: string[];
|
signalKeys: string[];
|
||||||
signalsData: QuickshellSignal;
|
signalsData: QuickshellSignal;
|
||||||
title: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { signalKeys, signalsData, title } = Astro.props;
|
const { signalKeys, signalsData } = Astro.props;
|
||||||
---
|
---
|
||||||
<ul class="typedata typesignals">
|
<ul class="typedata typesignals">
|
||||||
{
|
{
|
||||||
|
@ -44,9 +43,7 @@ const { signalKeys, signalsData, title } = Astro.props;
|
||||||
</p>
|
</p>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
<section class="typedata-details">
|
<TypeDetails markdown={signalData.details} />
|
||||||
<div class="typedata-detailsdata" set:html={parseMarkdown(signalData.details, title)} />
|
|
||||||
</section>
|
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
14
src/components/type/TypeDetails.astro
Normal file
14
src/components/type/TypeDetails.astro
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
import { processQsMarkdown } from "@config/io/helpers"
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
markdown?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const { markdown } = Astro.props;
|
||||||
|
|
||||||
|
const html = markdown ? await processQsMarkdown(markdown) : null;
|
||||||
|
---
|
||||||
|
<section class="typedata-details">
|
||||||
|
{html ? <div class="typedata-detailsdata" set:html={html} /> : <em>No details provided</em>}
|
||||||
|
</section>
|
|
@ -1,15 +1,14 @@
|
||||||
---
|
---
|
||||||
import type { QuickshellVariant } from "@config/io/types";
|
import type { QuickshellVariant } from "@config/io/types";
|
||||||
import { FourDiamonds } from "../icons";
|
import { FourDiamonds } from "../icons";
|
||||||
import { parseMarkdown } from "@src/config/io/helpers";
|
import TypeDetails from "./TypeDetails.astro";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
variantKeys: string[];
|
variantKeys: string[];
|
||||||
variantsData: QuickshellVariant;
|
variantsData: QuickshellVariant;
|
||||||
title: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { variantKeys, variantsData, title } = Astro.props;
|
const { variantKeys, variantsData } = Astro.props;
|
||||||
---
|
---
|
||||||
<ul class="typedata typevariants">
|
<ul class="typedata typevariants">
|
||||||
{
|
{
|
||||||
|
@ -34,9 +33,7 @@ const { variantKeys, variantsData, title } = Astro.props;
|
||||||
)
|
)
|
||||||
:null
|
:null
|
||||||
}
|
}
|
||||||
<section class="typedata-details">
|
<TypeDetails markdown={variantData.details} />
|
||||||
<div class="typedata-detailsdata" set:html={parseMarkdown(variantData.details, title)} />
|
|
||||||
</section>
|
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
import { unified } from "unified";
|
import * as markdownUtils from "./markdown.ts";
|
||||||
import remarkParse from "remark-parse";
|
|
||||||
import remarkRehype from "remark-rehype";
|
|
||||||
import rehypeStringify from "rehype-stringify";
|
|
||||||
import { remarkAlert } from "remark-github-blockquote-alert";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
// Flag,
|
// Flag,
|
||||||
|
@ -10,7 +6,8 @@ import {
|
||||||
Tag,
|
Tag,
|
||||||
FourDiamonds,
|
FourDiamonds,
|
||||||
RoundBrackets,
|
RoundBrackets,
|
||||||
} from "@icons";
|
// @icons breaks when imported indirectly from astro.config.mjs
|
||||||
|
} from "../../components/icons.tsx";
|
||||||
import type {
|
import type {
|
||||||
ConfigHeading,
|
ConfigHeading,
|
||||||
ConfigTOC,
|
ConfigTOC,
|
||||||
|
@ -78,21 +75,8 @@ export function groupRoutes(routes: RouteData[]): GroupedRoutes {
|
||||||
}, defaultValue);
|
}, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseMarkdown(text?: string, title?: string) {
|
export async function processQsMarkdown(markdown: string): Promise<string> {
|
||||||
if (!text) {
|
return await markdownUtils.processMarkdown(markdown);
|
||||||
return unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkRehype)
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
return unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkAlert)
|
|
||||||
.use(remarkRehype)
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQMLTypeLinkObject(unparsed: string) {
|
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;
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ import PreTheme from "@config/PreTheme.astro";
|
||||||
import Header from "@components/Header.astro";
|
import Header from "@components/Header.astro";
|
||||||
import Head from "@config/Head.astro";
|
import Head from "@config/Head.astro";
|
||||||
import Nav from "@components/navigation/sidebars/Nav.astro";
|
import Nav from "@components/navigation/sidebars/Nav.astro";
|
||||||
import CreateQMLCodeButtons from "@components/hooks/CreateQMLCodeButtons.astro";
|
|
||||||
import "@styles/global.css";
|
import "@styles/global.css";
|
||||||
import type { ConfigHeading } from "@src/components/navigation/sidebars/types";
|
import type { ConfigHeading } from "@src/components/navigation/sidebars/types";
|
||||||
import Footer from "@src/components/Footer.astro";
|
import Footer from "@src/components/Footer.astro";
|
||||||
|
@ -63,7 +62,6 @@ if (url[2]) {
|
||||||
<link rel="canonical" href={Astro.url} />
|
<link rel="canonical" href={Astro.url} />
|
||||||
<PreTheme />
|
<PreTheme />
|
||||||
<CreateCopyButtons />
|
<CreateCopyButtons />
|
||||||
<CreateQMLCodeButtons/>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="docslayout">
|
<body class="docslayout">
|
||||||
<Header headings={headings}/>
|
<Header headings={headings}/>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import {
|
import {
|
||||||
parseMarkdown,
|
processQsMarkdown,
|
||||||
getQMLTypeLink,
|
getQMLTypeLink,
|
||||||
} from "@config/io/helpers";
|
} from "@config/io/helpers";
|
||||||
import { generateTypeData } from "@config/io/generateTypeData";
|
import { generateTypeData } from "@config/io/generateTypeData";
|
||||||
|
@ -11,8 +11,6 @@ import Properties from "@components/type/Properties.astro";
|
||||||
import Functions from "@components/type/Functions.astro";
|
import Functions from "@components/type/Functions.astro";
|
||||||
import Signals from "@components/type/Signals.astro";
|
import Signals from "@components/type/Signals.astro";
|
||||||
import Variants from "@components/type/Variants.astro";
|
import Variants from "@components/type/Variants.astro";
|
||||||
import TransformMDCodeblocks from "@components/hooks/TransformMDCodeblocks.astro";
|
|
||||||
import TransformLinks from "@components/hooks/TransformLinks.astro";
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const routes = await generateTypeData();
|
const routes = await generateTypeData();
|
||||||
|
@ -51,11 +49,8 @@ const sidebarData = {
|
||||||
|
|
||||||
const superLink = data.super ? getQMLTypeLink(data.super) : null;
|
const superLink = data.super ? getQMLTypeLink(data.super) : null;
|
||||||
|
|
||||||
const details = parseMarkdown(data.details, route.name);
|
const details = data.details ? await processQsMarkdown(data.details) : null;
|
||||||
---
|
---
|
||||||
<TransformLinks/>
|
|
||||||
<TransformMDCodeblocks/>
|
|
||||||
|
|
||||||
<DocsLayout title={`${route.name} - ${route.type}`} description={data?.description ?? ""}>
|
<DocsLayout title={`${route.name} - ${route.type}`} description={data?.description ?? ""}>
|
||||||
<div class="docs">
|
<div class="docs">
|
||||||
<div class="typedocs-content">
|
<div class="typedocs-content">
|
||||||
|
@ -87,34 +82,30 @@ const details = parseMarkdown(data.details, route.name);
|
||||||
</span>
|
</span>
|
||||||
))}</div>
|
))}</div>
|
||||||
):null}
|
):null}
|
||||||
<span id="injectedMd" set:html={details}/>
|
{details ? <span set:html={details}/> : null}
|
||||||
{!details ? (<span class="toparse">{data.description}</span>):null}
|
{!details ? (<span class="toparse">{data.description}</span>):null}
|
||||||
</subheading>
|
</subheading>
|
||||||
{ data.properties && propsKeys ? (
|
{ data.properties && propsKeys ? (
|
||||||
<Properties
|
<Properties
|
||||||
propsData={data.properties}
|
propsData={data.properties}
|
||||||
propsKeys={propsKeys!}
|
propsKeys={propsKeys!}
|
||||||
title={route.name}
|
|
||||||
/>
|
/>
|
||||||
): null}
|
): null}
|
||||||
{ data.functions && data.functions.length > 0 ? (
|
{ data.functions && data.functions.length > 0 ? (
|
||||||
<Functions
|
<Functions
|
||||||
funcData={data.functions}
|
funcData={data.functions}
|
||||||
title={route.name}
|
|
||||||
/>
|
/>
|
||||||
): null}
|
): null}
|
||||||
{ data.signals && signalKeys ? (
|
{ data.signals && signalKeys ? (
|
||||||
<Signals
|
<Signals
|
||||||
signalsData={data.signals}
|
signalsData={data.signals}
|
||||||
signalKeys={signalKeys}
|
signalKeys={signalKeys}
|
||||||
title={route.name}
|
|
||||||
/>
|
/>
|
||||||
):null}
|
):null}
|
||||||
{ data.variants && variantKeys ? (
|
{ data.variants && variantKeys ? (
|
||||||
<Variants
|
<Variants
|
||||||
variantsData={data.variants}
|
variantsData={data.variants}
|
||||||
variantKeys={variantKeys}
|
variantKeys={variantKeys}
|
||||||
title={route.name}
|
|
||||||
/>
|
/>
|
||||||
):null}
|
):null}
|
||||||
</section>
|
</section>
|
||||||
|
|
17
yarn.lock
17
yarn.lock
|
@ -138,7 +138,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@astrojs/markdown-remark@npm:5.2.0":
|
"@astrojs/markdown-remark@npm:5.2.0, @astrojs/markdown-remark@npm:^5.1.0":
|
||||||
version: 5.2.0
|
version: 5.2.0
|
||||||
resolution: "@astrojs/markdown-remark@npm:5.2.0"
|
resolution: "@astrojs/markdown-remark@npm:5.2.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -4081,7 +4081,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"hast-util-from-html@npm:^2.0.0, hast-util-from-html@npm:^2.0.1":
|
"hast-util-from-html@npm:^2.0.0, hast-util-from-html@npm:^2.0.1, hast-util-from-html@npm:^2.0.3":
|
||||||
version: 2.0.3
|
version: 2.0.3
|
||||||
resolution: "hast-util-from-html@npm:2.0.3"
|
resolution: "hast-util-from-html@npm:2.0.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6302,6 +6302,7 @@ __metadata:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ark-ui/solid": "npm:^3.5.0"
|
"@ark-ui/solid": "npm:^3.5.0"
|
||||||
"@astrojs/check": "npm:^0.9.3"
|
"@astrojs/check": "npm:^0.9.3"
|
||||||
|
"@astrojs/markdown-remark": "npm:^5.1.0"
|
||||||
"@astrojs/mdx": "npm:^3.1.7"
|
"@astrojs/mdx": "npm:^3.1.7"
|
||||||
"@astrojs/solid-js": "npm:^4.4.2"
|
"@astrojs/solid-js": "npm:^4.4.2"
|
||||||
"@astrojs/ts-plugin": "npm:^1.10.2"
|
"@astrojs/ts-plugin": "npm:^1.10.2"
|
||||||
|
@ -6311,17 +6312,15 @@ __metadata:
|
||||||
"@types/node": "npm:^20.14.11"
|
"@types/node": "npm:^20.14.11"
|
||||||
astro: "npm:^4.15.9"
|
astro: "npm:^4.15.9"
|
||||||
astro-breadcrumbs: "npm:^2.3.1"
|
astro-breadcrumbs: "npm:^2.3.1"
|
||||||
|
hast-util-from-html: "npm:^2.0.3"
|
||||||
node: "npm:22.7.0"
|
node: "npm:22.7.0"
|
||||||
pagefind: "npm:^1.1.1"
|
pagefind: "npm:^1.1.1"
|
||||||
rehype-stringify: "npm:^10.0.1"
|
|
||||||
remark-github-blockquote-alert: "npm:^1.2.1"
|
remark-github-blockquote-alert: "npm:^1.2.1"
|
||||||
remark-parse: "npm:^11.0.0"
|
|
||||||
remark-rehype: "npm:^11.1.1"
|
|
||||||
shiki: "npm:^1.11.0"
|
|
||||||
solid-devtools: "npm:^0.30.1"
|
solid-devtools: "npm:^0.30.1"
|
||||||
solid-js: "npm:^1.8.18"
|
solid-js: "npm:^1.8.18"
|
||||||
typescript: "npm:^5.5.3"
|
typescript: "npm:^5.5.3"
|
||||||
unified: "npm:^11.0.5"
|
unified: "npm:^11.0.5"
|
||||||
|
unist-util-visit: "npm:^5.0.0"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
@ -6382,7 +6381,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"rehype-stringify@npm:^10.0.0, rehype-stringify@npm:^10.0.1":
|
"rehype-stringify@npm:^10.0.0":
|
||||||
version: 10.0.1
|
version: 10.0.1
|
||||||
resolution: "rehype-stringify@npm:10.0.1"
|
resolution: "rehype-stringify@npm:10.0.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6473,7 +6472,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"remark-rehype@npm:^11.0.0, remark-rehype@npm:^11.1.0, remark-rehype@npm:^11.1.1":
|
"remark-rehype@npm:^11.0.0, remark-rehype@npm:^11.1.0":
|
||||||
version: 11.1.1
|
version: 11.1.1
|
||||||
resolution: "remark-rehype@npm:11.1.1"
|
resolution: "remark-rehype@npm:11.1.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6830,7 +6829,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"shiki@npm:^1.10.3, shiki@npm:^1.11.0, shiki@npm:^1.16.2":
|
"shiki@npm:^1.10.3, shiki@npm:^1.16.2":
|
||||||
version: 1.20.0
|
version: 1.20.0
|
||||||
resolution: "shiki@npm:1.20.0"
|
resolution: "shiki@npm:1.20.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in a new issue