Skip to content

Commit e7fe267

Browse files
delucisHiDeoo
andauthored
Support passing generateId to docsLoader() (#3272)
Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com>
1 parent 1161af0 commit e7fe267

4 files changed

Lines changed: 151 additions & 6 deletions

File tree

.changeset/metal-trees-deny.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@astrojs/starlight': minor
3+
---
4+
5+
Adds a new `generateId` option to Starlight’s `docsLoader()`
6+
7+
This enables overriding the default sluggifier used to convert content filenames to URLs.

docs/src/content/docs/manual-setup.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Find all available options in the [Starlight configuration reference](/reference
6464

6565
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.
6666

67-
Create or update the content config file, adding a `docs` collection that uses Starlight’s `docsLoader` and `docsSchema`:
67+
Create or update the content config file, adding a `docs` collection that uses Starlight’s [`docsLoader`](/reference/configuration/#docsloader) and [`docsSchema`](/reference/configuration/#docsschema):
6868

6969
```js ins={3-4,7}
7070
// src/content.config.ts

docs/src/content/docs/reference/configuration.mdx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,3 +677,118 @@ starlight({
677677
credits: true,
678678
});
679679
```
680+
681+
## Configure content collections
682+
683+
Starlight uses Astro [content collections](https://docs.astro.build/en/guides/content-collections/) to load your content.
684+
Starlight’s content loaders and schemas help configure collections as required.
685+
686+
```js
687+
// src/content.config.ts
688+
import { defineCollection } from 'astro:content';
689+
import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders';
690+
import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
691+
692+
export const collections = {
693+
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
694+
// Optional: the i18n collection is used to translate UI in multilingual sites
695+
i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }),
696+
};
697+
```
698+
699+
### Loaders
700+
701+
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.
702+
703+
#### `docsLoader()`
704+
705+
The `docsLoader()` loads local Markdown, MDX, and Markdoc files from the `src/content/docs/` directory.
706+
File names starting with an underscore (`_`) are ignored.
707+
708+
##### Import
709+
710+
```js
711+
import { docsLoader } from '@astrojs/starlight/loaders';
712+
```
713+
714+
##### Options
715+
716+
###### `generateId()`
717+
718+
**type:** `({ entry: string; base: URL; data: Record<string, unknown> }) => string`
719+
720+
By default, pages generated using `docsLoader()` process your file names using a sluggifier, which removes special characters and lowercases the file name.
721+
If you want to override this default, provide your own custom `generateId()` function.
722+
723+
For example, this can be useful to preserve special characters that would be removed.
724+
By default, `Example.File.md` would be served at `/examplefile`.
725+
If you wanted to serve it at `/Example.File`, you could do so by defining a custom `generateId()` function:
726+
727+
```js
728+
docsLoader({
729+
// Remove the `.md` or `.mdx` extension, but otherwise don’t process filenames.
730+
generateId: ({ entry }) => entry.split('.').slice(0, -1).join('.'),
731+
}),
732+
```
733+
734+
See [`generateId()` in the Astro docs](https://docs.astro.build/en/reference/content-loader-reference/#generateid) for more details.
735+
736+
#### `i18nLoader()`
737+
738+
The `i18nLoader()` loads local JSON and YAML files from the `src/content/i18n/` directory.
739+
File names starting with an underscore (`_`) are ignored.
740+
741+
##### Import
742+
743+
```js
744+
import { i18nLoader } from '@astrojs/starlight/loaders';
745+
```
746+
747+
##### Options
748+
749+
There are currently no options to configure `i18nLoader()`.
750+
751+
### Schemas
752+
753+
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.
754+
These schemas must be used for the `docs` and `i18n` collections Starlight depends on.
755+
756+
#### `docsSchema()`
757+
758+
The `docsSchema()` parses frontmatter for all your content in the `docs` collection.
759+
760+
##### Import
761+
762+
```js
763+
import { docsSchema } from '@astrojs/starlight/schema';
764+
```
765+
766+
##### Options
767+
768+
###### `extend`
769+
770+
**type:** Zod schema or function that returns a Zod schema
771+
**default:** `z.object({})`
772+
773+
Extend Starlight’s frontmatter schema with additional fields.
774+
See [“Customize frontmatter schema”](/reference/frontmatter/#customize-frontmatter-schema) for more details about using the `extend` option.
775+
776+
#### `i18nSchema()`
777+
778+
The `i18nSchema()` parses all data files in the `i18n` collection.
779+
780+
##### Import
781+
782+
```js
783+
import { i18nSchema } from '@astrojs/starlight/schema';
784+
```
785+
786+
##### Options
787+
788+
###### `extend`
789+
790+
**type:** Zod object
791+
**default:** `z.object({})`
792+
793+
Extend Starlight’s i18n schema with additional fields.
794+
See [“Extend translation schema”](/guides/i18n/#extend-translation-schema) for more details about using the `extend` option.

packages/starlight/loaders.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,41 @@ import { getCollectionPathFromRoot, type StarlightCollection } from './utils/col
66
const docsExtensions = ['markdown', 'mdown', 'mkdn', 'mkd', 'mdwn', 'md', 'mdx'];
77
const i18nExtensions = ['json', 'yml', 'yaml'];
88

9-
export function docsLoader(): Loader {
9+
type GlobOptions = Parameters<typeof glob>[0];
10+
type GenerateIdFunction = NonNullable<GlobOptions['generateId']>;
11+
12+
/**
13+
* Loads content files from the `src/content/docs/` directory, ignoring filenames starting with `_`.
14+
*/
15+
export function docsLoader({
16+
generateId,
17+
}: {
18+
/**
19+
* Function that generates an ID for an entry. Default implementation generates a slug from the entry path.
20+
* @returns The ID of the entry. Must be unique per collection.
21+
**/
22+
generateId?: GenerateIdFunction;
23+
} = {}): Loader {
1024
return {
1125
name: 'starlight-docs-loader',
12-
load: createGlobLoadFn('docs'),
26+
load: createGlobLoadFn('docs', generateId),
1327
};
1428
}
1529

30+
/**
31+
* Loads data files from the `src/content/i18n/` directory, ignoring filenames starting with `_`.
32+
*/
1633
export function i18nLoader(): Loader {
1734
return {
1835
name: 'starlight-i18n-loader',
1936
load: createGlobLoadFn('i18n'),
2037
};
2138
}
2239

23-
function createGlobLoadFn(collection: StarlightCollection): Loader['load'] {
40+
function createGlobLoadFn(
41+
collection: StarlightCollection,
42+
generateId?: GenerateIdFunction
43+
): Loader['load'] {
2444
return (context: LoaderContext) => {
2545
const extensions = collection === 'docs' ? docsExtensions : i18nExtensions;
2646

@@ -32,9 +52,12 @@ function createGlobLoadFn(collection: StarlightCollection): Loader['load'] {
3252
extensions.push('mdoc');
3353
}
3454

35-
return glob({
55+
const options: GlobOptions = {
3656
base: getCollectionPathFromRoot(collection, context.config),
3757
pattern: `**/[^_]*.{${extensions.join(',')}}`,
38-
}).load(context);
58+
};
59+
if (generateId) options.generateId = generateId;
60+
61+
return glob(options).load(context);
3962
};
4063
}

0 commit comments

Comments
 (0)