@astrojs/starlight 0.31.1 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +99 -0
- package/components/Banner.astro +1 -3
- package/components/ContentPanel.astro +0 -4
- package/components/DraftContentNotice.astro +0 -1
- package/components/EditLink.astro +1 -2
- package/components/FallbackContentNotice.astro +0 -1
- package/components/Footer.astro +3 -5
- package/components/Head.astro +1 -2
- package/components/Header.astro +5 -6
- package/components/Hero.astro +1 -2
- package/components/LanguageSelect.astro +2 -3
- package/components/LastUpdated.astro +1 -3
- package/components/MarkdownContent.astro +0 -1
- package/components/MobileMenuFooter.astro +3 -4
- package/components/MobileMenuToggle.astro +0 -1
- package/components/MobileTableOfContents.astro +1 -2
- package/components/Page.astro +32 -32
- package/components/PageFrame.astro +2 -3
- package/components/PageSidebar.astro +3 -5
- package/components/PageTitle.astro +1 -2
- package/components/Pagination.astro +1 -2
- package/components/Search.astro +17 -3
- package/components/Sidebar.astro +3 -5
- package/components/SidebarPersister.astro +1 -2
- package/components/SidebarSublist.astro +2 -1
- package/components/SiteTitle.astro +1 -2
- package/components/SkipLink.astro +0 -1
- package/components/SocialIcons.astro +0 -1
- package/components/StarlightPage.astro +7 -3
- package/components/TableOfContents.astro +1 -2
- package/components/ThemeProvider.astro +0 -1
- package/components/ThemeSelect.astro +0 -1
- package/components/TwoColumnContent.astro +1 -5
- package/index.ts +7 -9
- package/integrations/asides.ts +4 -7
- package/integrations/expressive-code/index.ts +15 -10
- package/integrations/shared/{pathToLocale.ts → absolutePathToLang.ts} +7 -5
- package/integrations/virtual-user-config.ts +27 -0
- package/locals.d.ts +26 -0
- package/locals.ts +37 -2
- package/package.json +5 -3
- package/props.ts +13 -1
- package/route-data.ts +11 -0
- package/routes/common.astro +5 -11
- package/routes/ssr/index.astro +1 -1
- package/routes/static/404.astro +1 -41
- package/routes/static/index.astro +1 -4
- package/schemas/pagefind.ts +97 -33
- package/types.ts +1 -0
- package/utils/i18n.ts +0 -20
- package/utils/navigation.ts +19 -36
- package/utils/plugins.ts +316 -141
- package/utils/{route-data.ts → routing/data.ts} +56 -30
- package/utils/{routing.ts → routing/index.ts} +6 -44
- package/utils/routing/middleware.ts +81 -0
- package/utils/routing/types.ts +96 -0
- package/utils/slugs.ts +2 -10
- package/utils/starlight-page.ts +2 -10
- package/utils/user-config.ts +8 -0
- package/virtual-internal.d.ts +4 -0
package/utils/navigation.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AstroError } from 'astro/errors';
|
|
2
|
-
import config from 'virtual:starlight/user-config';
|
|
3
2
|
import project from 'virtual:starlight/project-context';
|
|
3
|
+
import config from 'virtual:starlight/user-config';
|
|
4
4
|
import type { Badge, I18nBadge, I18nBadgeConfig } from '../schemas/badge';
|
|
5
5
|
import type { PrevNextLinkConfig } from '../schemas/prevNextLink';
|
|
6
6
|
import type {
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
SidebarItem,
|
|
11
11
|
SidebarLinkItem,
|
|
12
12
|
} from '../schemas/sidebar';
|
|
13
|
+
import { getCollectionPathFromRoot } from './collection';
|
|
13
14
|
import { createPathFormatter } from './createPathFormatter';
|
|
14
15
|
import { formatPath } from './format-path';
|
|
15
16
|
import { BuiltInDefaultLocale, pickLang } from './i18n';
|
|
@@ -19,10 +20,16 @@ import {
|
|
|
19
20
|
stripExtension,
|
|
20
21
|
stripLeadingAndTrailingSlashes,
|
|
21
22
|
} from './path';
|
|
22
|
-
import { getLocaleRoutes, routes
|
|
23
|
+
import { getLocaleRoutes, routes } from './routing';
|
|
24
|
+
import type {
|
|
25
|
+
SidebarGroup,
|
|
26
|
+
SidebarLink,
|
|
27
|
+
PaginationLinks,
|
|
28
|
+
Route,
|
|
29
|
+
SidebarEntry,
|
|
30
|
+
} from './routing/types';
|
|
23
31
|
import { localeToLang, localizedId, slugToPathname } from './slugs';
|
|
24
32
|
import type { StarlightConfig } from './user-config';
|
|
25
|
-
import { getCollectionPathFromRoot } from './collection';
|
|
26
33
|
|
|
27
34
|
const DirKey = Symbol('DirKey');
|
|
28
35
|
const SlugKey = Symbol('SlugKey');
|
|
@@ -31,25 +38,6 @@ const neverPathFormatter = createPathFormatter({ trailingSlash: 'never' });
|
|
|
31
38
|
|
|
32
39
|
const docsCollectionPathFromRoot = getCollectionPathFromRoot('docs', project);
|
|
33
40
|
|
|
34
|
-
export interface Link {
|
|
35
|
-
type: 'link';
|
|
36
|
-
label: string;
|
|
37
|
-
href: string;
|
|
38
|
-
isCurrent: boolean;
|
|
39
|
-
badge: Badge | undefined;
|
|
40
|
-
attrs: LinkHTMLAttributes;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface Group {
|
|
44
|
-
type: 'group';
|
|
45
|
-
label: string;
|
|
46
|
-
entries: (Link | Group)[];
|
|
47
|
-
collapsed: boolean;
|
|
48
|
-
badge: Badge | undefined;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export type SidebarEntry = Link | Group;
|
|
52
|
-
|
|
53
41
|
/**
|
|
54
42
|
* A representation of the route structure. For each object entry:
|
|
55
43
|
* if it’s a folder, the key is the directory name, and value is the directory
|
|
@@ -107,7 +95,7 @@ function groupFromAutogenerateConfig(
|
|
|
107
95
|
locale: string | undefined,
|
|
108
96
|
routes: Route[],
|
|
109
97
|
currentPathname: string
|
|
110
|
-
):
|
|
98
|
+
): SidebarGroup {
|
|
111
99
|
const { collapsed: subgroupCollapsed, directory } = item.autogenerate;
|
|
112
100
|
const localeDir = locale ? locale + '/' + directory : directory;
|
|
113
101
|
const dirDocs = routes.filter((doc) => {
|
|
@@ -186,7 +174,7 @@ function makeSidebarLink(
|
|
|
186
174
|
label: string,
|
|
187
175
|
badge?: Badge,
|
|
188
176
|
attrs?: LinkHTMLAttributes
|
|
189
|
-
):
|
|
177
|
+
): SidebarLink {
|
|
190
178
|
if (!isAbsolute(href)) {
|
|
191
179
|
href = formatPath(href);
|
|
192
180
|
}
|
|
@@ -203,7 +191,7 @@ function makeLink({
|
|
|
203
191
|
href: string;
|
|
204
192
|
badge?: Badge | undefined;
|
|
205
193
|
attrs?: LinkHTMLAttributes | undefined;
|
|
206
|
-
}):
|
|
194
|
+
}): SidebarLink {
|
|
207
195
|
return { type: 'link', ...opts, badge, isCurrent: false, attrs };
|
|
208
196
|
}
|
|
209
197
|
|
|
@@ -275,7 +263,7 @@ function treeify(routes: Route[], locale: string | undefined, baseDir: string):
|
|
|
275
263
|
}
|
|
276
264
|
|
|
277
265
|
/** Create a link entry for a given content collection entry. */
|
|
278
|
-
function linkFromRoute(route: Route):
|
|
266
|
+
function linkFromRoute(route: Route): SidebarLink {
|
|
279
267
|
return makeSidebarLink(
|
|
280
268
|
slugToPathname(route.slug),
|
|
281
269
|
route.entry.data.sidebar.label || route.entry.data.title,
|
|
@@ -315,7 +303,7 @@ function groupFromDir(
|
|
|
315
303
|
currentPathname: string,
|
|
316
304
|
locale: string | undefined,
|
|
317
305
|
collapsed: boolean
|
|
318
|
-
):
|
|
306
|
+
): SidebarGroup {
|
|
319
307
|
const entries = sortDirEntries(Object.entries(dir)).map(([key, dirOrRoute]) =>
|
|
320
308
|
dirToItem(dirOrRoute, `${fullPath}/${key}`, key, currentPathname, locale, collapsed)
|
|
321
309
|
);
|
|
@@ -451,7 +439,7 @@ function recursivelyBuildSidebarIdentity(sidebar: SidebarEntry[]): string {
|
|
|
451
439
|
}
|
|
452
440
|
|
|
453
441
|
/** Turn the nested tree structure of a sidebar into a flat list of all the links. */
|
|
454
|
-
export function flattenSidebar(sidebar: SidebarEntry[]):
|
|
442
|
+
export function flattenSidebar(sidebar: SidebarEntry[]): SidebarLink[] {
|
|
455
443
|
return sidebar.flatMap((entry) =>
|
|
456
444
|
entry.type === 'group' ? flattenSidebar(entry.entries) : entry
|
|
457
445
|
);
|
|
@@ -465,12 +453,7 @@ export function getPrevNextLinks(
|
|
|
465
453
|
prev?: PrevNextLinkConfig;
|
|
466
454
|
next?: PrevNextLinkConfig;
|
|
467
455
|
}
|
|
468
|
-
): {
|
|
469
|
-
/** Link to previous page in the sidebar. */
|
|
470
|
-
prev: Link | undefined;
|
|
471
|
-
/** Link to next page in the sidebar. */
|
|
472
|
-
next: Link | undefined;
|
|
473
|
-
} {
|
|
456
|
+
): PaginationLinks {
|
|
474
457
|
const entries = flattenSidebar(sidebar);
|
|
475
458
|
const currentIndex = entries.findIndex((entry) => entry.isCurrent);
|
|
476
459
|
const prev = applyPrevNextLinkConfig(entries[currentIndex - 1], paginationEnabled, config.prev);
|
|
@@ -484,10 +467,10 @@ export function getPrevNextLinks(
|
|
|
484
467
|
|
|
485
468
|
/** Apply a prev/next link config to a navigation link. */
|
|
486
469
|
function applyPrevNextLinkConfig(
|
|
487
|
-
link:
|
|
470
|
+
link: SidebarLink | undefined,
|
|
488
471
|
paginationEnabled: boolean,
|
|
489
472
|
config: PrevNextLinkConfig | undefined
|
|
490
|
-
):
|
|
473
|
+
): SidebarLink | undefined {
|
|
491
474
|
// Explicitly remove the link.
|
|
492
475
|
if (config === false) return undefined;
|
|
493
476
|
// Use the generated link if any.
|
package/utils/plugins.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import type { AstroIntegration, HookParameters } from 'astro';
|
|
1
|
+
import type { AstroIntegration, HookParameters as AstroHookParameters } from 'astro';
|
|
2
|
+
import { AstroError } from 'astro/errors';
|
|
2
3
|
import { z } from 'astro/zod';
|
|
3
|
-
import { StarlightConfigSchema, type StarlightUserConfig } from '../utils/user-config';
|
|
4
4
|
import { parseWithFriendlyErrors } from '../utils/error-map';
|
|
5
|
+
import {
|
|
6
|
+
StarlightConfigSchema,
|
|
7
|
+
type StarlightConfig,
|
|
8
|
+
type StarlightUserConfig,
|
|
9
|
+
} from '../utils/user-config';
|
|
5
10
|
import type { UserI18nSchema } from './translations';
|
|
11
|
+
import { createTranslationSystemFromFs } from './translations-fs';
|
|
12
|
+
import { absolutePathToLang as getAbsolutePathFromLang } from '../integrations/shared/absolutePathToLang';
|
|
6
13
|
|
|
7
14
|
/**
|
|
8
15
|
* Runs Starlight plugins in the order that they are configured after validating the user-provided
|
|
@@ -30,22 +37,61 @@ export async function runPlugins(
|
|
|
30
37
|
'Invalid plugins config passed to starlight integration'
|
|
31
38
|
);
|
|
32
39
|
|
|
33
|
-
// A list of Astro integrations added by the various plugins.
|
|
34
|
-
const integrations: AstroIntegration[] = [];
|
|
35
40
|
// A list of translations injected by the various plugins keyed by locale.
|
|
36
41
|
const pluginTranslations: PluginTranslations = {};
|
|
42
|
+
// A list of route middleware added by the various plugins.
|
|
43
|
+
const routeMiddlewareConfigs: Array<z.output<typeof routeMiddlewareConfigSchema>> = [];
|
|
44
|
+
|
|
45
|
+
for (const {
|
|
46
|
+
hooks: { 'i18n:setup': i18nSetup },
|
|
47
|
+
} of pluginsConfig) {
|
|
48
|
+
if (i18nSetup) {
|
|
49
|
+
await i18nSetup({
|
|
50
|
+
injectTranslations(translations) {
|
|
51
|
+
// Merge the translations injected by the plugin.
|
|
52
|
+
for (const [locale, localeTranslations] of Object.entries(translations)) {
|
|
53
|
+
pluginTranslations[locale] ??= {};
|
|
54
|
+
Object.assign(pluginTranslations[locale]!, localeTranslations);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const useTranslations = createTranslationSystemFromFs(
|
|
62
|
+
starlightConfig,
|
|
63
|
+
context.config,
|
|
64
|
+
pluginTranslations
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
function absolutePathToLang(path: string) {
|
|
68
|
+
return getAbsolutePathFromLang(path, { astroConfig: context.config, starlightConfig });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// A list of Astro integrations added by the various plugins.
|
|
72
|
+
const integrations: AstroIntegration[] = [];
|
|
37
73
|
|
|
38
74
|
for (const {
|
|
39
75
|
name,
|
|
40
|
-
hooks: { setup },
|
|
76
|
+
hooks: { 'config:setup': configSetup, setup: deprecatedSetup },
|
|
41
77
|
} of pluginsConfig) {
|
|
78
|
+
// A refinement in the schema ensures that at least one of the two hooks is defined.
|
|
79
|
+
const setup = (configSetup ?? deprecatedSetup)!;
|
|
80
|
+
|
|
42
81
|
await setup({
|
|
43
82
|
config: pluginsUserConfig ? { ...userConfig, plugins: pluginsUserConfig } : userConfig,
|
|
44
83
|
updateConfig(newConfig) {
|
|
45
84
|
// Ensure that plugins do not update the `plugins` config key.
|
|
46
85
|
if ('plugins' in newConfig) {
|
|
47
|
-
throw new
|
|
48
|
-
`The
|
|
86
|
+
throw new AstroError(
|
|
87
|
+
`The \`${name}\` plugin tried to update the \`plugins\` config key which is not supported.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
if ('routeMiddleware' in newConfig) {
|
|
91
|
+
throw new AstroError(
|
|
92
|
+
`The \`${name}\` plugin tried to update the \`routeMiddleware\` config key which is not supported.`,
|
|
93
|
+
'Use the `addRouteMiddleware()` utility instead.\n' +
|
|
94
|
+
'See https://starlight.astro.build/reference/plugins/#addroutemiddleware for more details.'
|
|
49
95
|
);
|
|
50
96
|
}
|
|
51
97
|
|
|
@@ -65,6 +111,9 @@ export async function runPlugins(
|
|
|
65
111
|
// Collect any Astro integrations added by the plugin.
|
|
66
112
|
integrations.push(integration);
|
|
67
113
|
},
|
|
114
|
+
addRouteMiddleware(middlewareConfig) {
|
|
115
|
+
routeMiddlewareConfigs.push(middlewareConfig);
|
|
116
|
+
},
|
|
68
117
|
astroConfig: {
|
|
69
118
|
...context.config,
|
|
70
119
|
integrations: [...context.config.integrations, ...integrations],
|
|
@@ -72,22 +121,37 @@ export async function runPlugins(
|
|
|
72
121
|
command: context.command,
|
|
73
122
|
isRestart: context.isRestart,
|
|
74
123
|
logger: context.logger.fork(name),
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
for (const [locale, localeTranslations] of Object.entries(translations)) {
|
|
78
|
-
pluginTranslations[locale] ??= {};
|
|
79
|
-
Object.assign(pluginTranslations[locale]!, localeTranslations);
|
|
80
|
-
}
|
|
81
|
-
},
|
|
124
|
+
useTranslations,
|
|
125
|
+
absolutePathToLang,
|
|
82
126
|
});
|
|
83
127
|
}
|
|
84
128
|
|
|
85
|
-
|
|
129
|
+
applyPluginMiddleware(routeMiddlewareConfigs, starlightConfig);
|
|
130
|
+
|
|
131
|
+
return { integrations, starlightConfig, pluginTranslations, useTranslations, absolutePathToLang };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Updates `routeMiddleware` in the Starlight config to add plugin middlewares in the correct order. */
|
|
135
|
+
function applyPluginMiddleware(
|
|
136
|
+
routeMiddlewareConfigs: { entrypoint: string; order: 'default' | 'pre' | 'post' }[],
|
|
137
|
+
starlightConfig: StarlightConfig
|
|
138
|
+
) {
|
|
139
|
+
const middlewareBuckets = routeMiddlewareConfigs.reduce<
|
|
140
|
+
Record<'pre' | 'default' | 'post', string[]>
|
|
141
|
+
>(
|
|
142
|
+
(buckets, { entrypoint, order = 'default' }) => {
|
|
143
|
+
buckets[order].push(entrypoint);
|
|
144
|
+
return buckets;
|
|
145
|
+
},
|
|
146
|
+
{ pre: [], default: [], post: [] }
|
|
147
|
+
);
|
|
148
|
+
starlightConfig.routeMiddleware.unshift(...middlewareBuckets.pre);
|
|
149
|
+
starlightConfig.routeMiddleware.push(...middlewareBuckets.default, ...middlewareBuckets.post);
|
|
86
150
|
}
|
|
87
151
|
|
|
88
152
|
export function injectPluginTranslationsTypes(
|
|
89
153
|
translations: PluginTranslations,
|
|
90
|
-
injectTypes:
|
|
154
|
+
injectTypes: AstroHookParameters<'astro:config:done'>['injectTypes']
|
|
91
155
|
) {
|
|
92
156
|
const allKeys = new Set<string>();
|
|
93
157
|
|
|
@@ -118,140 +182,246 @@ const astroIntegrationSchema = z.object({
|
|
|
118
182
|
hooks: z.object({}).passthrough().default({}),
|
|
119
183
|
}) as z.Schema<AstroIntegration>;
|
|
120
184
|
|
|
185
|
+
const routeMiddlewareConfigSchema = z.object({
|
|
186
|
+
entrypoint: z.string(),
|
|
187
|
+
order: z.enum(['pre', 'post', 'default']).default('default'),
|
|
188
|
+
});
|
|
189
|
+
|
|
121
190
|
const baseStarlightPluginSchema = z.object({
|
|
122
191
|
/** Name of the Starlight plugin. */
|
|
123
192
|
name: z.string(),
|
|
124
193
|
});
|
|
125
194
|
|
|
195
|
+
const configSetupHookSchema = z
|
|
196
|
+
.function(
|
|
197
|
+
z.tuple([
|
|
198
|
+
z.object({
|
|
199
|
+
/**
|
|
200
|
+
* A read-only copy of the user-supplied Starlight configuration.
|
|
201
|
+
*
|
|
202
|
+
* Note that this configuration may have been updated by other plugins configured
|
|
203
|
+
* before this one.
|
|
204
|
+
*/
|
|
205
|
+
config: z.any() as z.Schema<
|
|
206
|
+
// The configuration passed to plugins should contains the list of plugins.
|
|
207
|
+
StarlightUserConfig & { plugins?: z.input<typeof baseStarlightPluginSchema>[] }
|
|
208
|
+
>,
|
|
209
|
+
/**
|
|
210
|
+
* A callback function to update the user-supplied Starlight configuration.
|
|
211
|
+
*
|
|
212
|
+
* You only need to provide the configuration values that you want to update but no deep
|
|
213
|
+
* merge is performed.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* {
|
|
217
|
+
* name: 'My Starlight Plugin',
|
|
218
|
+
* hooks: {
|
|
219
|
+
* 'config:setup'({ updateConfig }) {
|
|
220
|
+
* updateConfig({
|
|
221
|
+
* description: 'Custom description',
|
|
222
|
+
* });
|
|
223
|
+
* }
|
|
224
|
+
* }
|
|
225
|
+
* }
|
|
226
|
+
*/
|
|
227
|
+
updateConfig: z.function(
|
|
228
|
+
z.tuple([
|
|
229
|
+
z.record(z.any()) as z.Schema<Partial<Omit<StarlightUserConfig, 'routeMiddleware'>>>,
|
|
230
|
+
]),
|
|
231
|
+
z.void()
|
|
232
|
+
),
|
|
233
|
+
/**
|
|
234
|
+
* A callback function to add an Astro integration required by this plugin.
|
|
235
|
+
*
|
|
236
|
+
* @see https://docs.astro.build/en/reference/integrations-reference/
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* {
|
|
240
|
+
* name: 'My Starlight Plugin',
|
|
241
|
+
* hooks: {
|
|
242
|
+
* 'config:setup'({ addIntegration }) {
|
|
243
|
+
* addIntegration({
|
|
244
|
+
* name: 'My Plugin Astro Integration',
|
|
245
|
+
* hooks: {
|
|
246
|
+
* 'astro:config:setup': () => {
|
|
247
|
+
* // …
|
|
248
|
+
* },
|
|
249
|
+
* },
|
|
250
|
+
* });
|
|
251
|
+
* }
|
|
252
|
+
* }
|
|
253
|
+
* }
|
|
254
|
+
*/
|
|
255
|
+
addIntegration: z.function(z.tuple([astroIntegrationSchema]), z.void()),
|
|
256
|
+
/**
|
|
257
|
+
* A callback function to register additional route middleware handlers.
|
|
258
|
+
*
|
|
259
|
+
* If the order of execution is important, a plugin can use the `order` option to enforce
|
|
260
|
+
* running first or last.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* {
|
|
264
|
+
* name: 'My Starlight Plugin',
|
|
265
|
+
* hooks: {
|
|
266
|
+
* setup({ addRouteMiddleware }) {
|
|
267
|
+
* addRouteMiddleware({ entrypoint: '@me/my-plugin/route-middleware' });
|
|
268
|
+
* },
|
|
269
|
+
* },
|
|
270
|
+
* }
|
|
271
|
+
*/
|
|
272
|
+
addRouteMiddleware: z.function(z.tuple([routeMiddlewareConfigSchema]), z.void()),
|
|
273
|
+
/**
|
|
274
|
+
* A read-only copy of the user-supplied Astro configuration.
|
|
275
|
+
*
|
|
276
|
+
* Note that this configuration is resolved before any other integrations have run.
|
|
277
|
+
*
|
|
278
|
+
* @see https://docs.astro.build/en/reference/integrations-reference/#config-option
|
|
279
|
+
*/
|
|
280
|
+
astroConfig: z.any() as z.Schema<StarlightPluginContext['config']>,
|
|
281
|
+
/**
|
|
282
|
+
* The command used to run Starlight.
|
|
283
|
+
*
|
|
284
|
+
* @see https://docs.astro.build/en/reference/integrations-reference/#command-option
|
|
285
|
+
*/
|
|
286
|
+
command: z.any() as z.Schema<StarlightPluginContext['command']>,
|
|
287
|
+
/**
|
|
288
|
+
* `false` when the dev server starts, `true` when a reload is triggered.
|
|
289
|
+
*
|
|
290
|
+
* @see https://docs.astro.build/en/reference/integrations-reference/#isrestart-option
|
|
291
|
+
*/
|
|
292
|
+
isRestart: z.any() as z.Schema<StarlightPluginContext['isRestart']>,
|
|
293
|
+
/**
|
|
294
|
+
* An instance of the Astro integration logger with all logged messages prefixed with the
|
|
295
|
+
* plugin name.
|
|
296
|
+
*
|
|
297
|
+
* @see https://docs.astro.build/en/reference/integrations-reference/#astrointegrationlogger
|
|
298
|
+
*/
|
|
299
|
+
logger: z.any() as z.Schema<StarlightPluginContext['logger']>,
|
|
300
|
+
/**
|
|
301
|
+
* A callback function to generate a utility function to access UI strings for a given
|
|
302
|
+
* language.
|
|
303
|
+
*
|
|
304
|
+
* @see https://starlight.astro.build/guides/i18n/#using-ui-translations
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* {
|
|
308
|
+
* name: 'My Starlight Plugin',
|
|
309
|
+
* hooks: {
|
|
310
|
+
* 'config:setup'({ useTranslations, logger }) {
|
|
311
|
+
* const t = useTranslations('en');
|
|
312
|
+
* logger.info(t('builtWithStarlight.label'));
|
|
313
|
+
* // ^ Logs 'Built with Starlight' to the console.
|
|
314
|
+
* }
|
|
315
|
+
* }
|
|
316
|
+
* }
|
|
317
|
+
*/
|
|
318
|
+
useTranslations: z.any() as z.Schema<ReturnType<typeof createTranslationSystemFromFs>>,
|
|
319
|
+
/**
|
|
320
|
+
* A callback function to get the language for a given absolute file path. The returned
|
|
321
|
+
* language can be used with the `useTranslations` helper to get UI strings for that
|
|
322
|
+
* language.
|
|
323
|
+
*
|
|
324
|
+
* This can be particularly useful in remark or rehype plugins to get the language for
|
|
325
|
+
* the current file being processed and use it to get the appropriate UI strings for that
|
|
326
|
+
* language.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* {
|
|
330
|
+
* name: 'My Starlight Plugin',
|
|
331
|
+
* hooks: {
|
|
332
|
+
* 'config:setup'({ absolutePathToLang, useTranslations, logger }) {
|
|
333
|
+
* const lang = absolutePathToLang('/absolute/path/to/project/src/content/docs/fr/index.mdx');
|
|
334
|
+
* const t = useTranslations(lang);
|
|
335
|
+
* logger.info(t('aside.tip'));
|
|
336
|
+
* // ^ Logs 'Astuce' to the console.
|
|
337
|
+
* }
|
|
338
|
+
* }
|
|
339
|
+
* }
|
|
340
|
+
*/
|
|
341
|
+
absolutePathToLang: z.function(z.tuple([z.string()]), z.string()),
|
|
342
|
+
}),
|
|
343
|
+
]),
|
|
344
|
+
z.union([z.void(), z.promise(z.void())])
|
|
345
|
+
)
|
|
346
|
+
.optional();
|
|
347
|
+
|
|
126
348
|
/**
|
|
127
349
|
* A plugin `config` and `updateConfig` argument are purposely not validated using the Starlight
|
|
128
350
|
* user config schema but properly typed for user convenience because we do not want to run any of
|
|
129
351
|
* the Zod `transform`s used in the user config schema when running plugins.
|
|
130
352
|
*/
|
|
131
|
-
const starlightPluginSchema = baseStarlightPluginSchema
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
),
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
astroConfig: z.any() as z.Schema<StarlightPluginContext['config']>,
|
|
204
|
-
/**
|
|
205
|
-
* The command used to run Starlight.
|
|
206
|
-
*
|
|
207
|
-
* @see https://docs.astro.build/en/reference/integrations-reference/#command-option
|
|
208
|
-
*/
|
|
209
|
-
command: z.any() as z.Schema<StarlightPluginContext['command']>,
|
|
210
|
-
/**
|
|
211
|
-
* `false` when the dev server starts, `true` when a reload is triggered.
|
|
212
|
-
*
|
|
213
|
-
* @see https://docs.astro.build/en/reference/integrations-reference/#isrestart-option
|
|
214
|
-
*/
|
|
215
|
-
isRestart: z.any() as z.Schema<StarlightPluginContext['isRestart']>,
|
|
216
|
-
/**
|
|
217
|
-
* An instance of the Astro integration logger with all logged messages prefixed with the
|
|
218
|
-
* plugin name.
|
|
219
|
-
*
|
|
220
|
-
* @see https://docs.astro.build/en/reference/integrations-reference/#astrointegrationlogger
|
|
221
|
-
*/
|
|
222
|
-
logger: z.any() as z.Schema<StarlightPluginContext['logger']>,
|
|
223
|
-
/**
|
|
224
|
-
* A callback function to add or update translations strings.
|
|
225
|
-
*
|
|
226
|
-
* @see https://starlight.astro.build/guides/i18n/#extend-translation-schema
|
|
227
|
-
*
|
|
228
|
-
* @example
|
|
229
|
-
* {
|
|
230
|
-
* name: 'My Starlight Plugin',
|
|
231
|
-
* hooks: {
|
|
232
|
-
* setup({ injectTranslations }) {
|
|
233
|
-
* injectTranslations({
|
|
234
|
-
* en: {
|
|
235
|
-
* 'myPlugin.doThing': 'Do the thing',
|
|
236
|
-
* },
|
|
237
|
-
* fr: {
|
|
238
|
-
* 'myPlugin.doThing': 'Faire le truc',
|
|
239
|
-
* },
|
|
240
|
-
* });
|
|
241
|
-
* }
|
|
242
|
-
* }
|
|
243
|
-
* }
|
|
244
|
-
*/
|
|
245
|
-
injectTranslations: z.function(
|
|
246
|
-
z.tuple([z.record(z.string(), z.record(z.string(), z.string()))]),
|
|
247
|
-
z.void()
|
|
248
|
-
),
|
|
249
|
-
}),
|
|
250
|
-
]),
|
|
251
|
-
z.union([z.void(), z.promise(z.void())])
|
|
252
|
-
),
|
|
253
|
-
}),
|
|
254
|
-
});
|
|
353
|
+
const starlightPluginSchema = baseStarlightPluginSchema
|
|
354
|
+
.extend({
|
|
355
|
+
/** The different hooks available to the plugin. */
|
|
356
|
+
hooks: z.object({
|
|
357
|
+
/**
|
|
358
|
+
* Plugin internationalization setup function allowing to inject translations strings for the
|
|
359
|
+
* plugin in various locales. These translations will be available in the `config:setup` hook
|
|
360
|
+
* and plugin UI.
|
|
361
|
+
*/
|
|
362
|
+
'i18n:setup': z
|
|
363
|
+
.function(
|
|
364
|
+
z.tuple([
|
|
365
|
+
z.object({
|
|
366
|
+
/**
|
|
367
|
+
* A callback function to add or update translations strings.
|
|
368
|
+
*
|
|
369
|
+
* @see https://starlight.astro.build/guides/i18n/#extend-translation-schema
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* {
|
|
373
|
+
* name: 'My Starlight Plugin',
|
|
374
|
+
* hooks: {
|
|
375
|
+
* 'i18n:setup'({ injectTranslations }) {
|
|
376
|
+
* injectTranslations({
|
|
377
|
+
* en: {
|
|
378
|
+
* 'myPlugin.doThing': 'Do the thing',
|
|
379
|
+
* },
|
|
380
|
+
* fr: {
|
|
381
|
+
* 'myPlugin.doThing': 'Faire le truc',
|
|
382
|
+
* },
|
|
383
|
+
* });
|
|
384
|
+
* }
|
|
385
|
+
* }
|
|
386
|
+
* }
|
|
387
|
+
*/
|
|
388
|
+
injectTranslations: z.function(
|
|
389
|
+
z.tuple([z.record(z.string(), z.record(z.string(), z.string()))]),
|
|
390
|
+
z.void()
|
|
391
|
+
),
|
|
392
|
+
}),
|
|
393
|
+
]),
|
|
394
|
+
z.union([z.void(), z.promise(z.void())])
|
|
395
|
+
)
|
|
396
|
+
.optional(),
|
|
397
|
+
/**
|
|
398
|
+
* Plugin configuration setup function called with an object containing various values that
|
|
399
|
+
* can be used by the plugin to interact with Starlight.
|
|
400
|
+
*/
|
|
401
|
+
'config:setup': configSetupHookSchema,
|
|
402
|
+
/**
|
|
403
|
+
* @deprecated Use the `config:setup` hook instead as `setup` will be removed in a future
|
|
404
|
+
* version.
|
|
405
|
+
*/
|
|
406
|
+
setup: configSetupHookSchema,
|
|
407
|
+
}),
|
|
408
|
+
})
|
|
409
|
+
.superRefine((plugin, ctx) => {
|
|
410
|
+
if (!plugin.hooks['config:setup'] && !plugin.hooks.setup) {
|
|
411
|
+
ctx.addIssue({
|
|
412
|
+
code: z.ZodIssueCode.custom,
|
|
413
|
+
message: 'A plugin must define at least a `config:setup` hook.',
|
|
414
|
+
});
|
|
415
|
+
} else if (plugin.hooks['config:setup'] && plugin.hooks.setup) {
|
|
416
|
+
ctx.addIssue({
|
|
417
|
+
code: z.ZodIssueCode.custom,
|
|
418
|
+
message:
|
|
419
|
+
'A plugin cannot define both a `config:setup` and `setup` hook. ' +
|
|
420
|
+
'As `setup` is deprecated and will be removed in a future version, ' +
|
|
421
|
+
'consider using `config:setup` instead.',
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
});
|
|
255
425
|
|
|
256
426
|
const starlightPluginsConfigSchema = z.array(starlightPluginSchema).default([]);
|
|
257
427
|
|
|
@@ -259,6 +429,11 @@ type StarlightPluginsUserConfig = z.input<typeof starlightPluginsConfigSchema>;
|
|
|
259
429
|
|
|
260
430
|
export type StarlightPlugin = z.input<typeof starlightPluginSchema>;
|
|
261
431
|
|
|
432
|
+
export type HookParameters<
|
|
433
|
+
Hook extends keyof StarlightPlugin['hooks'],
|
|
434
|
+
HookFn = StarlightPlugin['hooks'][Hook],
|
|
435
|
+
> = HookFn extends (...args: any) => any ? Parameters<HookFn>[0] : never;
|
|
436
|
+
|
|
262
437
|
export type StarlightUserConfigWithPlugins = StarlightUserConfig & {
|
|
263
438
|
/**
|
|
264
439
|
* A list of plugins to extend Starlight with.
|
|
@@ -273,7 +448,7 @@ export type StarlightUserConfigWithPlugins = StarlightUserConfig & {
|
|
|
273
448
|
};
|
|
274
449
|
|
|
275
450
|
export type StarlightPluginContext = Pick<
|
|
276
|
-
|
|
451
|
+
AstroHookParameters<'astro:config:setup'>,
|
|
277
452
|
'command' | 'config' | 'isRestart' | 'logger'
|
|
278
453
|
>;
|
|
279
454
|
|