version docs pages

This commit is contained in:
outfoxxed 2025-07-22 01:08:30 -07:00
parent 5865251560
commit 886bd957fb
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
30 changed files with 324 additions and 335 deletions

View file

@ -50,7 +50,7 @@ async function readVersionsData(): Promise<VersionsData> {
const versions = await Promise.all(data.versions.map(async (d: { name: string, types: any }) => ({
name: d.name,
modules: await readModulesData(d.types),
})))
})));
return {
versions,
@ -70,5 +70,5 @@ export function getVersionsData(): Promise<VersionsData> {
export async function getModulesData(): Promise<ModuleData[]> {
const versions = await getVersionsData();
return versions.versions.find(v => v.name == versions.default)!.modules;
return versions.versions.find(v => v.name === versions.default)!.modules;
}

View file

@ -96,7 +96,7 @@ export function getQMLTypeLinkObject(unparsed: string) {
return hashMap[index]();
}
export function getQMLTypeLink({
export function getQMLTypeLink(version: string, {
type,
module,
name,
@ -107,7 +107,7 @@ export function getQMLTypeLink({
return "#unknown";
}
const qtStart = "https://doc.qt.io/qt-6/";
const localStart = "/docs/types";
const localStart = `/docs/${version}/types`;
const hashMap = {
local: () => {

View file

@ -21,96 +21,109 @@ import {
getIconForLink,
} from "./helpers.ts";
const remarkParseAtTypes: RemarkPlugin<[]> = () => {
return (root: Md.Root): Md.Root => {
visit(root as Unist.Parent, (rawNode: Unist.Node) => {
if (
rawNode.type === "text" ||
(rawNode.type === "code" &&
(rawNode as Md.Code).lang === "qml")
) {
const node = rawNode as Md.Literal;
let currentVersion = "NOVERSION";
node.value = node.value.replace(
/@@((?<module>([A-Z]\w*\.)*)(?<type>([A-Z]\w*))(\.(?!\s|$))?)?((?<member>[a-z]\w*)((?<function>\(\))|(?<signal>\(s\)))?)?(?=[$.,;:)\s]|$)/g,
(_full, ...args) => {
type Capture = {
module: string | undefined;
type: string | undefined;
member: string | undefined;
function: string | undefined;
signal: string | undefined;
};
const remarkParseAtTypes: RemarkPlugin<[]> = () => (root: Md.Root): Md.Root => {
visit(root as Unist.Parent, (rawNode: Unist.Node) => {
if (
rawNode.type === "text" ||
(rawNode.type === "code" &&
(rawNode as Md.Code).lang === "qml")
) {
const node = rawNode as Md.Literal;
const groups = args.pop() as Capture;
node.value = node.value.replace(
/@@((?<module>([A-Z]\w*\.)*)(?<type>([A-Z]\w*))(\.(?!\s|$))?)?((?<member>[a-z]\w*)((?<function>\(\))|(?<signal>\(s\)))?)?(?=[$.,;:)\s]|$)/g,
(_full, ...args) => {
type Capture = {
module: string | undefined;
type: string | undefined;
member: string | undefined;
function: string | undefined;
signal: string | undefined;
};
if (groups.module) {
groups.module = groups.module.substring(
0,
groups.module.length - 1
);
const isQs = groups.module.startsWith("Quickshell");
groups.module = `99M${isQs ? "QS" : "QT_qml"}_${groups.module.replace(".", "_")}`;
} else groups.module = ""; // WARNING: rehype parser can't currently handle intra-module links
const groups = args.pop() as Capture;
groups.type = groups.type ? `99N${groups.type}` : "";
groups.member = groups.member
? `99V${groups.member}`
: "";
const type = groups.member
? `99T${groups.function ? "func" : groups.signal ? "signal" : "prop"}`
: "";
return `TYPE${groups.module}${groups.type}${groups.member}${type}99TYPE`;
}
);
}
});
return root;
};
if (groups.module) {
groups.module = groups.module.substring(
0,
groups.module.length - 1
);
const isQs = groups.module.startsWith("Quickshell");
groups.module = `99M${isQs ? "QS" : "QT_qml"}_${groups.module.replace(".", "_")}`;
} else groups.module = ""; // WARNING: rehype parser can't currently handle intra-module links
groups.type = groups.type ? `99N${groups.type}` : "";
groups.member = groups.member
? `99V${groups.member}`
: "";
const type = groups.member
? `99T${groups.function ? "func" : groups.signal ? "signal" : "prop"}`
: "";
return `TYPE${groups.module}${groups.type}${groups.member}${type}99TYPE`;
}
);
}
});
return root;
};
const rehypeRewriteTypelinks: RehypePlugin<[]> = () => {
return (root: Html.Root): Html.Root => {
visit(
root as Unist.Parent,
"text",
(node: Html.Text, index: number, parent: Html.Parent) => {
let changed = false;
const rehypeRewriteTypelinks: RehypePlugin<[]> = () => (root: Html.Root): Html.Root => {
visit(
root as Unist.Parent,
"text",
(node: Html.Text, index: number, parent: Html.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(currentVersion, 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 `<a class="type${linkObject.mtype}-link typedata-link" href=${link}>${icon ?? ""}${linkObject.name ?? ""}${hasDot ? "." : ""}${linkObject.mname ?? ""}${hasParens ? "()" : ""}</a>`;
}
);
return CONTINUE;
if (changed) {
const fragment = fromHtml(node.value, {
fragment: true,
});
parent.children.splice(index, 1, ...fragment.children);
return SKIP;
}
);
return root;
};
return CONTINUE;
}
);
return root;
};
const rehypeRewriteVersionedDoclinks: RehypePlugin<[]> = () => (root: Html.Root): Html.Root => {
visit(
root as Unist.Parent,
"element",
({ tagName, properties }: Html.Element) => {
if (tagName !== "a") return CONTINUE;
if (!(properties.href as string ?? "").startsWith("@docs")) return CONTINUE;
properties.href = `/docs/${currentVersion}/${(properties.href as string).slice(6)}`;
return CONTINUE;
}
);
return root;
};
const shikiRewriteTypelinks: ShikiTransformer = {
@ -123,7 +136,7 @@ const shikiRewriteTypelinks: ShikiTransformer = {
if (hasTypelinks) {
code.replace(regExp, (_full: string, match: string) => {
const linkObject = getQMLTypeLinkObject(match);
const link = getQMLTypeLink(linkObject);
const link = getQMLTypeLink(currentVersion, linkObject);
return `<a href=${link}>${linkObject.name ?? ""}</a>`;
});
}
@ -166,6 +179,7 @@ export const markdownConfig: AstroMarkdownOptions = {
{ idPropertyName: "id" },
],
rehypeRewriteTypelinks,
rehypeRewriteVersionedDoclinks,
],
};
@ -173,16 +187,18 @@ 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
version: string,
markdown: string,
): Promise<string> {
return (await (await getMarkdownProcessor()).render(markdown))
.code;
currentVersion = version;
const r = (await (await getMarkdownProcessor()).render(markdown)).code;
currentVersion = "NOVERSION";
return r;
}