Mirror of
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #14 from trueberryless-org/ci-format

[ci] format

authored by

trueberryless and committed by
GitHub
4f3f0ef4 fc8c8a6b

+521 -465
+95 -91
docs/astro.config.ts
··· 5 5 import starlightPluginsDocsComponents from "@trueberryless-org/starlight-plugins-docs-components"; 6 6 7 7 export default defineConfig({ 8 - integrations: [ 9 - starlight({ 10 - title: "Starlight Sidebar Topics Dropdown", 11 - logo: { 12 - light: "./src/assets/logo-white.png", 13 - dark: "./src/assets/logo-dark.png", 14 - replacesTitle: true, 8 + integrations: [ 9 + starlight({ 10 + title: "Starlight Sidebar Topics Dropdown", 11 + logo: { 12 + light: "./src/assets/logo-white.png", 13 + dark: "./src/assets/logo-dark.png", 14 + replacesTitle: true, 15 + }, 16 + customCss: ["./src/styles/custom.css"], 17 + editLink: { 18 + baseUrl: 19 + "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown/edit/main/docs/", 20 + }, 21 + plugins: [ 22 + starlightSidebarTopicsDropdown([ 23 + { 24 + label: "Documentation", 25 + link: "/docs/getting-started/", 26 + icon: "open-book", 27 + items: [ 28 + { 29 + label: "Start Here", 30 + items: ["docs/getting-started", "docs/configuration"], 31 + }, 32 + { label: "Guides", autogenerate: { directory: "docs/guides" } }, 33 + { 34 + label: "Resources", 35 + items: [ 36 + { 37 + label: "Showcase", 38 + link: "/resources/sites/", 39 + }, 40 + { 41 + label: "Plugins", 42 + link: "/resources/plugins/", 43 + }, 44 + { 45 + label: "Content from HiDeoo", 46 + link: "/resources/hideoo/", 47 + }, 48 + ], 49 + }, 50 + ], 51 + }, 52 + { 53 + id: "demo", 54 + label: { 55 + en: "Demo", 56 + fr: "Démo", 15 57 }, 16 - customCss: ["./src/styles/custom.css"], 17 - editLink: { 18 - baseUrl: 19 - "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown/edit/main/docs/", 20 - }, 21 - plugins: [ 22 - starlightSidebarTopicsDropdown([ 23 - { 24 - label: "Documentation", 25 - link: "/docs/getting-started/", 26 - icon: "open-book", 27 - items: [ 28 - { 29 - label: "Start Here", 30 - items: ["docs/getting-started", "docs/configuration"], 31 - }, 32 - { label: "Guides", autogenerate: { directory: "docs/guides" } }, 33 - { 34 - label: "Resources", 35 - items: [ 36 - { 37 - label: "Showcase", 38 - link: "/resources/sites/", 39 - }, 40 - { 41 - label: "Plugins", 42 - link: "/resources/plugins/", 43 - }, 44 - { 45 - label: "Content from HiDeoo", 46 - link: "/resources/hideoo/", 47 - }, 48 - ], 49 - }, 50 - ], 51 - }, 52 - { 53 - id: "demo", 54 - label: { 55 - en: "Demo", 56 - fr: "Démo", 57 - }, 58 - link: "/demo/", 59 - icon: "puzzle", 60 - items: [ 61 - { label: "API", autogenerate: { directory: "demo/api" } }, 62 - { label: "Components", autogenerate: { directory: "demo/components" } }, 63 - { 64 - label: "Commands", 65 - autogenerate: { directory: "demo/commands" }, 66 - collapsed: true, 67 - }, 68 - ], 69 - badge: { 70 - text: { 71 - en: "Stub", 72 - fr: "Ébauche", 73 - }, 74 - variant: "caution", 75 - }, 76 - }, 77 - { 78 - label: "Starlight Docs", 79 - link: "https://starlight.astro.build/", 80 - icon: "starlight", 81 - }, 82 - ]), 83 - starlightLinksValidator(), 84 - starlightPluginsDocsComponents({ 85 - pluginName: "starlight-sidebar-topics-dropdown", 86 - showcaseProps: { 87 - entries: [ 88 - { 89 - title: "TanaFlows Documentation", 90 - thumbnail: "./src/assets/tanaflows-docs.png", 91 - href: "https://docs.ghostfam.com/", 92 - description: "Professional multilingual theme for ghost CMS", 93 - }, 94 - ], 95 - }, 96 - }), 58 + link: "/demo/", 59 + icon: "puzzle", 60 + items: [ 61 + { label: "API", autogenerate: { directory: "demo/api" } }, 62 + { 63 + label: "Components", 64 + autogenerate: { directory: "demo/components" }, 65 + }, 66 + { 67 + label: "Commands", 68 + autogenerate: { directory: "demo/commands" }, 69 + collapsed: true, 70 + }, 97 71 ], 98 - social: { 99 - github: "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown", 72 + badge: { 73 + text: { 74 + en: "Stub", 75 + fr: "Ébauche", 76 + }, 77 + variant: "caution", 100 78 }, 79 + }, 80 + { 81 + label: "Starlight Docs", 82 + link: "https://starlight.astro.build/", 83 + icon: "starlight", 84 + }, 85 + ]), 86 + starlightLinksValidator(), 87 + starlightPluginsDocsComponents({ 88 + pluginName: "starlight-sidebar-topics-dropdown", 89 + showcaseProps: { 90 + entries: [ 91 + { 92 + title: "TanaFlows Documentation", 93 + thumbnail: "./src/assets/tanaflows-docs.png", 94 + href: "https://docs.ghostfam.com/", 95 + description: "Professional multilingual theme for ghost CMS", 96 + }, 97 + ], 98 + }, 101 99 }), 102 - ], 100 + ], 101 + social: { 102 + github: 103 + "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown", 104 + }, 105 + }), 106 + ], 103 107 });
+34 -34
docs/package.json
··· 1 1 { 2 - "name": "starlight-sidebar-topics-dropdown-docs", 3 - "version": "0.2.2", 4 - "license": "MIT", 5 - "description": "Starlight plugin to split your docs page into multiple subpages and switch between them with a dropdown menu in the sidebar.", 6 - "author": "trueberryless-org", 7 - "type": "module", 8 - "scripts": { 9 - "dev": "astro dev", 10 - "start": "astro dev", 11 - "build": "astro build", 12 - "preview": "astro preview", 13 - "astro": "astro" 14 - }, 15 - "dependencies": { 16 - "@astrojs/starlight": "^0.28.3", 17 - "@hideoo/starlight-plugins-docs-components": "^0.2.2", 18 - "@trueberryless-org/starlight-plugins-docs-components": "^0.2.1", 19 - "astro": "^4.16.6", 20 - "sharp": "^0.33.5", 21 - "starlight-links-validator": "^0.12.4", 22 - "starlight-sidebar-topics-dropdown": "workspace:*" 23 - }, 24 - "engines": { 25 - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" 26 - }, 27 - "packageManager": "pnpm@9.3.0", 28 - "private": true, 29 - "homepage": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown", 30 - "repository": { 31 - "type": "git", 32 - "url": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown.git", 33 - "directory": "docs" 34 - }, 35 - "bugs": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown/issues" 2 + "name": "starlight-sidebar-topics-dropdown-docs", 3 + "version": "0.2.2", 4 + "private": true, 5 + "description": "Starlight plugin to split your docs page into multiple subpages and switch between them with a dropdown menu in the sidebar.", 6 + "homepage": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown", 7 + "bugs": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown/issues", 8 + "repository": { 9 + "type": "git", 10 + "url": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown.git", 11 + "directory": "docs" 12 + }, 13 + "license": "MIT", 14 + "author": "trueberryless-org", 15 + "type": "module", 16 + "scripts": { 17 + "astro": "astro", 18 + "build": "astro build", 19 + "dev": "astro dev", 20 + "preview": "astro preview", 21 + "start": "astro dev" 22 + }, 23 + "dependencies": { 24 + "@astrojs/starlight": "^0.28.3", 25 + "@hideoo/starlight-plugins-docs-components": "^0.2.2", 26 + "@trueberryless-org/starlight-plugins-docs-components": "^0.2.1", 27 + "astro": "^4.16.6", 28 + "sharp": "^0.33.5", 29 + "starlight-links-validator": "^0.12.4", 30 + "starlight-sidebar-topics-dropdown": "workspace:*" 31 + }, 32 + "packageManager": "pnpm@9.3.0", 33 + "engines": { 34 + "node": "^18.17.1 || ^20.3.0 || >=21.0.0" 35 + } 36 36 }
+1 -1
docs/src/content/config.ts
··· 3 3 import { topicSchema } from "starlight-sidebar-topics-dropdown/schema"; 4 4 5 5 export const collections = { 6 - docs: defineCollection({ schema: docsSchema({ extend: topicSchema }) }), 6 + docs: defineCollection({ schema: docsSchema({ extend: topicSchema }) }), 7 7 };
+1 -1
docs/src/env.d.ts
··· 1 - /// <reference path="../.astro/types.d.ts" /> 1 + /// <reference path="../.astro/types.d.ts" />
+4 -4
docs/src/styles/custom.css
··· 1 1 .hero-html { 2 - --size: 12rem; 2 + --size: 12rem; 3 3 4 - font-size: var(--size); 5 - justify-content: center; 6 - line-height: var(--size); 4 + font-size: var(--size); 5 + justify-content: center; 6 + line-height: var(--size); 7 7 }
+72 -62
packages/starlight-sidebar-topics-dropdown/index.ts
··· 1 - import type { StarlightPlugin, StarlightUserConfig } from "@astrojs/starlight/types"; 1 + import type { 2 + StarlightPlugin, 3 + StarlightUserConfig, 4 + } from "@astrojs/starlight/types"; 2 5 3 6 import { 4 - StarlightSidebarTopicsDropdownConfigSchema, 5 - type StarlightSidebarTopicsDropdownUserConfig, 7 + StarlightSidebarTopicsDropdownConfigSchema, 8 + type StarlightSidebarTopicsDropdownUserConfig, 6 9 } from "./lib/config"; 7 10 import { overrideStarlightComponent, throwPluginError } from "./lib/plugin"; 8 11 import { vitePluginStarlightSidebarTopicsDropdown } from "./lib/vite"; 9 12 10 13 export type { 11 - StarlightSidebarTopicsDropdownConfig, 12 - StarlightSidebarTopicsDropdownUserConfig, 14 + StarlightSidebarTopicsDropdownConfig, 15 + StarlightSidebarTopicsDropdownUserConfig, 13 16 } from "./lib/config"; 14 17 15 18 export default function starlightSidebarTopicsDropdownPlugin( 16 - userConfig: StarlightSidebarTopicsDropdownUserConfig 19 + userConfig: StarlightSidebarTopicsDropdownUserConfig 17 20 ): StarlightPlugin { 18 - const parsedConfig = StarlightSidebarTopicsDropdownConfigSchema.safeParse(userConfig); 21 + const parsedConfig = 22 + StarlightSidebarTopicsDropdownConfigSchema.safeParse(userConfig); 19 23 20 - if (!parsedConfig.success) { 21 - throwPluginError( 22 - `The provided plugin configuration is invalid.\n${parsedConfig.error.issues 23 - .map((issue) => issue.message) 24 - .join("\n")}` 25 - ); 26 - } 24 + if (!parsedConfig.success) { 25 + throwPluginError( 26 + `The provided plugin configuration is invalid.\n${parsedConfig.error.issues 27 + .map((issue) => issue.message) 28 + .join("\n")}` 29 + ); 30 + } 27 31 28 - const config = parsedConfig.data; 32 + const config = parsedConfig.data; 29 33 30 - return { 31 - name: "starlight-sidebar-topics-dropdown-plugin", 32 - hooks: { 33 - setup({ addIntegration, command, config: starlightConfig, logger, updateConfig }) { 34 - if (command !== "dev" && command !== "build") return; 34 + return { 35 + name: "starlight-sidebar-topics-dropdown-plugin", 36 + hooks: { 37 + setup({ 38 + addIntegration, 39 + command, 40 + config: starlightConfig, 41 + logger, 42 + updateConfig, 43 + }) { 44 + if (command !== "dev" && command !== "build") return; 35 45 36 - if (starlightConfig.sidebar) { 37 - throwPluginError( 38 - "It looks like you have a `sidebar` configured in your Starlight configuration. To use `starlight-sidebar-topics-dropdown`, create a new topic with your sidebar items.", 39 - "Learn more about topic configuration at https://starlight-sidebar-topics-dropdown.netlify.app/docs/configuration/" 40 - ); 41 - } 46 + if (starlightConfig.sidebar) { 47 + throwPluginError( 48 + "It looks like you have a `sidebar` configured in your Starlight configuration. To use `starlight-sidebar-topics-dropdown`, create a new topic with your sidebar items.", 49 + "Learn more about topic configuration at https://starlight-sidebar-topics-dropdown.netlify.app/docs/configuration/" 50 + ); 51 + } 42 52 43 - const sidebar: StarlightUserConfig["sidebar"] = []; 53 + const sidebar: StarlightUserConfig["sidebar"] = []; 44 54 45 - for (const [index, topic] of config.entries()) { 46 - if ("items" in topic) { 47 - sidebar.push({ label: String(index), items: topic.items }); 48 - } 49 - } 50 - updateConfig({ 51 - components: { 52 - ...starlightConfig.components, 53 - ...overrideStarlightComponent( 54 - starlightConfig.components, 55 - logger, 56 - "Sidebar" 57 - ), 58 - ...overrideStarlightComponent( 59 - starlightConfig.components, 60 - logger, 61 - "Pagination" 62 - ), 63 - }, 64 - sidebar, 65 - }); 55 + for (const [index, topic] of config.entries()) { 56 + if ("items" in topic) { 57 + sidebar.push({ label: String(index), items: topic.items }); 58 + } 59 + } 60 + updateConfig({ 61 + components: { 62 + ...starlightConfig.components, 63 + ...overrideStarlightComponent( 64 + starlightConfig.components, 65 + logger, 66 + "Sidebar" 67 + ), 68 + ...overrideStarlightComponent( 69 + starlightConfig.components, 70 + logger, 71 + "Pagination" 72 + ), 73 + }, 74 + sidebar, 75 + }); 66 76 67 - addIntegration({ 68 - name: "starlight-sidebar-topics-dropdown-integration", 69 - hooks: { 70 - "astro:config:setup": ({ updateConfig }) => { 71 - updateConfig({ 72 - vite: { 73 - plugins: [vitePluginStarlightSidebarTopicsDropdown(config)], 74 - }, 75 - }); 76 - }, 77 - }, 78 - }); 77 + addIntegration({ 78 + name: "starlight-sidebar-topics-dropdown-integration", 79 + hooks: { 80 + "astro:config:setup": ({ updateConfig }) => { 81 + updateConfig({ 82 + vite: { 83 + plugins: [vitePluginStarlightSidebarTopicsDropdown(config)], 84 + }, 85 + }); 79 86 }, 80 - }, 81 - }; 87 + }, 88 + }); 89 + }, 90 + }, 91 + }; 82 92 }
+59 -51
packages/starlight-sidebar-topics-dropdown/lib/config.ts
··· 2 2 import { z } from "astro/zod"; 3 3 4 4 const sidebarTopicBadgeSchema = z.object({ 5 - text: z.union([z.string(), z.record(z.string())]), 6 - variant: z.enum(["note", "danger", "success", "caution", "tip", "default"]).default("default"), 5 + text: z.union([z.string(), z.record(z.string())]), 6 + variant: z 7 + .enum(["note", "danger", "success", "caution", "tip", "default"]) 8 + .default("default"), 7 9 }); 8 10 9 11 const sidebarTopicBaseSchema = z.object({ 10 - /** 11 - * An optional badge to display next to the topic label. 12 - * 13 - * This option accepts the same configuration as the Starlight badge sidebar item configuration. 14 - * @see https://starlight.astro.build/guides/sidebar/#badges 15 - */ 16 - badge: z 17 - .union([z.string(), sidebarTopicBadgeSchema]) 18 - .transform((badge) => 19 - typeof badge === "string" ? { variant: "default" as const, text: badge } : badge 20 - ) 21 - .optional(), 22 - /** 23 - * The name of an optional icon to display before the topic label set to one of Starlight’s built-in icons. 24 - * @see https://starlight.astro.build/reference/icons/#all-icons 25 - */ 26 - icon: z.string().optional(), 27 - /** 28 - * The topic label visible at the top of the sidebar. 29 - * 30 - * The value can be a string, or for multilingual sites, an object with values for each different locale. When using 31 - * the object form, the keys must be BCP-47 tags (e.g. en, fr, or zh-CN). 32 - */ 33 - label: z.union([z.string(), z.record(z.string())]), 34 - /** 35 - * The link to the topic’s content which an be a relative link to local files or the full URL of an external page. 36 - * 37 - * For internal links, the link can either be a page included in the items array or a different page acting as the 38 - * topic’s landing page. 39 - */ 40 - link: z.string(), 12 + /** 13 + * An optional badge to display next to the topic label. 14 + * 15 + * This option accepts the same configuration as the Starlight badge sidebar item configuration. 16 + * @see https://starlight.astro.build/guides/sidebar/#badges 17 + */ 18 + badge: z 19 + .union([z.string(), sidebarTopicBadgeSchema]) 20 + .transform((badge) => 21 + typeof badge === "string" 22 + ? { variant: "default" as const, text: badge } 23 + : badge 24 + ) 25 + .optional(), 26 + /** 27 + * The name of an optional icon to display before the topic label set to one of Starlight’s built-in icons. 28 + * @see https://starlight.astro.build/reference/icons/#all-icons 29 + */ 30 + icon: z.string().optional(), 31 + /** 32 + * The topic label visible at the top of the sidebar. 33 + * 34 + * The value can be a string, or for multilingual sites, an object with values for each different locale. When using 35 + * the object form, the keys must be BCP-47 tags (e.g. en, fr, or zh-CN). 36 + */ 37 + label: z.union([z.string(), z.record(z.string())]), 38 + /** 39 + * The link to the topic’s content which an be a relative link to local files or the full URL of an external page. 40 + * 41 + * For internal links, the link can either be a page included in the items array or a different page acting as the 42 + * topic’s landing page. 43 + */ 44 + link: z.string(), 41 45 }); 42 46 43 47 const sidebarTopicLinkSchema = sidebarTopicBaseSchema; 44 48 45 49 const sidebarTopicGroupSchema = sidebarTopicBaseSchema.extend({ 46 - /** 47 - * An optional unique identifier for the topic that can be used to associate content pages that are not listed in any 48 - * topic sidebar configuration with this topic. 49 - */ 50 - id: z.string().optional(), 51 - /** 52 - * The sidebar items (links and subcategories) to display for this topic. 53 - * 54 - * The topic’s sidebar navigation items. This represents the sidebar displayed when the topic `link` page or any of 55 - * the pages configured in the `items` array is the current page. 56 - */ 57 - items: z.any().array() as z.Schema<NonNullable<StarlightUserConfig["sidebar"]>>, 50 + /** 51 + * An optional unique identifier for the topic that can be used to associate content pages that are not listed in any 52 + * topic sidebar configuration with this topic. 53 + */ 54 + id: z.string().optional(), 55 + /** 56 + * The sidebar items (links and subcategories) to display for this topic. 57 + * 58 + * The topic’s sidebar navigation items. This represents the sidebar displayed when the topic `link` page or any of 59 + * the pages configured in the `items` array is the current page. 60 + */ 61 + items: z.any().array() as z.Schema< 62 + NonNullable<StarlightUserConfig["sidebar"]> 63 + >, 58 64 }); 59 65 60 66 export const StarlightSidebarTopicsDropdownConfigSchema = z 61 - .union([sidebarTopicGroupSchema, sidebarTopicLinkSchema]) 62 - .array(); 67 + .union([sidebarTopicGroupSchema, sidebarTopicLinkSchema]) 68 + .array(); 63 69 64 70 export type StarlightSidebarTopicsDropdownUserConfig = z.input< 65 - typeof StarlightSidebarTopicsDropdownConfigSchema 71 + typeof StarlightSidebarTopicsDropdownConfigSchema 66 72 >; 67 73 export type StarlightSidebarTopicsDropdownConfig = z.output< 68 - typeof StarlightSidebarTopicsDropdownConfigSchema 74 + typeof StarlightSidebarTopicsDropdownConfigSchema 69 75 >; 70 76 71 77 export type StarlightSidebarTopicsDropdownSharedConfig = ( 72 - | (z.output<typeof sidebarTopicLinkSchema> & { type: "link" }) 73 - | (Omit<z.output<typeof sidebarTopicGroupSchema>, "items"> & { type: "group" }) 78 + | (z.output<typeof sidebarTopicLinkSchema> & { type: "link" }) 79 + | (Omit<z.output<typeof sidebarTopicGroupSchema>, "items"> & { 80 + type: "group"; 81 + }) 74 82 )[];
+11 -7
packages/starlight-sidebar-topics-dropdown/lib/content.ts
··· 1 1 import type { Props } from "@astrojs/starlight/props"; 2 2 import type { TopicFrontmatterSchema } from "../schema"; 3 - export function isStarlightEntryWithTopic(entry: StarlightEntry): entry is StarlightEntryWithTopic { 4 - return ( 5 - "data" in entry && 6 - "topic" in (entry as StarlightEntryWithTopic).data && 7 - typeof (entry as StarlightEntryWithTopic).data.topic === "string" 8 - ); 3 + export function isStarlightEntryWithTopic( 4 + entry: StarlightEntry 5 + ): entry is StarlightEntryWithTopic { 6 + return ( 7 + "data" in entry && 8 + "topic" in (entry as StarlightEntryWithTopic).data && 9 + typeof (entry as StarlightEntryWithTopic).data.topic === "string" 10 + ); 9 11 } 10 12 export type StarlightEntry = Props["entry"]; 11 - export type StarlightEntryWithTopic = StarlightEntry & { data: TopicFrontmatterSchema }; 13 + export type StarlightEntryWithTopic = StarlightEntry & { 14 + data: TopicFrontmatterSchema; 15 + };
+17 -12
packages/starlight-sidebar-topics-dropdown/lib/i18n.ts
··· 2 2 3 3 import { stripTrailingSlash } from "./pathname"; 4 4 5 - export function getLocalizedSlug(slug: string, locale: string | undefined): string { 6 - const slugLocale = getLocaleFromSlug(slug); 7 - if (slugLocale === locale) return slug; 8 - locale ??= ""; 9 - if (slugLocale === slug) return locale; 5 + export function getLocalizedSlug( 6 + slug: string, 7 + locale: string | undefined 8 + ): string { 9 + const slugLocale = getLocaleFromSlug(slug); 10 + if (slugLocale === locale) return slug; 11 + locale ??= ""; 12 + if (slugLocale === slug) return locale; 10 13 11 - if (slugLocale) { 12 - return stripTrailingSlash(slug.replace(`${slugLocale}/`, locale ? `${locale}/` : "")); 13 - } 14 + if (slugLocale) { 15 + return stripTrailingSlash( 16 + slug.replace(`${slugLocale}/`, locale ? `${locale}/` : "") 17 + ); 18 + } 14 19 15 - return slug ? `${locale}/${slug}` : locale; 20 + return slug ? `${locale}/${slug}` : locale; 16 21 } 17 22 18 23 export function getLocaleFromSlug(slug: string): string | undefined { 19 - const locales = Object.keys(starlightConfig.locales ?? {}); 20 - const baseSegment = slug.split("/")[0]; 21 - return baseSegment && locales.includes(baseSegment) ? baseSegment : undefined; 24 + const locales = Object.keys(starlightConfig.locales ?? {}); 25 + const baseSegment = slug.split("/")[0]; 26 + return baseSegment && locales.includes(baseSegment) ? baseSegment : undefined; 22 27 }
+9 -6
packages/starlight-sidebar-topics-dropdown/lib/pathname.ts
··· 1 1 export function arePathnamesEqual(pathnameA: string, pathnameB: string) { 2 - return stripLeadingAndTrailingSlashes(pathnameA) === stripLeadingAndTrailingSlashes(pathnameB); 2 + return ( 3 + stripLeadingAndTrailingSlashes(pathnameA) === 4 + stripLeadingAndTrailingSlashes(pathnameB) 5 + ); 3 6 } 4 7 5 8 export function stripLeadingAndTrailingSlashes(pathname: string): string { 6 - return stripLeadingSlash(stripTrailingSlash(pathname)); 9 + return stripLeadingSlash(stripTrailingSlash(pathname)); 7 10 } 8 11 9 12 export function stripLeadingSlash(pathname: string) { 10 - if (pathname.startsWith("/")) pathname = pathname.slice(1); 11 - return pathname; 13 + if (pathname.startsWith("/")) pathname = pathname.slice(1); 14 + return pathname; 12 15 } 13 16 14 17 export function stripTrailingSlash(pathname: string) { 15 - if (pathname.endsWith("/")) pathname = pathname.slice(0, -1); 16 - return pathname; 18 + if (pathname.endsWith("/")) pathname = pathname.slice(0, -1); 19 + return pathname; 17 20 }
+20 -20
packages/starlight-sidebar-topics-dropdown/lib/plugin.ts
··· 3 3 import { AstroError } from "astro/errors"; 4 4 5 5 export function throwPluginError(message: string, hint?: string): never { 6 - throw new AstroError( 7 - message, 8 - hint ?? 9 - `See the error report above for more informations.\n\nIf you believe this is a bug, please file an issue at https://github.com/HiDeoo/starlight-sidebar-topics-dropdown/issues/new/choose` 10 - ); 6 + throw new AstroError( 7 + message, 8 + hint ?? 9 + `See the error report above for more informations.\n\nIf you believe this is a bug, please file an issue at https://github.com/HiDeoo/starlight-sidebar-topics-dropdown/issues/new/choose` 10 + ); 11 11 } 12 12 13 13 export function overrideStarlightComponent( 14 - components: StarlightUserConfig["components"], 15 - logger: AstroIntegrationLogger, 16 - component: keyof NonNullable<StarlightUserConfig["components"]> 14 + components: StarlightUserConfig["components"], 15 + logger: AstroIntegrationLogger, 16 + component: keyof NonNullable<StarlightUserConfig["components"]> 17 17 ) { 18 - if (components?.[component]) { 19 - logger.warn( 20 - `It looks like you already have a \`${component}\` component override in your Starlight configuration.` 21 - ); 22 - logger.warn( 23 - `To use \`starlight-sidebar-topics-dropdown\`, either remove your override or update it to render the content from \`starlight-sidebar-topics-dropdown/overrides/${component}.astro\`.` 24 - ); 18 + if (components?.[component]) { 19 + logger.warn( 20 + `It looks like you already have a \`${component}\` component override in your Starlight configuration.` 21 + ); 22 + logger.warn( 23 + `To use \`starlight-sidebar-topics-dropdown\`, either remove your override or update it to render the content from \`starlight-sidebar-topics-dropdown/overrides/${component}.astro\`.` 24 + ); 25 25 26 - return {}; 27 - } 26 + return {}; 27 + } 28 28 29 - return { 30 - [component]: `starlight-sidebar-topics-dropdown/overrides/${component}.astro`, 31 - }; 29 + return { 30 + [component]: `starlight-sidebar-topics-dropdown/overrides/${component}.astro`, 31 + }; 32 32 }
+123 -103
packages/starlight-sidebar-topics-dropdown/lib/sidebar.ts
··· 8 8 const absoluteLinkRegex = /^https?:\/\//; 9 9 10 10 export function getCurrentTopic( 11 - config: StarlightSidebarTopicsDropdownSharedConfig, 12 - sidebar: SidebarEntry[], 13 - currentSlug: string, 14 - entry: StarlightEntry 11 + config: StarlightSidebarTopicsDropdownSharedConfig, 12 + sidebar: SidebarEntry[], 13 + currentSlug: string, 14 + entry: StarlightEntry 15 15 ): Topic | undefined { 16 - // If the current page has a topic ID, use it to find the topic. 17 - const topicId = getTopicIdFromEntry(entry); 18 - if (topicId) return getTopicById(config, sidebar, topicId); 16 + // If the current page has a topic ID, use it to find the topic. 17 + const topicId = getTopicIdFromEntry(entry); 18 + if (topicId) return getTopicById(config, sidebar, topicId); 19 19 20 - // Start by checking if the current page is a topic root. 21 - const topicFromSlug = getTopicFromSlug(config, sidebar, currentSlug); 22 - if (topicFromSlug) return topicFromSlug; 20 + // Start by checking if the current page is a topic root. 21 + const topicFromSlug = getTopicFromSlug(config, sidebar, currentSlug); 22 + if (topicFromSlug) return topicFromSlug; 23 23 24 - // Otherwise, find the current topic by looking for the current page in the sidebar. 25 - const currentSidebarTopic = getCurrentSidebarTopic(sidebar); 26 - if (!currentSidebarTopic) return; 24 + // Otherwise, find the current topic by looking for the current page in the sidebar. 25 + const currentSidebarTopic = getCurrentSidebarTopic(sidebar); 26 + if (!currentSidebarTopic) return; 27 27 28 - const currentTopicConfig = config[Number.parseInt(currentSidebarTopic.label, 10)]; 29 - if (!currentTopicConfig) return; 28 + const currentTopicConfig = 29 + config[Number.parseInt(currentSidebarTopic.label, 10)]; 30 + if (!currentTopicConfig) return; 30 31 31 - return { config: currentTopicConfig, sidebar: currentSidebarTopic.entries }; 32 + return { config: currentTopicConfig, sidebar: currentSidebarTopic.entries }; 32 33 } 33 34 34 - export function isTopicFirstPage(sidebar: SidebarEntry[], currentSlug: string): boolean { 35 - const currentSidebarTopic = getCurrentSidebarTopic(sidebar); 36 - if (!currentSidebarTopic) return false; 35 + export function isTopicFirstPage( 36 + sidebar: SidebarEntry[], 37 + currentSlug: string 38 + ): boolean { 39 + const currentSidebarTopic = getCurrentSidebarTopic(sidebar); 40 + if (!currentSidebarTopic) return false; 37 41 38 - const firstPage = getSidebarFirstPage(currentSidebarTopic.entries); 39 - if (!firstPage) return false; 42 + const firstPage = getSidebarFirstPage(currentSidebarTopic.entries); 43 + if (!firstPage) return false; 40 44 41 - return arePathnamesEqual(stripLeadingAndTrailingSlashes(firstPage.href), currentSlug); 45 + return arePathnamesEqual( 46 + stripLeadingAndTrailingSlashes(firstPage.href), 47 + currentSlug 48 + ); 42 49 } 43 50 44 - export function isTopicLastPage(sidebar: SidebarEntry[], currentSlug: string): boolean { 45 - const currentSidebarTopic = getCurrentSidebarTopic(sidebar); 46 - if (!currentSidebarTopic) return false; 51 + export function isTopicLastPage( 52 + sidebar: SidebarEntry[], 53 + currentSlug: string 54 + ): boolean { 55 + const currentSidebarTopic = getCurrentSidebarTopic(sidebar); 56 + if (!currentSidebarTopic) return false; 47 57 48 - const lastPage = getSidebarLastPage(currentSidebarTopic.entries); 49 - if (!lastPage) return false; 58 + const lastPage = getSidebarLastPage(currentSidebarTopic.entries); 59 + if (!lastPage) return false; 50 60 51 - return arePathnamesEqual(stripLeadingAndTrailingSlashes(lastPage.href), currentSlug); 61 + return arePathnamesEqual( 62 + stripLeadingAndTrailingSlashes(lastPage.href), 63 + currentSlug 64 + ); 52 65 } 53 66 54 67 function getSidebarFirstPage(sidebar: SidebarEntry[]) { 55 - const entry = sidebar[0]; 56 - if (!entry) return; 57 - if (entry.type === "link") return entry; 68 + const entry = sidebar[0]; 69 + if (!entry) return; 70 + if (entry.type === "link") return entry; 58 71 59 - return getSidebarFirstPage(entry.entries); 72 + return getSidebarFirstPage(entry.entries); 60 73 } 61 74 62 75 function getSidebarLastPage(sidebar: SidebarEntry[]) { 63 - const entry = sidebar.at(-1); 64 - if (!entry) return; 65 - if (entry.type === "link") return entry; 76 + const entry = sidebar.at(-1); 77 + if (!entry) return; 78 + if (entry.type === "link") return entry; 66 79 67 - return getSidebarLastPage(entry.entries); 80 + return getSidebarLastPage(entry.entries); 68 81 } 69 82 70 83 function getTopicFromSlug( 71 - config: StarlightSidebarTopicsDropdownSharedConfig, 72 - sidebar: SidebarEntry[], 73 - slug: string 84 + config: StarlightSidebarTopicsDropdownSharedConfig, 85 + sidebar: SidebarEntry[], 86 + slug: string 74 87 ): Topic | undefined { 75 - let topicConfig: Topic["config"] | undefined; 76 - let topicSidebar: Topic["sidebar"] | undefined; 88 + let topicConfig: Topic["config"] | undefined; 89 + let topicSidebar: Topic["sidebar"] | undefined; 77 90 78 - // Start by checking if the current page is a topic homepage. 79 - let groupTopicIndex = -1; 80 - const slugLocale = getLocaleFromSlug(slug); 91 + // Start by checking if the current page is a topic homepage. 92 + let groupTopicIndex = -1; 93 + const slugLocale = getLocaleFromSlug(slug); 81 94 82 - for (const topic of config) { 83 - if (topic.type === "group") groupTopicIndex++; 95 + for (const topic of config) { 96 + if (topic.type === "group") groupTopicIndex++; 84 97 85 - if ( 86 - !absoluteLinkRegex.test(topic.link) && 87 - arePathnamesEqual( 88 - getLocalizedSlug(stripLeadingAndTrailingSlashes(topic.link), slugLocale), 89 - slug 90 - ) && 91 - groupTopicIndex !== -1 92 - ) { 93 - const sidebarTopic = sidebar[groupTopicIndex]; 98 + if ( 99 + !absoluteLinkRegex.test(topic.link) && 100 + arePathnamesEqual( 101 + getLocalizedSlug( 102 + stripLeadingAndTrailingSlashes(topic.link), 103 + slugLocale 104 + ), 105 + slug 106 + ) && 107 + groupTopicIndex !== -1 108 + ) { 109 + const sidebarTopic = sidebar[groupTopicIndex]; 94 110 95 - if (sidebarTopic?.type === "group") { 96 - topicConfig = topic; 97 - topicSidebar = sidebarTopic.entries; 98 - } 111 + if (sidebarTopic?.type === "group") { 112 + topicConfig = topic; 113 + topicSidebar = sidebarTopic.entries; 114 + } 99 115 100 - break; 101 - } 116 + break; 102 117 } 118 + } 103 119 104 - if (!topicConfig || !topicSidebar) return; 120 + if (!topicConfig || !topicSidebar) return; 105 121 106 - return { config: topicConfig, sidebar: topicSidebar }; 122 + return { config: topicConfig, sidebar: topicSidebar }; 107 123 } 108 124 109 125 function getTopicById( 110 - config: StarlightSidebarTopicsDropdownSharedConfig, 111 - sidebar: SidebarEntry[], 112 - id: string 126 + config: StarlightSidebarTopicsDropdownSharedConfig, 127 + sidebar: SidebarEntry[], 128 + id: string 113 129 ): Topic | undefined { 114 - let topicConfig: Topic["config"] | undefined; 115 - let topicSidebar: Topic["sidebar"] | undefined; 116 - let groupTopicIndex = -1; 117 - for (const topic of config) { 118 - if (topic.type === "group") groupTopicIndex++; 119 - if (topic.type === "group" && topic.id === id) { 120 - const sidebarTopic = sidebar[groupTopicIndex]; 121 - if (sidebarTopic?.type === "group") { 122 - topicConfig = topic; 123 - topicSidebar = sidebarTopic.entries; 124 - } 125 - break; 126 - } 130 + let topicConfig: Topic["config"] | undefined; 131 + let topicSidebar: Topic["sidebar"] | undefined; 132 + let groupTopicIndex = -1; 133 + for (const topic of config) { 134 + if (topic.type === "group") groupTopicIndex++; 135 + if (topic.type === "group" && topic.id === id) { 136 + const sidebarTopic = sidebar[groupTopicIndex]; 137 + if (sidebarTopic?.type === "group") { 138 + topicConfig = topic; 139 + topicSidebar = sidebarTopic.entries; 140 + } 141 + break; 127 142 } 128 - if (!topicConfig || !topicSidebar) return; 129 - return { config: topicConfig, sidebar: topicSidebar }; 143 + } 144 + if (!topicConfig || !topicSidebar) return; 145 + return { config: topicConfig, sidebar: topicSidebar }; 130 146 } 131 147 132 - function getCurrentSidebarTopic(sidebar: SidebarEntry[]): SidebarTopic | undefined { 133 - let currentSidebarTopic: SidebarTopic | undefined; 148 + function getCurrentSidebarTopic( 149 + sidebar: SidebarEntry[] 150 + ): SidebarTopic | undefined { 151 + let currentSidebarTopic: SidebarTopic | undefined; 134 152 135 - for (const topic of sidebar) { 136 - if (topic.type === "link") continue; 153 + for (const topic of sidebar) { 154 + if (topic.type === "link") continue; 137 155 138 - const currentSidebarEntry = getCurrentSidebarEntry(topic.entries); 156 + const currentSidebarEntry = getCurrentSidebarEntry(topic.entries); 139 157 140 - if (currentSidebarEntry) { 141 - currentSidebarTopic = topic; 142 - break; 143 - } 158 + if (currentSidebarEntry) { 159 + currentSidebarTopic = topic; 160 + break; 144 161 } 162 + } 145 163 146 - return currentSidebarTopic; 164 + return currentSidebarTopic; 147 165 } 148 166 149 - function getCurrentSidebarEntry(sidebar: SidebarEntry[]): SidebarEntry | undefined { 150 - return sidebar.find((entry) => { 151 - if (entry.type === "link") { 152 - return entry.isCurrent; 153 - } 167 + function getCurrentSidebarEntry( 168 + sidebar: SidebarEntry[] 169 + ): SidebarEntry | undefined { 170 + return sidebar.find((entry) => { 171 + if (entry.type === "link") { 172 + return entry.isCurrent; 173 + } 154 174 155 - return getCurrentSidebarEntry(entry.entries); 156 - }); 175 + return getCurrentSidebarEntry(entry.entries); 176 + }); 157 177 } 158 178 159 179 function getTopicIdFromEntry(entry: StarlightEntry): string | undefined { 160 - return isStarlightEntryWithTopic(entry) ? entry.data.topic : undefined; 180 + return isStarlightEntryWithTopic(entry) ? entry.data.topic : undefined; 161 181 } 162 182 163 183 type SidebarEntry = Props["sidebar"][number]; 164 184 165 185 interface SidebarTopic { 166 - label: string; 167 - entries: SidebarEntry[]; 186 + label: string; 187 + entries: SidebarEntry[]; 168 188 } 169 189 170 190 export interface Topic { 171 - config: StarlightSidebarTopicsDropdownSharedConfig[number]; 172 - sidebar: SidebarEntry[]; 191 + config: StarlightSidebarTopicsDropdownSharedConfig[number]; 192 + sidebar: SidebarEntry[]; 173 193 }
+21 -19
packages/starlight-sidebar-topics-dropdown/lib/vite.ts
··· 1 1 import type { ViteUserConfig } from "astro"; 2 2 3 3 import type { 4 - StarlightSidebarTopicsDropdownConfig, 5 - StarlightSidebarTopicsDropdownSharedConfig, 4 + StarlightSidebarTopicsDropdownConfig, 5 + StarlightSidebarTopicsDropdownSharedConfig, 6 6 } from "./config"; 7 7 8 8 const moduleId = "virtual:starlight-sidebar-topics-dropdown/config"; 9 9 10 10 export function vitePluginStarlightSidebarTopicsDropdown( 11 - config: StarlightSidebarTopicsDropdownConfig 11 + config: StarlightSidebarTopicsDropdownConfig 12 12 ): VitePlugin { 13 - const resolvedModuleId = `\0${moduleId}`; 13 + const resolvedModuleId = `\0${moduleId}`; 14 14 15 - const sharedConfig: StarlightSidebarTopicsDropdownSharedConfig = config.map((topic) => { 16 - if (!("items" in topic)) return { ...topic, type: "link" }; 17 - const { items, ...topicWithoutItems } = topic; 18 - return { ...topicWithoutItems, type: "group" }; 19 - }); 15 + const sharedConfig: StarlightSidebarTopicsDropdownSharedConfig = config.map( 16 + (topic) => { 17 + if (!("items" in topic)) return { ...topic, type: "link" }; 18 + const { items, ...topicWithoutItems } = topic; 19 + return { ...topicWithoutItems, type: "group" }; 20 + } 21 + ); 20 22 21 - const moduleContent = `export default ${JSON.stringify(sharedConfig)}`; 23 + const moduleContent = `export default ${JSON.stringify(sharedConfig)}`; 22 24 23 - return { 24 - name: "vite-plugin-starlight-sidebar-topics-dropdown", 25 - load(id) { 26 - return id === resolvedModuleId ? moduleContent : undefined; 27 - }, 28 - resolveId(id) { 29 - return id === moduleId ? resolvedModuleId : undefined; 30 - }, 31 - }; 25 + return { 26 + name: "vite-plugin-starlight-sidebar-topics-dropdown", 27 + load(id) { 28 + return id === resolvedModuleId ? moduleContent : undefined; 29 + }, 30 + resolveId(id) { 31 + return id === moduleId ? resolvedModuleId : undefined; 32 + }, 33 + }; 32 34 } 33 35 34 36 type VitePlugin = NonNullable<ViteUserConfig["plugins"]>[number];
+44 -44
packages/starlight-sidebar-topics-dropdown/package.json
··· 1 1 { 2 - "name": "starlight-sidebar-topics-dropdown", 3 - "version": "0.2.2", 4 - "license": "MIT", 5 - "description": "Starlight plugin to split your docs page into multiple subpages and switch between them with a dropdown menu in the sidebar.", 6 - "author": "trueberryless (https://trueberryless.org)", 7 - "type": "module", 8 - "exports": { 9 - ".": "./index.ts", 10 - "./overrides/Pagination.astro": "./overrides/Pagination.astro", 11 - "./overrides/Sidebar.astro": "./overrides/Sidebar.astro", 12 - "./schema": "./schema.ts", 13 - "./package.json": "./package.json" 14 - }, 15 - "devDependencies": { 16 - "@astrojs/starlight": "^0.28.3", 17 - "astro": "^4.16.6" 18 - }, 19 - "peerDependencies": { 20 - "@astrojs/starlight": ">=0.28" 21 - }, 22 - "engines": { 23 - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" 24 - }, 25 - "packageManager": "pnpm@9.3.0", 26 - "publishConfig": { 27 - "access": "public" 28 - }, 29 - "keywords": [ 30 - "starlight", 31 - "plugin", 32 - "sidebar", 33 - "subpages", 34 - "sections", 35 - "dropdown", 36 - "documentation", 37 - "astro" 38 - ], 39 - "homepage": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown", 40 - "repository": { 41 - "type": "git", 42 - "url": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown.git", 43 - "directory": "packages/starlight-sidebar-topics-dropdown" 44 - }, 45 - "bugs": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown/issues" 2 + "name": "starlight-sidebar-topics-dropdown", 3 + "version": "0.2.2", 4 + "description": "Starlight plugin to split your docs page into multiple subpages and switch between them with a dropdown menu in the sidebar.", 5 + "keywords": [ 6 + "starlight", 7 + "plugin", 8 + "sidebar", 9 + "subpages", 10 + "sections", 11 + "dropdown", 12 + "documentation", 13 + "astro" 14 + ], 15 + "homepage": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown", 16 + "bugs": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown/issues", 17 + "repository": { 18 + "type": "git", 19 + "url": "https://github.com/trueberryless-org/starlight-sidebar-topics-dropdown.git", 20 + "directory": "packages/starlight-sidebar-topics-dropdown" 21 + }, 22 + "license": "MIT", 23 + "author": "trueberryless (https://trueberryless.org)", 24 + "type": "module", 25 + "exports": { 26 + ".": "./index.ts", 27 + "./overrides/Pagination.astro": "./overrides/Pagination.astro", 28 + "./overrides/Sidebar.astro": "./overrides/Sidebar.astro", 29 + "./schema": "./schema.ts", 30 + "./package.json": "./package.json" 31 + }, 32 + "devDependencies": { 33 + "@astrojs/starlight": "^0.28.3", 34 + "astro": "^4.16.6" 35 + }, 36 + "peerDependencies": { 37 + "@astrojs/starlight": ">=0.28" 38 + }, 39 + "packageManager": "pnpm@9.3.0", 40 + "engines": { 41 + "node": "^18.17.1 || ^20.3.0 || >=21.0.0" 42 + }, 43 + "publishConfig": { 44 + "access": "public" 45 + } 46 46 }
+6 -6
packages/starlight-sidebar-topics-dropdown/schema.ts
··· 1 1 import { z } from "astro/zod"; 2 2 export const topicSchema = z.object({ 3 - /** 4 - * ID of the topic to associate with the current page if the page is not listed in any topic sidebar configuration. 5 - * 6 - * @see https://starlight-sidebar-topics.netlify.app/docs/guides/unlisted-pages/ 7 - */ 8 - topic: z.string().optional(), 3 + /** 4 + * ID of the topic to associate with the current page if the page is not listed in any topic sidebar configuration. 5 + * 6 + * @see https://starlight-sidebar-topics.netlify.app/docs/guides/unlisted-pages/ 7 + */ 8 + topic: z.string().optional(), 9 9 }); 10 10 export type TopicFrontmatterSchema = z.input<typeof topicSchema>;
+2 -2
packages/starlight-sidebar-topics-dropdown/starlight.d.ts
··· 1 1 declare module "virtual:starlight/user-config" { 2 - const Config: import("@astrojs/starlight/types").StarlightConfig; 2 + const Config: import("@astrojs/starlight/types").StarlightConfig; 3 3 4 - export default Config; 4 + export default Config; 5 5 }
+2 -2
packages/starlight-sidebar-topics-dropdown/virtual.d.ts
··· 1 1 declare module "virtual:starlight-sidebar-topics-dropdown/config" { 2 - const StarlightSidebarTopicsDropdownConfig: import("./libs/config").StarlightSidebarTopicsDropdownSharedConfig; 2 + const StarlightSidebarTopicsDropdownConfig: import("./libs/config").StarlightSidebarTopicsDropdownSharedConfig; 3 3 4 - export default StarlightSidebarTopicsDropdownConfig; 4 + export default StarlightSidebarTopicsDropdownConfig; 5 5 }