version docs pages

This commit is contained in:
outfoxxed 2025-07-22 01:08:30 -07:00
parent 5865251560
commit 21e175d3a6
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
31 changed files with 329 additions and 388 deletions

View file

@ -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 {

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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/>

View file

@ -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>
)
})

View file

@ -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">:&nbsp;<a
href=""
target="_blank"
href={getQMLTypeLink(version!, param.type)}
>{param.type.name}</a></span>
</span>
)

View file

@ -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>}

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;
}

View file

@ -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 };

View file

@ -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.

View file

@ -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

View file

@ -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"

View 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>

View 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>

View file

@ -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!}
/>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>