version docs pages
This commit is contained in:
parent
5865251560
commit
21e175d3a6
31 changed files with 329 additions and 388 deletions
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { processMarkdown } from "@config/io/markdown";
|
||||
|
||||
const codeDesktop = await processMarkdown(`\`\`\`qml
|
||||
const codeDesktop = await processMarkdown("N/A", `\`\`\`qml
|
||||
// a standard desktop window
|
||||
FloatingWindow {
|
||||
Timer {
|
||||
|
@ -21,7 +21,7 @@ FloatingWindow {
|
|||
}
|
||||
\`\`\``);
|
||||
|
||||
const codeMobile = await processMarkdown(`\`\`\`qml
|
||||
const codeMobile = await processMarkdown("N/A", `\`\`\`qml
|
||||
// a standard desktop window
|
||||
FloatingWindow {
|
||||
Timer {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import "@pagefind/default-ui/css/ui.css";
|
||||
import magnifierIcon from "@icons/magnifier.svg?raw"
|
||||
---
|
||||
|
||||
<site-search class="search-wrapper">
|
||||
<button
|
||||
data-open-modal
|
||||
|
@ -52,7 +51,6 @@ import magnifierIcon from "@icons/magnifier.svg?raw"
|
|||
|
||||
<script>
|
||||
import { getQMLTypeLinkObject, getQMLTypeLink, getIconForLink } from '@src/config/io/helpers';
|
||||
|
||||
class SiteSearch extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -107,7 +105,7 @@ import { getQMLTypeLinkObject, getQMLTypeLink, getIconForLink } from '@src/confi
|
|||
if (match.length > 0){
|
||||
for (const matching of match) {
|
||||
const linkObject = getQMLTypeLinkObject(matching[1]);
|
||||
const link = getQMLTypeLink(linkObject);
|
||||
const link = getQMLTypeLink("NOVERSION", linkObject);
|
||||
const icon = linkObject.mtype ? getIconForLink(linkObject.mtype, false) : null;
|
||||
|
||||
// for signal
|
||||
|
|
|
@ -5,15 +5,18 @@ export interface Props {
|
|||
currentClass?: string;
|
||||
}
|
||||
|
||||
import { getModulesData } from "@config/io/generateTypeData";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
import type { TreeEntry } from "./Tree.astro";
|
||||
import Tree from "./Tree.astro";
|
||||
import Link from "./Link.astro";
|
||||
import VersionSelector from "./VersionSelector.astro"
|
||||
|
||||
const modules = await getModulesData();
|
||||
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const versions = await getVersionsData();
|
||||
const versionName = Astro.params.version;
|
||||
const modules = versions.versions.find(version => version.name === versionName)?.modules;
|
||||
|
||||
const currentPath = Astro.url.pathname.split('/').filter(s => s !== "");
|
||||
|
||||
const guidePages = await getCollection("guide");
|
||||
|
||||
interface NavTree {
|
||||
|
@ -22,8 +25,6 @@ interface NavTree {
|
|||
entries?: NavTree[],
|
||||
}
|
||||
|
||||
const currentPath = Astro.url.pathname.slice(1).split('/');
|
||||
|
||||
function mkTree(mount: string, pathIdx: number, { title, slug, entries }: NavTree): TreeEntry {
|
||||
const link = `${mount}/${slug}`;
|
||||
|
||||
|
@ -48,43 +49,67 @@ function genGuideNav(base: string): NavTree[] | undefined {
|
|||
return pages.length === 0 ? undefined : pages;
|
||||
}
|
||||
|
||||
const guide = mkTree("/docs", 1, {
|
||||
title: "Usage Guide",
|
||||
slug: "guide",
|
||||
entries: genGuideNav(""),
|
||||
});
|
||||
let versionedEntries;
|
||||
let versionsTree;
|
||||
|
||||
const types = mkTree("/docs", 1, {
|
||||
title: "Quickshell Types",
|
||||
slug: "types",
|
||||
entries: modules.map(module => ({
|
||||
title: module.name,
|
||||
slug: module.name,
|
||||
entries: module.types.map(type => ({
|
||||
title: type.name,
|
||||
slug: type.name,
|
||||
}))
|
||||
}))
|
||||
});
|
||||
if (versionName) {
|
||||
versionedEntries = {
|
||||
guide: mkTree(`/docs/${versionName}`, 2, {
|
||||
title: "Usage Guide",
|
||||
slug: "guide",
|
||||
entries: genGuideNav(""),
|
||||
}),
|
||||
types: mkTree(`/docs/${versionName}`, 2, {
|
||||
title: "Quickshell Types",
|
||||
slug: "types",
|
||||
entries: modules!.map(module => ({
|
||||
title: module.name,
|
||||
slug: module.name,
|
||||
entries: module.types.map(type => ({
|
||||
title: type.name,
|
||||
slug: type.name,
|
||||
}))
|
||||
}))
|
||||
}),
|
||||
};
|
||||
|
||||
versionsTree = {
|
||||
title: `Switch Version (${versionName})`,
|
||||
link: "#",
|
||||
entries: versions.versions.map(version => ({
|
||||
title: version.name,
|
||||
link: `/docs/${version.name}${Astro.url.pathname.slice(6 + versionName.length)}`,
|
||||
current: version.name == versionName,
|
||||
})),
|
||||
};
|
||||
}
|
||||
---
|
||||
<nav class="navtree">
|
||||
<VersionSelector title="Versions" link=`${Astro.currentLocale}` current/>
|
||||
<Link
|
||||
title="About Quickshell"
|
||||
title="About"
|
||||
link="/about"
|
||||
current={Astro.url.pathname === "/about"}
|
||||
/>
|
||||
<Tree {...guide}/>
|
||||
<Tree {...types}/>
|
||||
<Link
|
||||
title="QtQuick Types"
|
||||
link="https://doc.qt.io/qt-6/qtquick-qmlmodule.html"
|
||||
showIcon={true}
|
||||
/>
|
||||
<Link
|
||||
title="Quickshell Examples"
|
||||
link="https://git.outfoxxed.me/outfoxxed/quickshell-examples"
|
||||
showIcon={true}
|
||||
current={currentPath.length === 1 && currentPath[0] === "about"}
|
||||
/>
|
||||
{ versionedEntries && <Tree {...versionsTree as TreeEntry}/>}
|
||||
<hr/>
|
||||
{ versionedEntries && (
|
||||
<Tree {...versionedEntries.guide}/>
|
||||
<Tree {...versionedEntries.types}/>
|
||||
<Link
|
||||
title="QtQuick Types"
|
||||
link="https://doc.qt.io/qt-6/qtquick-qmlmodule.html"
|
||||
showIcon={true}
|
||||
/>
|
||||
<Link
|
||||
title="Quickshell Examples"
|
||||
link="https://git.outfoxxed.me/outfoxxed/quickshell-examples"
|
||||
showIcon={true}
|
||||
/>
|
||||
)}
|
||||
{ !versionedEntries && versions.versions.map(version => (
|
||||
<Link
|
||||
title={`Quickshell Documentation (${version.name})`}
|
||||
link={`/docs/${version.name}/guide`}
|
||||
/>
|
||||
))}
|
||||
</nav>
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
---
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import Link from './Link.astro';
|
||||
import Accordion from "@components/Accordion.astro"
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
link: string;
|
||||
current?: boolean;
|
||||
}
|
||||
interface VersionData {
|
||||
default: string;
|
||||
versions: {
|
||||
name: string;
|
||||
types: string;
|
||||
}[]
|
||||
}
|
||||
const versionFilePath = import.meta.env.VERSION_FILE_PATH;
|
||||
|
||||
if (!versionFilePath){
|
||||
throw new Error("no env var VERSION_FILE_PATH")
|
||||
}
|
||||
const absolutePath = path.resolve(process.cwd(), versionFilePath);
|
||||
const versionData:VersionData = JSON.parse(fs.readFileSync(absolutePath, 'utf-8'));
|
||||
|
||||
const { title, link, current } = Astro.props;
|
||||
---
|
||||
<Accordion class=`nav-component version-collapsible ${current ? "nav-current" : ""}` {...(!current ? { open: "_" } : {})}>
|
||||
<div slot="header">
|
||||
<span class="nav-component nav-item nav-link">
|
||||
versions
|
||||
</span>
|
||||
</div>
|
||||
<div class="version-select-menu">
|
||||
{versionData.versions.map((ver, _) => {
|
||||
return (
|
||||
<Link
|
||||
link={`${Astro.url.pathname}`}
|
||||
title=`${ver.name}`
|
||||
>
|
||||
{ver.name}
|
||||
</Link>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</Accordion>
|
|
@ -13,12 +13,13 @@ export interface Props {
|
|||
}
|
||||
|
||||
const { funcData } = Astro.props;
|
||||
const { version } = Astro.params;
|
||||
---
|
||||
<ul class="typedata typefuncs">
|
||||
{
|
||||
funcData.map(item => {
|
||||
const functionParams = item.params.length > 0 ? item.params.map((funcparam,index) => `${funcparam.name}${index !== item.params.length -1 ? ", ":""}`) : undefined
|
||||
const retTypeLink = getQMLTypeLink(item.ret as unknown as QMLTypeLinkObject)
|
||||
const retTypeLink = getQMLTypeLink(version!, item.ret as unknown as QMLTypeLinkObject)
|
||||
let genericType:string|undefined;
|
||||
let genericTypeLink:string|undefined;
|
||||
return (
|
||||
|
@ -37,7 +38,7 @@ const { funcData } = Astro.props;
|
|||
<p class="typedata-params typefunc-params">
|
||||
{
|
||||
item.params.map(param => {
|
||||
const paramTypeLink = getQMLTypeLink(param.type);
|
||||
const paramTypeLink = getQMLTypeLink(version!, param.type);
|
||||
return (
|
||||
<span class="typedata-param typefunc-param">
|
||||
<Tag client:idle/>
|
||||
|
|
|
@ -14,6 +14,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const { props } = Astro.props;
|
||||
const { version } = Astro.params;
|
||||
---
|
||||
<ul class="typedata typeprops">
|
||||
{
|
||||
|
@ -27,12 +28,12 @@ const { props } = Astro.props;
|
|||
typeLink = "#"
|
||||
linkText = `[${Object.keys(gadget).toString()}]`
|
||||
} else {
|
||||
typeLink = getQMLTypeLink(propData.type)
|
||||
typeLink = getQMLTypeLink(version!, propData.type)
|
||||
linkText = propData.type.name || propData.type.type
|
||||
}
|
||||
if (propData.type.of) {
|
||||
genericType = propData.type.of.name;
|
||||
genericTypeLink = getQMLTypeLink(propData.type.of)
|
||||
genericTypeLink = getQMLTypeLink(version!, propData.type.of)
|
||||
}
|
||||
return (
|
||||
<li id={ name } class="typedata-root typeprop-root">
|
||||
|
@ -54,7 +55,7 @@ const { props } = Astro.props;
|
|||
return (
|
||||
<span class="typedata-param typefunc-param">
|
||||
<Tag client:idle/>
|
||||
{key}:<span><a href=`${getQMLTypeLink(gadgetData as unknown as QMLTypeLinkObject)}`>{gadgetData.name}</a></span>
|
||||
{key}:<span><a href={getQMLTypeLink(version!, gadgetData as unknown as QMLTypeLinkObject)}>{gadgetData.name}</a></span>
|
||||
</span>
|
||||
)
|
||||
})
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
import { getQMLTypeLink } from "@config/io/helpers";
|
||||
import type { QuickshellSignal } from "@config/io/types";
|
||||
import { Tag } from "@icons";
|
||||
import TypeDetails from "./TypeDetails.astro";
|
||||
|
@ -9,6 +10,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
const { signals } = Astro.props;
|
||||
const { version } = Astro.params;
|
||||
---
|
||||
<ul class="typedata typesignals">
|
||||
{
|
||||
|
@ -36,8 +38,7 @@ const { signals } = Astro.props;
|
|||
<span class="typedata-param typesignal-param">
|
||||
<Tag client:idle/>
|
||||
{param.name}<span class="type-datatype">: <a
|
||||
href=""
|
||||
target="_blank"
|
||||
href={getQMLTypeLink(version!, param.type)}
|
||||
>{param.type.name}</a></span>
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -6,8 +6,9 @@ export interface Props {
|
|||
}
|
||||
|
||||
const { markdown } = Astro.props;
|
||||
const { version } = Astro.params;
|
||||
|
||||
const html = markdown ? await processMarkdown(markdown) : null;
|
||||
const html = markdown ? await processMarkdown(version!, markdown) : null;
|
||||
---
|
||||
<section class="typedata-details">
|
||||
{html ? <div class="typedata-detailsdata" set:html={html} /> : <em>No details provided</em>}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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: () => {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,5 @@ const guide = defineCollection({
|
|||
index: z.number(),
|
||||
}),
|
||||
});
|
||||
const version = defineCollection({
|
||||
loader: glob({ pattern: "**/*", base: "src/docs" }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
index: z.number(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { guide, version };
|
||||
export const collections = { guide };
|
||||
|
|
|
@ -4,7 +4,7 @@ index: 2
|
|||
---
|
||||
This page will walk you through the process of creating a simple bar/panel, and
|
||||
introduce you to all the basic concepts involved. You can use the
|
||||
[QML Language Reference](/docs/guide/qml-language) to learn about the syntax
|
||||
[QML Language Reference](@docs/guide/qml-language) to learn about the syntax
|
||||
of the QML language.
|
||||
|
||||
> [!NOTE]
|
||||
|
@ -65,7 +65,7 @@ The above example creates a bar/panel on your currently focused monitor with
|
|||
a centered piece of [text](https://doc.qt.io/qt-6/qml-qtquick-text.html).
|
||||
It will also reserve space for itself on your monitor.
|
||||
|
||||
More information about available properties is available in the [type reference](/docs/types/Quickshell/PanelWindow).
|
||||
More information about available properties is available in the [type reference](@docs/types/Quickshell/PanelWindow).
|
||||
|
||||
## Running a process
|
||||
|
||||
|
@ -75,11 +75,11 @@ To start with, let's make a clock. To get the time, we'll use the `date` command
|
|||
> [!note/Note]
|
||||
> Quickshell can do more than just run processes. Read until the end for more information.
|
||||
|
||||
We can use a [Process](/docs/types/quickshell.io/process) object to run commands
|
||||
We can use a [Process](@docs/types/quickshell.io/process) object to run commands
|
||||
and a @@Quickshell.Io.StdioCollector to read their output.
|
||||
|
||||
We'll listen to the @@Quickshell.Io.StdioCollector.streamFinished(s) signal with
|
||||
a [signal handler](/docs/configuration/qml-overview/#signal-handlers)
|
||||
a [signal handler](@docs/guide/qml-language/#signal-handlers)
|
||||
to update the text on the clock.
|
||||
|
||||
> [!note/Note]
|
||||
|
@ -252,14 +252,12 @@ import QtQuick
|
|||
}
|
||||
```
|
||||
|
||||
<span class="small">
|
||||
See also: [Property Bindings](/docs/configuration/qml-overview/#property-bindings),
|
||||
[Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
|
||||
</span>
|
||||
See also: [Property Bindings](@docs/guide/qml-language#property-bindings),
|
||||
[Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
|
||||
|
||||
With this example, bars will be created and destroyed as you plug and unplug them,
|
||||
due to the reactive nature of the @@Quickshell.Quickshell.screens property.
|
||||
(See: [Reactive Bindings](/docs/configuration/qml-overview/#reactive-bindings).)
|
||||
(See: [Reactive Bindings](@docs/guide/qml-language#reactive-bindings).)
|
||||
|
||||
Now there's an important problem you might have noticed: when the window
|
||||
is created multiple times, we also make a new Process and Timer, which makes the
|
||||
|
@ -336,10 +334,10 @@ outside of its component. Remember, components can be created _any number of tim
|
|||
including zero, so `clock` may not exist or there may be more than one, meaning
|
||||
there isn't an object to refer to from here.
|
||||
|
||||
We can fix it with a [Property Definition](/docs/configuration/qml-overview/#property-definitions).
|
||||
We can fix it with a [Property Definition](@docs/guide/qml-language#property-definitions).
|
||||
|
||||
We can define a property inside of the ShellRoot and reference it from the clock
|
||||
text instead. Due to QML's [Reactive Bindings](/docs/configuration/qml-overview/#reactive-bindings),
|
||||
text instead. Due to QML's [Reactive Bindings](@docs/guide/qml-language#reactive-bindings),
|
||||
the clock text will be updated when we update the property for every clock that
|
||||
currently exists.
|
||||
|
||||
|
@ -409,7 +407,7 @@ above code; however, we can make it more concise:
|
|||
component wrapping the window and place the window directly into the
|
||||
`delegate` property.
|
||||
2. The @@Quickshell.Variants.delegate property is a
|
||||
[Default Property](/docs/configuration/qml-overview/#the-default-property),
|
||||
[Default Property](@docs/guide/qml-language#the-default-property),
|
||||
which means we can skip the `delegate:` part of the assignment.
|
||||
We're already using the default property of @@Quickshell.ShellRoot to store our
|
||||
Variants, Process, and Timer components among other things.
|
||||
|
@ -533,11 +531,11 @@ import QtQuick
|
|||
}
|
||||
```
|
||||
|
||||
<span class="small">See also: [Scope](/docs/types/Quickshell/Scope/)</span>
|
||||
See also: @@Quickshell.Scope
|
||||
|
||||
Any qml file that starts with an uppercase letter can be referenced this way.
|
||||
We can bring in other folders as well using
|
||||
[import statements](/docs/configuration/qml-overview/#explicit-imports).
|
||||
[import statements](@docs/guide/qml-language#explicit-imports).
|
||||
|
||||
Now what about breaking out the clock? This is a bit more complex because
|
||||
the clock component in the bar need to be dealt with, as well as the necessary
|
||||
|
@ -683,7 +681,7 @@ import Quickshell
|
|||
|
||||
Now you might be thinking, why do we need the `Time` type in
|
||||
our bar file, and the answer is we don't. We can make `Time`
|
||||
a [Singleton](/docs/configuration/qml-overview/#singletons).
|
||||
a [Singleton](@docs/guide/qml-language#singletons).
|
||||
|
||||
A singleton object has only one instance, and is accessible from
|
||||
any scope.
|
|
@ -7,10 +7,7 @@ import Collapsible from "@components/Collapsible.astro";
|
|||
Quickshell is configured using the Qt Modeling Language, or QML.
|
||||
This page explains what you need to know about QML to start using Quickshell.
|
||||
|
||||
<span class="small">
|
||||
See also: [Qt Documentation: QML
|
||||
Tutorial](https://doc.qt.io/qt-6/qml-tutorial.html)
|
||||
</span>
|
||||
See also: [Qt Documentation: QML Tutorial](https://doc.qt.io/qt-6/qml-tutorial.html)
|
||||
|
||||
## Structure
|
||||
|
||||
|
@ -143,10 +140,7 @@ import QtQuick.Layouts 6.0 as L
|
|||
import "jsfile.js" as JsFile
|
||||
```
|
||||
|
||||
<span class="small">
|
||||
See also: [Qt Documentation: Import
|
||||
syntax](https://doc.qt.io/qt-6/qtqml-syntax-imports.html)
|
||||
</span>
|
||||
See also: [Qt Documentation: Import syntax](https://doc.qt.io/qt-6/qtqml-syntax-imports.html)
|
||||
|
||||
#### Implicit imports
|
||||
|
||||
|
@ -222,7 +216,7 @@ All property bindings are [_reactive_](#reactive-bindings). This means that when
|
|||
property the expression depends on is updated, the expression is re-evaluated and the property
|
||||
is updated accordingly.
|
||||
|
||||
<span class="small">See also [Reactive bindings](#reactive-bindings) for more information</span>
|
||||
See also [Reactive bindings](#reactive-bindings) for more information
|
||||
|
||||
##### Property definitions
|
||||
|
||||
|
@ -374,10 +368,7 @@ all other objects, you should refer to them by id when accessing properties.
|
|||
}
|
||||
```
|
||||
|
||||
<span class="small">
|
||||
See also: [Qt Documentation: Scope and Naming
|
||||
Resolution](https://doc.qt.io/qt-6/qtqml-documents-scope.html)
|
||||
</span>
|
||||
See also: [Qt Documentation: Scope and Naming Resolution](https://doc.qt.io/qt-6/qtqml-documents-scope.html)
|
||||
|
||||
#### Functions
|
||||
|
||||
|
@ -486,10 +477,7 @@ A signal is basically an event emitter you can connect to and receive updates fr
|
|||
They can be declared everywhere [properties](#properties) and [functions](#functions)
|
||||
can, and follow the same [scoping rules](#property-access-scopes).
|
||||
|
||||
<span class="small">
|
||||
See also: [Qt Documentation: Signal and Handler Event
|
||||
System](https://doc.qt.io/qt-6/qtqml-syntax-signals.html)
|
||||
</span>
|
||||
See also: [Qt Documentation: Signal and Handler Event System](https://doc.qt.io/qt-6/qtqml-syntax-signals.html)
|
||||
|
||||
##### Signal definitions
|
||||
|
||||
|
@ -529,11 +517,8 @@ or signal when the signal is emitted.
|
|||
}
|
||||
```
|
||||
|
||||
<span class="small">
|
||||
`Component.onCompleted` will be addressed later in [Attached
|
||||
Properties](#attached-properties), but for now, just know that it runs
|
||||
immediately once the object is fully initialized.
|
||||
</span>
|
||||
`Component.onCompleted` will be addressed later in [Attached Properties](#attached-properties),
|
||||
but for now, just know that it runs immediately once the object is fully initialized.
|
||||
|
||||
When the button is clicked, the button emits the @@QtQuick.Controls.Button.clicked(s)
|
||||
signal, which we connected to `updateText`. The signal then invokes `updateText`,
|
||||
|
@ -788,11 +773,9 @@ files.
|
|||
|
||||
### Reactive bindings
|
||||
|
||||
<span class="small">
|
||||
This section assumes knowledge of: [Properties](#properties),
|
||||
[Signals](#signals), and [Functions](#functions). See also the [Qt
|
||||
documentation](https://doc.qt.io/qt-6/qtqml-syntax-propertybinding.html).
|
||||
</span>
|
||||
This section assumes knowledge of: [Properties](#properties), [Signals](#signals),
|
||||
and [Functions](#functions).
|
||||
See also the [Qt documentation](https://doc.qt.io/qt-6/qtqml-syntax-propertybinding.html).
|
||||
|
||||
Reactivity is when a property is updated based on updates to another property.
|
||||
Every time one of the properties in a binding change, the binding is re-evaluated
|
|
@ -19,38 +19,30 @@ interface Props {
|
|||
}
|
||||
|
||||
const { title, description, headings, type } = Astro.props;
|
||||
const url = Astro.url.pathname.split("/");
|
||||
let url = Astro.url.pathname.split("/").filter(s => s !== "");
|
||||
|
||||
const customBreadcrumbs = [
|
||||
{
|
||||
index: 0,
|
||||
text: "custom",
|
||||
href: "/",
|
||||
},
|
||||
{
|
||||
text: url[1].slice(0, 1)[0].toUpperCase() + url[1].slice(1),
|
||||
href: `/${url[1]}`,
|
||||
},
|
||||
];
|
||||
const breadcrumbs = [{
|
||||
text: "custom",
|
||||
href: "/",
|
||||
}];
|
||||
|
||||
if (url[2]) {
|
||||
customBreadcrumbs.push({
|
||||
text: url[2].slice(0, 1)[0].toUpperCase() + url[2].slice(1),
|
||||
href: `/${url[1]}/${url[2]}`,
|
||||
let linkPath = "";
|
||||
if (url[0] === "docs") {
|
||||
const { version } = Astro.params;
|
||||
linkPath = `/docs/${version}`;
|
||||
breadcrumbs.push({
|
||||
text: `Docs (${version})`,
|
||||
href: linkPath,
|
||||
});
|
||||
url = url.slice(2);
|
||||
}
|
||||
|
||||
for (const segment of url) {
|
||||
linkPath += `/${segment}`;
|
||||
breadcrumbs.push({
|
||||
text: segment[0].toUpperCase() + segment.slice(1),
|
||||
href: linkPath,
|
||||
});
|
||||
if (url[3]) {
|
||||
customBreadcrumbs.push({
|
||||
text: url[3].slice(0, 1)[0].toUpperCase() + url[3].slice(1),
|
||||
href: `/${url[1]}/${url[2]}/${url[3]}`,
|
||||
});
|
||||
if (url[4]) {
|
||||
customBreadcrumbs.filter((_, index) => index !== 4);
|
||||
customBreadcrumbs.push({
|
||||
text: url[4],
|
||||
href: `/${url[1]}/${url[2]}/${url[3]}/${url[4]}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
---
|
||||
|
||||
|
@ -65,7 +57,7 @@ if (url[2]) {
|
|||
<div class="docslayout-root">
|
||||
<Nav mobile={false}/>
|
||||
<div class="docslayout-inner" data-pagefind-body>
|
||||
<Breadcrumbs crumbs={customBreadcrumbs} linkTextFormat="sentence" truncated={true} data-pagefind-ignore>
|
||||
<Breadcrumbs crumbs={breadcrumbs} linkTextFormat="sentence" truncated={true} data-pagefind-ignore>
|
||||
<svg
|
||||
slot="index"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
27
src/pages/docs/[version]/guide/[...id].astro
Normal file
27
src/pages/docs/[version]/guide/[...id].astro
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
import GuideLayout from "@layouts/GuideLayout.astro";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
import { processMarkdown } from "@config/io/markdown";
|
||||
|
||||
import { getCollection, render } from "astro:content";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const { versions } = await getVersionsData();
|
||||
const guidePages = await getCollection("guide");
|
||||
|
||||
// versioned guides unhandled for now
|
||||
return versions.flatMap(version => guidePages.map(page => ({
|
||||
params: { version: version.name, id: page.id == "index" ? "/" : page.id },
|
||||
props: { version, page },
|
||||
})));
|
||||
}
|
||||
|
||||
const { version, page } = Astro.props;
|
||||
const { headings } = await render(page);
|
||||
|
||||
// we can't use 'Content' because there isn't a way to pass in a version
|
||||
const html = await processMarkdown(version.name, page.body!);
|
||||
---
|
||||
<GuideLayout title={page.data.title} description="" headings={headings}>
|
||||
<Fragment set:html={html}/>
|
||||
</GuideLayout>
|
20
src/pages/docs/[version]/index.astro
Normal file
20
src/pages/docs/[version]/index.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import DocsLayout from "@layouts/DocsLayout.astro";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return (await getVersionsData()).versions.map(version => ({
|
||||
params: { version: version.name },
|
||||
props: { version },
|
||||
}));
|
||||
}
|
||||
|
||||
const { version } = Astro.props;
|
||||
---
|
||||
<DocsLayout title="Quickshell Docs" description="Quickshell Documentation">
|
||||
<h2>Docs</h2>
|
||||
<div class="root-nav">
|
||||
<h3><a href={`/docs/${version.name}/guide`}>Usage Guide</a></h3>
|
||||
<h3><a href={`/docs/${version.name}/types`}>Type Definitions</a></h3>
|
||||
</div>
|
||||
</DocsLayout>
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { getQMLTypeLink } from "@config/io/helpers";
|
||||
import { processMarkdown } from "@config/io/markdown";
|
||||
import { getModulesData } from "@config/io/generateTypeData";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
import DocsLayout from "@layouts/DocsLayout.astro";
|
||||
import TOC from "@components/navigation/sidebars/TOC.astro";
|
||||
import Properties from "@components/type/Properties.astro";
|
||||
|
@ -11,19 +11,22 @@ import Variants from "@components/type/Variants.astro";
|
|||
import Badge from "@components/Badge.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const modules = await getModulesData();
|
||||
return modules.flatMap(module => module.types.map(type => ({
|
||||
params: { module: module.name, type: type.name },
|
||||
props: { module, type }
|
||||
})));
|
||||
return (await getVersionsData()).versions.flatMap(version => {
|
||||
return version.modules.flatMap(module => {
|
||||
return module.types.map(type => ({
|
||||
params: { version: version.name, module: module.name, type: type.name },
|
||||
props: { version, module, type },
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const { module, type } = Astro.props;
|
||||
const { version, module, type } = Astro.props;
|
||||
|
||||
const superLink = type.super ? getQMLTypeLink(type.super) : null;
|
||||
const superLink = type.super ? getQMLTypeLink(version.name, type.super) : null;
|
||||
|
||||
const details = type.details
|
||||
? await processMarkdown(type.details)
|
||||
? await processMarkdown(version.name, type.details)
|
||||
: null;
|
||||
---
|
||||
<DocsLayout title={`${module.name} - ${type.name}`} description={type.description ?? ""} type={type}>
|
||||
|
@ -57,17 +60,17 @@ const details = type.details
|
|||
{details ? <span class="parsedMD" set:html={details}/> : (<span class="toparse">{type.description}</span>)}
|
||||
</subheading>
|
||||
{ Object.keys(type.properties ?? {}).length != 0 && (
|
||||
<h2>Properties <a href="/docs/guide/qml-language#properties">[?]</a></h2>
|
||||
<h2>Properties <a href={`/docs/${version.name}/guide/qml-language#properties`}>[?]</a></h2>
|
||||
<Properties props={type.properties!}/>
|
||||
)}
|
||||
{ (type.functions?.length ?? 0) != 0 && (
|
||||
<h2>Functions <a href="/docs/guide/qml-language#functions">[?]</a></h2>
|
||||
<h2>Functions <a href={`/docs/${version.name}guide/qml-language#functions`}>[?]</a></h2>
|
||||
<Functions
|
||||
funcData={type.functions!}
|
||||
/>
|
||||
)}
|
||||
{ Object.keys(type.signals ?? {}).length != 0 && (
|
||||
<h2>Signals <a href="/docs/guide/qml-language#signals">[?]</a></h2>
|
||||
<h2>Signals <a href={`/docs/${version.name}guide/qml-language#signals`}>[?]</a></h2>
|
||||
<Signals
|
||||
signals={type.signals!}
|
||||
/>
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
import DocsLayout from "@layouts/DocsLayout.astro";
|
||||
import { getModulesData } from "@config/io/generateTypeData";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
import { processMarkdown } from "@src/config/io/markdown";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const modules = await getModulesData();
|
||||
return modules.map(module => ({
|
||||
params: { module: module.name },
|
||||
props: { module },
|
||||
}));
|
||||
return (await getVersionsData()).versions.flatMap(version => {
|
||||
return version.modules.map(module => ({
|
||||
params: { version: version.name, module: module.name },
|
||||
props: { version, module },
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
const { module } = Astro.props;
|
||||
const { version, module } = Astro.props;
|
||||
const details = module.details
|
||||
? await processMarkdown(module.details)
|
||||
? await processMarkdown(version.name, module.details)
|
||||
: null;
|
||||
---
|
||||
|
||||
|
@ -30,7 +31,7 @@ const details = module.details
|
|||
{module.types.map(type =>
|
||||
(
|
||||
<div class="root-nav-entry">
|
||||
<a class="root-nav-link" href={`/docs/types/${module.name}/${type.name}`}>
|
||||
<a class="root-nav-link" href={`/docs/${version.name}/types/${module.name}/${type.name}`}>
|
||||
{type.name}
|
||||
</a>
|
||||
<span class="root-nav-desc">{type.description}</span>
|
|
@ -1,8 +1,15 @@
|
|||
---
|
||||
import DocsLayout from "@layouts/DocsLayout.astro";
|
||||
import { getModulesData } from "@config/io/generateTypeData";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
|
||||
const modules = await getModulesData();
|
||||
export async function getStaticPaths() {
|
||||
return (await getVersionsData()).versions.map(version => ({
|
||||
params: { version: version.name },
|
||||
props: { version },
|
||||
}));
|
||||
}
|
||||
|
||||
const { version } = Astro.props;
|
||||
---
|
||||
<DocsLayout title="Quickshell Module Listing" description="Quickshell Type Documentation">
|
||||
<div class="docs-content">
|
||||
|
@ -11,9 +18,9 @@ const modules = await getModulesData();
|
|||
<section>
|
||||
<span>All modules included with Quickshell</span>
|
||||
<div class="root-nav" data-pagefind-ignore>
|
||||
{modules.map(module => (
|
||||
{version.modules.map(module => (
|
||||
<div class="root-nav-entry">
|
||||
<a class="root-nav-link" href={`/docs/types/${module.name}`}>
|
||||
<a class="root-nav-link" href={`/docs/${version.name}/types/${module.name}`}>
|
||||
{module.name}
|
||||
</a>
|
||||
<span class="root-nav-desc">{module.description}</span>
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
import GuideLayout from "@layouts/GuideLayout.astro";
|
||||
|
||||
import { getCollection, render } from "astro:content";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const guidePages = await getCollection("guide");
|
||||
|
||||
return guidePages.map(page => ({
|
||||
params: { id: page.id == "index" ? "/" : page.id },
|
||||
props: { page },
|
||||
}));
|
||||
}
|
||||
|
||||
const { page } = Astro.props;
|
||||
const { Content, headings } = await render(page);
|
||||
---
|
||||
<GuideLayout title={page.data.title} description="" headings={headings}>
|
||||
<Content/>
|
||||
</GuideLayout>
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
import DocsLayout from "@layouts/DocsLayout.astro";
|
||||
---
|
||||
<DocsLayout title="Quickshell Docs" description="Quickshell Documentation">
|
||||
<h2>Docs</h2>
|
||||
<div class="root-nav">
|
||||
<h3><a href="/docs/guide">Usage Guide</a></h3>
|
||||
<h3><a href="/docs/types">Type Definitions</a></h3>
|
||||
</div>
|
||||
</DocsLayout>
|
|
@ -3,6 +3,8 @@ import Footer from "@src/components/Footer.astro";
|
|||
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||
import Marquee from "@components/marquee/Marquee.astro";
|
||||
import FeatureList from "@src/components/featurelist/FeatureList.astro";
|
||||
import { getVersionsData } from "@config/io/generateTypeData";
|
||||
const defaultVersion = (await getVersionsData()).default;
|
||||
|
||||
const title = "Quickshell";
|
||||
---
|
||||
|
@ -28,10 +30,10 @@ const title = "Quickshell";
|
|||
</p>
|
||||
</div>
|
||||
<div class="about-buttons">
|
||||
<a href="/docs/guide/install-setup" class="main-page_link-card">
|
||||
<a href={`/docs/${defaultVersion}/guide/install-setup`} class="main-page_link-card">
|
||||
<h3>Install</h3>
|
||||
</a>
|
||||
<a href="/docs/types" class="main-page_link-card main-page_bluecard">
|
||||
<a href={`/docs/${defaultVersion}/types`} class="main-page_link-card main-page_bluecard">
|
||||
<h3>Documentation</h3>
|
||||
</a>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue