From 49fed51ced8291fb8e7610d075aece1f36042ec8 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 21 Jul 2025 17:15:39 -0700 Subject: [PATCH] the great typeinfo unfuckening --- src/components/Header.astro | 46 ++----- src/components/navigation/sidebars/TOC.astro | 12 +- .../navigation/sidebars/nav/RootNav.astro | 28 ++-- src/components/type/Properties.astro | 14 +- src/components/type/Signals.astro | 16 +-- src/components/type/Variants.astro | 13 +- src/config/io/generateTypeData.ts | 82 +++++------- src/config/io/helpers.ts | 20 +-- src/config/io/types.d.ts | 32 ++--- src/layouts/DocsLayout.astro | 6 +- src/pages/docs/types/[module]/[type].astro | 86 +++++++++++++ src/pages/docs/types/[module]/index.astro | 44 +++++++ src/pages/docs/types/[type]/[name].astro | 120 ------------------ src/pages/docs/types/[type]/index.astro | 59 --------- src/pages/docs/types/index.astro | 20 +-- 15 files changed, 233 insertions(+), 365 deletions(-) create mode 100644 src/pages/docs/types/[module]/[type].astro create mode 100644 src/pages/docs/types/[module]/index.astro delete mode 100644 src/pages/docs/types/[type]/[name].astro delete mode 100644 src/pages/docs/types/[type]/index.astro diff --git a/src/components/Header.astro b/src/components/Header.astro index f1a60a6..a7b9305 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -1,48 +1,18 @@ --- import { ThemeSelect } from "@components/hooks/ThemeSwitch"; -import { getTypeData } from "@config/io/generateTypeData"; +import type { TypeData } from "@config/io/types"; import Nav from "@components/navigation/sidebars/nav/index.astro"; import TOC from "@components/navigation/sidebars/TOC.astro"; -import type { TypeTOC } from "./navigation/sidebars/types"; +import type { ConfigHeading } from "@components/navigation/sidebars/types"; import Search from "./navigation/Search.astro"; -const routes = await getTypeData(); - -const url = Astro.url.pathname.split("/"); -const currentClass = url[4]; -const currentData = routes.find( - item => item.name === currentClass -); - -const data = currentData?.data; -const tocFunctions = - data?.functions?.map(item => item.name) || null; - -const propsKeys = data?.properties - ? Object.keys(data.properties) - : null; -const signalKeys = data?.signals - ? Object.keys(data.signals) - : null; -const variantKeys = data?.variants - ? Object.keys(data.variants) - : null; - -let sidebarData: TypeTOC | undefined = { - properties: propsKeys, - functions: tocFunctions, - signals: signalKeys, - variants: variantKeys, -}; - -if (!data) { - sidebarData = undefined; +interface Props { + title?: string; + headings?: ConfigHeading[]; + type?: TypeData; } -const { - title = null, - headings = [], -} = Astro.props; +const { title, headings, type } = Astro.props; ---
@@ -54,6 +24,6 @@ const {
- +
diff --git a/src/components/navigation/sidebars/TOC.astro b/src/components/navigation/sidebars/TOC.astro index 7933715..1effd82 100644 --- a/src/components/navigation/sidebars/TOC.astro +++ b/src/components/navigation/sidebars/TOC.astro @@ -1,15 +1,23 @@ --- import TableOfContents from "./toc"; import type { ConfigHeading, TypeTOC } from "./types.d.ts"; +import type { TypeData } from "@config/io/types"; export interface Props { title?: string; headings?: ConfigHeading[]; - types?: TypeTOC; + type?: TypeData; mobile: boolean; } -const { title, headings, types, mobile } = Astro.props; +const { title, headings, type, mobile } = Astro.props; + +const types: TypeTOC | null = type ? { + properties: Object.keys(type.properties ?? {}), + functions: (type.functions ?? []).map(f => f.name), + signals: Object.keys(type.signals ?? {}), + variants: Object.keys(type.variants ?? {}), +} : null; --- {((headings?.length ?? 0) != 0 || types) &&
diff --git a/src/components/navigation/sidebars/nav/RootNav.astro b/src/components/navigation/sidebars/nav/RootNav.astro index 7a4792d..0b83c24 100644 --- a/src/components/navigation/sidebars/nav/RootNav.astro +++ b/src/components/navigation/sidebars/nav/RootNav.astro @@ -7,15 +7,13 @@ export interface Props { const { currentRoute, currentModule, currentClass } = Astro.props; -import { getTypeData } from "@config/io/generateTypeData"; -import { groupRoutes } from "@config/io/helpers"; +import { getModulesData } 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 routes = await getTypeData(); -const groupedRoutes = groupRoutes(routes); +const modules = await getModulesData(); import { getCollection } from "astro:content"; const guidePages = await getCollection("guide"); @@ -45,18 +43,16 @@ const types = { title: "Quickshell Types", link: "/docs/types", current: currentRoute?.startsWith("types") ?? false, - entries: Object.entries(groupedRoutes.types).map( - ([module, items]) => ({ - title: module, - link: `/docs/types/${module}`, - current: currentModule === module, - entries: items.map(type => ({ - title: type.name, - link: `/docs/types/${module}/${type.name}`, - current: currentClass === type.name, - })), - }) - ), + entries: modules.map(module => ({ + title: module.name, + link: `/docs/types/${module.name}`, + current: currentModule === module.name, + entries: module.types.map(type => ({ + title: type.name, + link: `/docs/types/${module.name}/${type.name}`, + current: currentClass === type.name, + })) + })) }; --- diff --git a/src/components/type/Properties.astro b/src/components/type/Properties.astro index 4e50a2f..41e19ca 100644 --- a/src/components/type/Properties.astro +++ b/src/components/type/Properties.astro @@ -4,22 +4,20 @@ import type { QMLTypeLinkObject, QuickshellProps, } from "@config/io/types"; -import { Tag, Flag } from "@icons"; +import { Tag } from "@icons"; import TypeTitle from "./TypeTitle.astro"; import TypeDetails from "./TypeDetails.astro"; export interface Props { - propsKeys: string[]; - propsData: QuickshellProps; + props: QuickshellProps; } -const { propsKeys, propsData } = Astro.props; +const { props } = Astro.props; ---
    { - propsKeys.map(item => { - const propData = propsData[item] + Object.entries(props).map(([name, propData]) => { let typeLink:string; let linkText:string; let genericType:string|undefined; @@ -37,10 +35,10 @@ const { propsKeys, propsData } = Astro.props; genericTypeLink = getQMLTypeLink(propData.type.of) } return ( -
  • +
  • { - signalKeys.map(item => { - const signalData = signalsData[item]; + Object.entries(signals).map(([name, signalData]) => { const paramKeys = signalData.params.length > 0 ? signalData.params.map((param,index) => `${param.name}${index !== signalData.params.length -1 ? ", ":""}`) : [] let genericType:string|undefined; let genericTypeLink:string|undefined; return ( -
  • +
  • { - variantKeys.map(item => { - const variantData = variantsData[item]; + Object.entries(variants).map(([name, variantData]) => { const paramKeys = variantData.params && variantData.params.length > 0 ? variantData.params.map(param => param.name) : []; return ( -
  • +
  • diff --git a/src/config/io/generateTypeData.ts b/src/config/io/generateTypeData.ts index 7efa80d..948008d 100644 --- a/src/config/io/generateTypeData.ts +++ b/src/config/io/generateTypeData.ts @@ -1,57 +1,41 @@ import { promises as fs } from "node:fs"; import path from "node:path"; -import type { RouteData, dirData } from "./types"; +import type { VersionsData, ModuleData } from "./types"; -async function readSubdir(basePath: string, subdir: string): Promise { - const fullpath = path.join(basePath, subdir); - const filenames = await fs.readdir(fullpath); +async function readModulesData(basePath: string): Promise { + const moduleDirs = await fs.readdir(basePath); - const data = await Promise.all( - filenames.map(async filename => { - const filepath = path.join(fullpath, filename); - const content = await fs.readFile(filepath, "utf8"); - const data = JSON.parse(content); - if (typeof data.module === "undefined") { - data.module = "index"; - data.contains = filenames - .filter(filename => filename !== "index.json") - .map(filename => filename.replace(".json", "")); - } - const returnValue = { - fullpath: path.join(fullpath, filename), - filename: filename.replace(".json", ""), - category: subdir, - data: data, - }; - return returnValue; - }) - ); - return data; -} + const modules = await Promise.all(moduleDirs.map(async moduleDir => { + const modulePath = path.join(basePath, moduleDir); -async function generateTypeData(basePath: string): Promise { - const subdirs = await fs.readdir(basePath, { - withFileTypes: true, - }); - const routes: RouteData[] = []; + const indexPromise = async () => { + const indexPath = path.join(modulePath, "index.json"); + const indexContent = await fs.readFile(indexPath, "utf8"); + return JSON.parse(indexContent); + }; - for (const subdir of subdirs) { - const data = await readSubdir(basePath, subdir.name); - const returnValue = data.map(entry => { - return { - type: entry.category, - name: entry.filename, - path: entry.fullpath, - data: entry.data, - }; + const typeNames = (await fs.readdir(modulePath)).filter(name => name !== "index.json"); + const typePromises = typeNames.map(async fileName => { + const typePath = path.join(modulePath, fileName); + const fileContent = await fs.readFile(typePath, "utf8"); + return JSON.parse(fileContent); }); - routes.push(...returnValue); - } - return routes; + + const [index, ...types] = await Promise.all([indexPromise(), ...typePromises]); + + return { + name: index.name, + description: index.description, + details: index.details, + types, + } + })); + + return modules; } -async function generateVersionsData(): Promise { +async function readVersionsData(): Promise { const versionsPath = import.meta.env.VERSION_FILE_PATH; if (!versionsPath || versionsPath === "") { @@ -63,9 +47,9 @@ async function generateVersionsData(): Promise { const content = await fs.readFile(versionsPath, "utf8"); const data = JSON.parse(content); - const versions = await Promise.all(data.versions.map(async d => ({ + const versions = await Promise.all(data.versions.map(async (d: { name: string, types: any }) => ({ name: d.name, - modules: await generateTypeData(d.types), + modules: await readModulesData(d.types), }))) return { @@ -78,13 +62,13 @@ let globalVersionsData: Promise; export function getVersionsData(): Promise { if (!globalVersionsData) { - globalVersionsData = generateVersionsData(); + globalVersionsData = readVersionsData(); } return globalVersionsData; } -export async function getTypeData(): RouteData[] { +export async function getModulesData(): Promise { const versions = await getVersionsData(); - return versions.versions.find(v => v.name == versions.default).modules; + return versions.versions.find(v => v.name == versions.default)!.modules; } diff --git a/src/config/io/helpers.ts b/src/config/io/helpers.ts index be075c3..12615c7 100644 --- a/src/config/io/helpers.ts +++ b/src/config/io/helpers.ts @@ -9,9 +9,8 @@ import { import type { ConfigHeading, ConfigTOC, - GroupedRoutes, } from "@components/navigation/sidebars/types"; -import type { QMLTypeLinkObject, RouteData } from "./types"; +import type { QMLTypeLinkObject } from "./types"; export function buildHierarchy(headings: ConfigHeading[]) { const toc: ConfigTOC[] = []; @@ -43,23 +42,6 @@ export function buildHierarchy(headings: ConfigHeading[]) { return toc; } -export function groupRoutes(routes: RouteData[]): GroupedRoutes { - const froutes = routes.filter(route => route.name !== "index"); - return froutes.reduce((acc, route) => { - if (!acc.types) acc.types = {}; - - if (!acc.types[route.type]) { - acc.types[route.type] = []; - } - - acc.types[route.type].push({ - name: route.name, - type: route.type, - }); - return acc; - }, { types: {} }); -} - export function getQMLTypeLinkObject(unparsed: string) { const isLocal = unparsed.startsWith("MQS_") ? "local" : false; const isQT = unparsed.startsWith("MQT_") ? "qt" : false; diff --git a/src/config/io/types.d.ts b/src/config/io/types.d.ts index 19138bf..155b716 100644 --- a/src/config/io/types.d.ts +++ b/src/config/io/types.d.ts @@ -61,9 +61,7 @@ export interface QuickshellVariant { }; } -export interface QuickshellData { - type: string; - module: string; +export interface TypeData { name: string; description: string; details: string; @@ -77,33 +75,22 @@ export interface QuickshellData { subtypes?: QuickshellData[]; } -export interface RouteData { - // priority 1: Quickshell, Quickshell.Io, etc. - type: string; - // priority 1.1: entry name (e.g. DataStreamParser) +export interface ModuleData { name: string; - // path to json - path: string; - // data content of the route - data: QuickshellData; + description: string; + details: string; + types: TypeData[]; } export interface VersionData { name: string; - modules: RouteData[]; + modules: ModuleData[]; } export interface VersionsData { default: string; versions: VersionData[]; } - -export interface dirData { - fullpath: string; - filename: string; - category: string; - data: QuickshellData; -} // -- // helpers.ts @@ -124,8 +111,9 @@ export type { QuickshellFunction, QuickshellSignal, QuickshellVariant, - QuickshellData, - RouteData, - dirData, + TypeData, + ModuleData, + VersionData, + VersionsData, QMLTypeLinkObject, }; diff --git a/src/layouts/DocsLayout.astro b/src/layouts/DocsLayout.astro index ebce18d..782fafe 100644 --- a/src/layouts/DocsLayout.astro +++ b/src/layouts/DocsLayout.astro @@ -9,14 +9,16 @@ import Head from "@config/Head.astro"; import Nav from "@components/navigation/sidebars/nav/index.astro"; import type { ConfigHeading } from "@src/components/navigation/sidebars/types"; import Footer from "@src/components/Footer.astro"; +import type { TypeData } from "@config/io/types"; interface Props { title: string; description: string; headings?: ConfigHeading[]; + type?: TypeData } -const { title, description, headings } = Astro.props; +const { title, description, headings, type } = Astro.props; const url = Astro.url.pathname.split("/"); const customBreadcrumbs = [ @@ -59,7 +61,7 @@ if (url[2]) { -
    +