Skip to content

Commit f493361

Browse files
delucisHiDeootrueberryless
authored
Move route data to Astro.locals (#2390)
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com> Co-authored-by: trueberryless <99918022+trueberryless@users.noreply.github.com>
1 parent f895f75 commit f493361

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1087
-540
lines changed

.changeset/chilled-bees-pump.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
'@astrojs/starlight': minor
3+
---
4+
5+
Moves route data to `Astro.locals` instead of passing it down via component props
6+
7+
⚠️ **Breaking change:**
8+
Previously, all of Starlight’s templating components, including user or plugin overrides, had access to a data object for the current route via `Astro.props`.
9+
This data is now available as `Astro.locals.starlightRoute` instead.
10+
11+
To update, refactor any component overrides you have:
12+
13+
- Remove imports of `@astrojs/starlight/props`, which is now deprecated.
14+
- Update code that accesses `Astro.props` to use `Astro.locals.starlightRoute` instead.
15+
- Remove any spreading of `{...Astro.props}` into child components, which is no longer required.
16+
17+
In the following example, a custom override for Starlight’s `LastUpdated` component is updated for the new style:
18+
19+
```diff
20+
---
21+
import Default from '@astrojs/starlight/components/LastUpdated.astro';
22+
- import type { Props } from '@astrojs/starlight/props';
23+
24+
- const { lastUpdated } = Astro.props;
25+
+ const { lastUpdated } = Astro.locals.starlightRoute;
26+
27+
const updatedThisYear = lastUpdated?.getFullYear() === new Date().getFullYear();
28+
---
29+
30+
{updatedThisYear && (
31+
- <Default {...Astro.props}><slot /></Default>
32+
+ <Default><slot /></Default>
33+
)}
34+
```
35+
36+
_Community Starlight plugins may also need to be manually updated to work with Starlight 0.32. If you encounter any issues, please reach out to the plugin author to see if it is a known issue or if an updated version is being worked on._

docs/src/components/sidebar-preview.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
} from '../../../packages/starlight/schemas/sidebar';
77
import SidebarSublist from '../../../packages/starlight/components/SidebarSublist.astro';
88
import type { Badge } from '../../../packages/starlight/schemas/badge';
9-
import type { SidebarEntry } from '../../../packages/starlight/utils/navigation';
9+
import type { SidebarEntry } from '../../../packages/starlight/utils/routing/types';
1010
1111
interface Props {
1212
config: SidebarConfig;

docs/src/content/docs/guides/overriding-components.mdx

+16-22
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ Overriding Starlight’s default components can be useful when:
3636
```astro
3737
---
3838
// src/components/EmailLink.astro
39-
import type { Props } from '@astrojs/starlight/props';
39+
40+
const email = 'houston@example.com';
4041
---
4142
42-
<a href="mailto:houston@example.com">E-mail Me</a>
43+
<a href=`mailto:${email}`>E-mail Me</a>
4344
```
4445

4546
3. Tell Starlight to use your custom component in the [`components`](/reference/configuration/#components) configuration option in `astro.config.mjs`:
@@ -70,52 +71,46 @@ You can build with Starlight’s default UI components just as you would with yo
7071

7172
The example below shows a custom component that renders an e-mail link along with the default `SocialIcons` component:
7273

73-
```astro {4,8}
74+
```astro {3,7}
7475
---
7576
// src/components/EmailLink.astro
76-
import type { Props } from '@astrojs/starlight/props';
7777
import Default from '@astrojs/starlight/components/SocialIcons.astro';
7878
---
7979
8080
<a href="mailto:houston@example.com">E-mail Me</a>
81-
<Default {...Astro.props}><slot /></Default>
81+
<Default><slot /></Default>
8282
```
8383

84-
When rendering a built-in component inside a custom component:
85-
86-
- Spread `Astro.props` into it. This makes sure that it receives all the data it needs to render.
87-
- Add a [`<slot />`](https://docs.astro.build/en/basics/astro-components/#slots) inside the default component. This makes sure that if the component is passed any child elements, Astro knows where to render them.
84+
When rendering a built-in component inside a custom component add a [`<slot />`](https://docs.astro.build/en/basics/astro-components/#slots) inside the default component. This makes sure that if the component is passed any child elements, Astro knows where to render them.
8885

8986
If you are reusing the [`PageFrame`](/reference/overrides/#pageframe) or [`TwoColumnContent`](/reference/overrides/#twocolumncontent) components which contain [named slots](https://docs.astro.build/en/basics/astro-components/#named-slots), you also need to [transfer](https://docs.astro.build/en/basics/astro-components/#transferring-slots) these slots as well.
9087

9188
The example below shows a custom component that reuses the `TwoColumnContent` component which contains an additional `right-sidebar` named slot that needs to be transferred:
9289

93-
```astro {9}
90+
```astro {8}
9491
---
9592
// src/components/CustomContent.astro
96-
import type { Props } from '@astrojs/starlight/props';
9793
import Default from '@astrojs/starlight/components/TwoColumnContent.astro';
9894
---
9995
100-
<Default {...Astro.props}>
96+
<Default>
10197
<slot />
10298
<slot name="right-sidebar" slot="right-sidebar" />
10399
</Default>
104100
```
105101

106102
## Use page data
107103

108-
When overriding a Starlight component, your custom implementation receives a standard `Astro.props` object containing all the data for the current page.
104+
When overriding a Starlight component, you can access the global [`starlightRoute` object](/guides/route-data/) containing all the data for the current page.
109105
This allows you to use these values to control how your component template renders.
110106

111-
For example, you can read the page’s frontmatter values as `Astro.props.entry.data`. In the following example, a replacement [`PageTitle`](/reference/overrides/#pagetitle) component uses this to display the current page’s title:
107+
In the following example, a replacement [`PageTitle`](/reference/overrides/#pagetitle) component displays the current page’s title as set in the content’s frontmatter:
112108

113-
```astro {5} "{title}"
109+
```astro {4} "{title}"
114110
---
115111
// src/components/Title.astro
116-
import type { Props } from '@astrojs/starlight/props';
117112
118-
const { title } = Astro.props.entry.data;
113+
const { title } = Astro.locals.starlightRoute.entry.data;
119114
---
120115
121116
<h1 id="_top">{title}</h1>
@@ -127,28 +122,27 @@ const { title } = Astro.props.entry.data;
127122
</style>
128123
```
129124

130-
Learn more about all the available props in the [Overrides Reference](/reference/overrides/#component-props).
125+
Learn more about all the available properties in the [Route Data Reference](/reference/route-data/).
131126

132127
### Only override on specific pages
133128

134-
Component overrides apply to all pages. However, you can conditionally render using values from `Astro.props` to determine when to show your custom UI, when to show Starlight’s default UI, or even when to show something entirely different.
129+
Component overrides apply to all pages. However, you can conditionally render using values from `starlightRoute` to determine when to show your custom UI, when to show Starlight’s default UI, or even when to show something entirely different.
135130

136131
In the following example, a component overriding Starlight's [`Footer`](/reference/overrides/#footer-1) displays "Built with Starlight 🌟" on the homepage only, and otherwise shows the default footer on all other pages:
137132

138133
```astro
139134
---
140135
// src/components/ConditionalFooter.astro
141-
import type { Props } from '@astrojs/starlight/props';
142136
import Default from '@astrojs/starlight/components/Footer.astro';
143137
144-
const isHomepage = Astro.props.id === '';
138+
const isHomepage = Astro.locals.starlightRoute.id === '';
145139
---
146140
147141
{
148142
isHomepage ? (
149143
<footer>Built with Starlight 🌟</footer>
150144
) : (
151-
<Default {...Astro.props}>
145+
<Default>
152146
<slot />
153147
</Default>
154148
)
+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
title: Route Data
3+
description: Learn how Starlight’s page data model is used to render your pages and how you can customize it.
4+
---
5+
6+
import { Steps } from '@astrojs/starlight/components';
7+
8+
When Starlight renders a page in your documentation, it first creates a route data object to represent what is on that page.
9+
This guide explains how route data is generated, how to use it, and how you can customize it to modify Starlight’s default behavior.
10+
11+
See the [“Route Data Reference”](/reference/route-data/) for a full list of the available properties.
12+
13+
## What is route data?
14+
15+
Starlight route data is an object containing all the information required to render a single page.
16+
It includes information for the current page as well as data generated from your Starlight configuration.
17+
18+
## Using route data
19+
20+
All of Starlight’s components use route data to decide what to render for each page.
21+
For example, the [`siteTitle`](/reference/route-data/#sitetitle) string is used to display the site title and the [`sidebar`](/reference/route-data/#sidebar) array is used to render the global sidebar navigation.
22+
23+
You can access this data from the `Astro.locals.starlightRoute` global in Astro components:
24+
25+
```astro title="example.astro" {2}
26+
---
27+
const { siteTitle } = Astro.locals.starlightRoute;
28+
---
29+
30+
<p>The title of this site is “{siteTitle}”</p>
31+
```
32+
33+
This can be useful for example when building [component overrides](/guides/overriding-components/) to customize what you display.
34+
35+
## Customizing route data
36+
37+
Starlight’s route data works out of the box and does not require any configuration.
38+
However, for advanced use cases, you may want to customize route data for some or all pages to modify how your site displays.
39+
40+
This is a similar concept to [component overrides](/guides/overriding-components/), but instead of modifying how Starlight renders your data, you modify the data Starlight renders.
41+
42+
### When to customize route data
43+
44+
Customizing route data can be useful when you want to modify how Starlight processes your data in a way not possible with existing configuration options.
45+
46+
For example, you may want to filter sidebar items or customize titles for specific pages.
47+
Changes like this do not require modifying Starlight’s default components, only the data passed to those components.
48+
49+
### How to customize route data
50+
51+
You can customize route data using a special form of “middleware”.
52+
This is a function that is called every time Starlight renders a page and can modify values in the route data object.
53+
54+
<Steps>
55+
56+
1. Create a new file exporting an `onRequest` function using Starlight’s `defineRouteMiddleware()` utility:
57+
58+
```ts
59+
// src/routeData.ts
60+
import { defineRouteMiddleware } from '@astrojs/starlight/route-data';
61+
62+
export const onRequest = defineRouteMiddleware(() => {});
63+
```
64+
65+
2. Tell Starlight where your route data middleware file is located in `astro.config.mjs`:
66+
67+
```js ins={9}
68+
// astro.config.mjs
69+
import { defineConfig } from 'astro/config';
70+
import starlight from '@astrojs/starlight';
71+
72+
export default defineConfig({
73+
integrations: [
74+
starlight({
75+
title: 'My delightful docs site',
76+
routeMiddleware: './src/routeData.ts',
77+
}),
78+
],
79+
});
80+
```
81+
82+
3. Update your `onRequest` function to modify route data.
83+
84+
The first argument your middleware will receive is [Astro’s `context` object](https://docs.astro.build/en/reference/api-reference/).
85+
This contains full information about the current page render, including the current URL and `locals`.
86+
87+
In this example, we are going to make our docs more exciting by adding an exclamation mark to the end of every page’s title.
88+
89+
```ts
90+
// src/routeData.ts
91+
import { defineRouteMiddleware } from '@astrojs/starlight/route-data';
92+
93+
export const onRequest = defineRouteMiddleware((context) => {
94+
// Get the content collection entry for this page.
95+
const { entry } = context.locals.starlightRoute;
96+
// Update the title to add an exclamation mark.
97+
entry.data.title = entry.data.title + '!';
98+
});
99+
```
100+
101+
</Steps>
102+
103+
#### Multiple route middleware
104+
105+
Starlight also supports providing multiple middleware.
106+
Set `routeMiddleware` to an array of paths to add more than one middleware handler:
107+
108+
```js {9}
109+
// astro.config.mjs
110+
import { defineConfig } from 'astro/config';
111+
import starlight from '@astrojs/starlight';
112+
113+
export default defineConfig({
114+
integrations: [
115+
starlight({
116+
title: 'My site with multiple middleware',
117+
routeMiddleware: ['./src/middleware-one.ts', './src/middleware-two.ts'],
118+
}),
119+
],
120+
});
121+
```
122+
123+
#### Waiting for later route middleware
124+
125+
To wait for middleware later in the stack to run before executing your code, you can await the `next()` callback passed as the second argument to your middleware function.
126+
This can be useful to wait for a plugin’s middleware to run before making changes for example.
127+
128+
```ts "next" "await next();"
129+
// src/routeData.ts
130+
import { defineRouteMiddleware } from '@astrojs/starlight/route-data';
131+
132+
export const onRequest = defineRouteMiddleware(async (context, next) => {
133+
// Wait for later middleware to run.
134+
await next();
135+
// Modify route data.
136+
const { entry } = context.locals.starlightRoute;
137+
entry.data.title = entry.data.title + '!';
138+
});
139+
```

docs/src/content/docs/guides/sidebar.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ The configuration above generates the following sidebar:
191191
Starlight can automatically generate a group in your sidebar based on a directory of your docs.
192192
This is helpful when you do not want to manually enter each sidebar item in a group.
193193

194-
By default, pages are sorted in alphabetical order according to the file [`slug`](/reference/overrides/#slug).
194+
By default, pages are sorted in alphabetical order according to the file [`slug`](/reference/route-data/#slug).
195195

196196
Add an autogenerated group using an object with `label` and `autogenerate` properties. Your `autogenerate` configuration must specify the `directory` to use for sidebar entries. For example, with the following configuration:
197197

docs/src/content/docs/hi/guides/overriding-components.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ const { title } = Astro.props.entry.data;
100100
</style>
101101
```
102102

103-
[ओवरराइड्स संदर्भ](/hi/reference/overrides/#component-props) में सभी उपलब्ध प्रॉप्स के बारे में और जानें।
103+
[ओवरराइड्स संदर्भ](/hi/reference/route-data/) में सभी उपलब्ध प्रॉप्स के बारे में और जानें।
104104

105105
### केवल विशिष्ट पृष्ठों पर ही ओवरराइड करें
106106

docs/src/content/docs/hi/guides/sidebar.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ starlight({
139139
Starlight स्वचालित रूप से आपके दस्तावेज़ों की निर्देशिका के आधार पर आपके साइडबार में एक समूह उत्पन्न कर सकता है।
140140
यह तब सहायक होता है जब आप किसी समूह में प्रत्येक साइडबार आइटम को मैन्युअल रूप से दर्ज नहीं करना चाहते हैं।
141141

142-
डिफ़ॉल्ट रूप से, पेजों को फ़ाइल [`slug`](/hi/reference/overrides/#slug) के अनुसार वर्णानुक्रम में क्रमबद्ध किया जाता है।
142+
डिफ़ॉल्ट रूप से, पेजों को फ़ाइल [`slug`](/hi/reference/route-data/#slug) के अनुसार वर्णानुक्रम में क्रमबद्ध किया जाता है।
143143

144144
`label` और `autogenerate` गुणों वाले ऑब्जेक्ट का उपयोग करके एक स्वतः निर्मित समूह जोड़ें। साइडबार प्रविष्टियों के लिए उपयोग करने के लिए आपके `autogenerate` कॉन्फ़िगरेशन को `directory` निर्दिष्ट करना होगा। उदाहरण के लिए, निम्नलिखित कॉन्फ़िगरेशन के साथ:
145145

docs/src/content/docs/id/guides/overriding-components.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const { title } = Astro.props.entry.data;
101101
</style>
102102
```
103103

104-
Pelajari lebih lanjut tentang semua prop yang tersedia di [Referensi Penggantian](/id/reference/overrides/#component-props).
104+
Pelajari lebih lanjut tentang semua prop yang tersedia di [Referensi Penggantian](/id/reference/route-data/).
105105

106106
### Mengganti komponen hanya pada halaman tertentu
107107

docs/src/content/docs/id/guides/sidebar.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ Starlight dapat secara otomatis membuat grup di sidebar Anda berdasarkan direkto
191191
Ini berguna ketika Anda tidak ingin memasukkan setiap item sidebar secara manual ke dalam grup.
192192
Halaman akan diurutkan secara alfabetis berdasarkan nama file secara default.
193193

194-
Secara default, halaman diurutkan berdasarkan abjad menurut file [`slug`](/id/reference/overrides/#slug).
194+
Secara default, halaman diurutkan berdasarkan abjad menurut file [`slug`](/id/reference/route-data/#slug).
195195

196196
Tambahkan grup yang dihasilkan secara otomatis menggunakan objek dengan properti `label` dan `autogenerate`. Konfigurasi `autogenerate` Anda harus menentukan `directory` yang akan digunakan untuk entri sidebar. Sebagai contoh, dengan konfigurasi berikut:
197197

0 commit comments

Comments
 (0)