diff options
author | Chris Swithinbank | 2025-07-16 15:58:04 +0200 |
---|---|---|
committer | GitHub | 2025-07-16 15:58:04 +0200 |
commit | e7fe26720b7527c39e3aab42ea9fd0468f92167c (patch) | |
tree | 97d9f10826f04998fa6f3083885a3363160ac9fb | |
parent | 1161af0c2fe26485da6123f8fd7205c53b0e45e5 (diff) | |
download | IT.starlight-e7fe26720b7527c39e3aab42ea9fd0468f92167c.tar.gz IT.starlight-e7fe26720b7527c39e3aab42ea9fd0468f92167c.tar.bz2 IT.starlight-e7fe26720b7527c39e3aab42ea9fd0468f92167c.zip |
Support passing `generateId` to `docsLoader()` (#3272)
Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com>
-rw-r--r-- | .changeset/metal-trees-deny.md | 7 | ||||
-rw-r--r-- | docs/src/content/docs/manual-setup.mdx | 2 | ||||
-rw-r--r-- | docs/src/content/docs/reference/configuration.mdx | 115 | ||||
-rw-r--r-- | packages/starlight/loaders.ts | 33 |
4 files changed, 151 insertions, 6 deletions
diff --git a/.changeset/metal-trees-deny.md b/.changeset/metal-trees-deny.md new file mode 100644 index 00000000..86b2ab20 --- /dev/null +++ b/.changeset/metal-trees-deny.md @@ -0,0 +1,7 @@ +--- +'@astrojs/starlight': minor +--- + +Adds a new `generateId` option to Starlight’s `docsLoader()` + +This enables overriding the default sluggifier used to convert content filenames to URLs. diff --git a/docs/src/content/docs/manual-setup.mdx b/docs/src/content/docs/manual-setup.mdx index 7848438a..7b8fbe5d 100644 --- a/docs/src/content/docs/manual-setup.mdx +++ b/docs/src/content/docs/manual-setup.mdx @@ -64,7 +64,7 @@ Find all available options in the [Starlight configuration reference](/reference Starlight is built on top of Astro’s [content collections](https://docs.astro.build/en/guides/content-collections/), which are configured in the `src/content.config.ts` file. -Create or update the content config file, adding a `docs` collection that uses Starlight’s `docsLoader` and `docsSchema`: +Create or update the content config file, adding a `docs` collection that uses Starlight’s [`docsLoader`](/reference/configuration/#docsloader) and [`docsSchema`](/reference/configuration/#docsschema): ```js ins={3-4,7} // src/content.config.ts diff --git a/docs/src/content/docs/reference/configuration.mdx b/docs/src/content/docs/reference/configuration.mdx index 9d245531..e7e21955 100644 --- a/docs/src/content/docs/reference/configuration.mdx +++ b/docs/src/content/docs/reference/configuration.mdx @@ -677,3 +677,118 @@ starlight({ credits: true, }); ``` + +## Configure content collections + +Starlight uses Astro [content collections](https://docs.astro.build/en/guides/content-collections/) to load your content. +Starlight’s content loaders and schemas help configure collections as required. + +```js +// src/content.config.ts +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + // Optional: the i18n collection is used to translate UI in multilingual sites + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; +``` + +### Loaders + +Starlight exports the following [Astro loaders](https://docs.astro.build/en/reference/content-loader-reference/) from the `@astrojs/starlight/loaders` module to simplify configuring content collections. + +#### `docsLoader()` + +The `docsLoader()` loads local Markdown, MDX, and Markdoc files from the `src/content/docs/` directory. +File names starting with an underscore (`_`) are ignored. + +##### Import + +```js +import { docsLoader } from '@astrojs/starlight/loaders'; +``` + +##### Options + +###### `generateId()` + +**type:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string` + +By default, pages generated using `docsLoader()` process your file names using a sluggifier, which removes special characters and lowercases the file name. +If you want to override this default, provide your own custom `generateId()` function. + +For example, this can be useful to preserve special characters that would be removed. +By default, `Example.File.md` would be served at `/examplefile`. +If you wanted to serve it at `/Example.File`, you could do so by defining a custom `generateId()` function: + +```js +docsLoader({ + // Remove the `.md` or `.mdx` extension, but otherwise don’t process filenames. + generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'), +}), +``` + +See [`generateId()` in the Astro docs](https://docs.astro.build/en/reference/content-loader-reference/#generateid) for more details. + +#### `i18nLoader()` + +The `i18nLoader()` loads local JSON and YAML files from the `src/content/i18n/` directory. +File names starting with an underscore (`_`) are ignored. + +##### Import + +```js +import { i18nLoader } from '@astrojs/starlight/loaders'; +``` + +##### Options + +There are currently no options to configure `i18nLoader()`. + +### Schemas + +Starlight provides the following [content collection schemas](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema) from the `@astrojs/starlight/schema` module. +These schemas must be used for the `docs` and `i18n` collections Starlight depends on. + +#### `docsSchema()` + +The `docsSchema()` parses frontmatter for all your content in the `docs` collection. + +##### Import + +```js +import { docsSchema } from '@astrojs/starlight/schema'; +``` + +##### Options + +###### `extend` + +**type:** Zod schema or function that returns a Zod schema +**default:** `z.object({})` + +Extend Starlight’s frontmatter schema with additional fields. +See [“Customize frontmatter schema”](/reference/frontmatter/#customize-frontmatter-schema) for more details about using the `extend` option. + +#### `i18nSchema()` + +The `i18nSchema()` parses all data files in the `i18n` collection. + +##### Import + +```js +import { i18nSchema } from '@astrojs/starlight/schema'; +``` + +##### Options + +###### `extend` + +**type:** Zod object +**default:** `z.object({})` + +Extend Starlight’s i18n schema with additional fields. +See [“Extend translation schema”](/guides/i18n/#extend-translation-schema) for more details about using the `extend` option. diff --git a/packages/starlight/loaders.ts b/packages/starlight/loaders.ts index bb424d0e..ef2d6766 100644 --- a/packages/starlight/loaders.ts +++ b/packages/starlight/loaders.ts @@ -6,13 +6,30 @@ import { getCollectionPathFromRoot, type StarlightCollection } from './utils/col const docsExtensions = ['markdown', 'mdown', 'mkdn', 'mkd', 'mdwn', 'md', 'mdx']; const i18nExtensions = ['json', 'yml', 'yaml']; -export function docsLoader(): Loader { +type GlobOptions = Parameters<typeof glob>[0]; +type GenerateIdFunction = NonNullable<GlobOptions['generateId']>; + +/** + * Loads content files from the `src/content/docs/` directory, ignoring filenames starting with `_`. + */ +export function docsLoader({ + generateId, +}: { + /** + * Function that generates an ID for an entry. Default implementation generates a slug from the entry path. + * @returns The ID of the entry. Must be unique per collection. + **/ + generateId?: GenerateIdFunction; +} = {}): Loader { return { name: 'starlight-docs-loader', - load: createGlobLoadFn('docs'), + load: createGlobLoadFn('docs', generateId), }; } +/** + * Loads data files from the `src/content/i18n/` directory, ignoring filenames starting with `_`. + */ export function i18nLoader(): Loader { return { name: 'starlight-i18n-loader', @@ -20,7 +37,10 @@ export function i18nLoader(): Loader { }; } -function createGlobLoadFn(collection: StarlightCollection): Loader['load'] { +function createGlobLoadFn( + collection: StarlightCollection, + generateId?: GenerateIdFunction +): Loader['load'] { return (context: LoaderContext) => { const extensions = collection === 'docs' ? docsExtensions : i18nExtensions; @@ -32,9 +52,12 @@ function createGlobLoadFn(collection: StarlightCollection): Loader['load'] { extensions.push('mdoc'); } - return glob({ + const options: GlobOptions = { base: getCollectionPathFromRoot(collection, context.config), pattern: `**/[^_]*.{${extensions.join(',')}}`, - }).load(context); + }; + if (generateId) options.generateId = generateId; + + return glob(options).load(context); }; } |