@astrojs/starlight 0.21.4 → 0.22.0
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 +69 -0
- package/__e2e__/fixtures/basics/astro.config.mjs +10 -0
- package/__e2e__/fixtures/basics/node_modules/.bin/astro +17 -0
- package/__e2e__/fixtures/basics/package.json +9 -0
- package/__e2e__/fixtures/basics/src/content/config.ts +6 -0
- package/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx +151 -0
- package/__e2e__/fixtures/basics/src/content/docs/tabs.mdx +37 -0
- package/__e2e__/fixtures/basics/src/env.d.ts +2 -0
- package/__e2e__/tabs.test.ts +122 -0
- package/__e2e__/test-utils.ts +53 -0
- package/components/ContentNotice.astro +31 -0
- package/components/DraftContentNotice.astro +8 -0
- package/components/FallbackContentNotice.astro +2 -21
- package/components/Head.astro +3 -3
- package/components/Icons.ts +10 -0
- package/components/Page.astro +2 -0
- package/components/SiteTitle.astro +2 -1
- package/components/ThemeSelect.astro +36 -48
- package/global.d.ts +1 -1
- package/index.astro +1 -1
- package/integrations/expressive-code/hast.d.ts +5 -0
- package/integrations/expressive-code/hast.mjs +9 -0
- package/integrations/shared/pathToLocale.ts +2 -1
- package/package.json +13 -3
- package/playwright.config.ts +15 -0
- package/schema.ts +16 -3
- package/schemas/components.ts +9 -0
- package/schemas/i18n.ts +18 -5
- package/schemas/site-title.ts +22 -0
- package/schemas/social.ts +2 -0
- package/style/props.css +1 -1
- package/translations/ar.json +1 -0
- package/translations/cs.json +1 -0
- package/translations/da.json +1 -0
- package/translations/de.json +1 -0
- package/translations/en.json +1 -0
- package/translations/es.json +1 -0
- package/translations/fa.json +8 -7
- package/translations/fr.json +1 -0
- package/translations/gl.json +1 -0
- package/translations/he.json +1 -0
- package/translations/hi.json +1 -0
- package/translations/id.json +1 -0
- package/translations/it.json +1 -0
- package/translations/ja.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/nb.json +1 -0
- package/translations/nl.json +1 -0
- package/translations/pl.json +1 -0
- package/translations/pt.json +1 -0
- package/translations/ro.json +1 -0
- package/translations/ru.json +5 -1
- package/translations/sv.json +1 -0
- package/translations/tr.json +1 -0
- package/translations/uk.json +1 -0
- package/translations/vi.json +1 -0
- package/translations/zh-CN.json +1 -0
- package/translations/zh-TW.json +1 -0
- package/user-components/Tabs.astro +48 -7
- package/user-components/file-tree-icons.ts +1 -0
- package/user-components/rehype-file-tree.ts +1 -1
- package/utils/createTranslationSystem.ts +10 -8
- package/utils/route-data.ts +14 -1
- package/utils/routing.ts +9 -6
- package/utils/translations.ts +6 -2
- package/utils/user-config.ts +33 -19
- package/virtual.d.ts +4 -0
package/translations/vi.json
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"page.lastUpdated": "Cập nhật lần cuối:",
|
|
19
19
|
"page.previousLink": "Tiếp",
|
|
20
20
|
"page.nextLink": "Trước",
|
|
21
|
+
"page.draft": "This content is a draft and will not be included in production builds.",
|
|
21
22
|
"404.text": "Không tìm thấy trang. Kiểm tra URL hoặc thử sử dụng thanh tìm kiếm.",
|
|
22
23
|
"aside.note": "Ghi chú",
|
|
23
24
|
"aside.tip": "Mẹo",
|
package/translations/zh-CN.json
CHANGED
package/translations/zh-TW.json
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"page.lastUpdated": "最後更新於:",
|
|
19
19
|
"page.previousLink": "前一則",
|
|
20
20
|
"page.nextLink": "下一則",
|
|
21
|
+
"page.draft": "This content is a draft and will not be included in production builds.",
|
|
21
22
|
"404.text": "找不到頁面。請檢查網址或改用搜尋功能。",
|
|
22
23
|
"aside.note": "注意",
|
|
23
24
|
"aside.tip": "提示",
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
import Icon from './Icon.astro';
|
|
3
3
|
import { processPanels } from './rehype-tabs';
|
|
4
4
|
|
|
5
|
+
interface Props {
|
|
6
|
+
syncKey?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { syncKey } = Astro.props;
|
|
5
10
|
const panelHtml = await Astro.slots.render('default');
|
|
6
11
|
const { html, panels } = processPanels(panelHtml);
|
|
7
12
|
---
|
|
8
13
|
|
|
9
|
-
<starlight-tabs>
|
|
14
|
+
<starlight-tabs data-sync-key={syncKey}>
|
|
10
15
|
{
|
|
11
16
|
panels && (
|
|
12
17
|
<div class="tablist-wrapper not-content">
|
|
@@ -17,7 +22,7 @@ const { html, panels } = processPanels(panelHtml);
|
|
|
17
22
|
role="tab"
|
|
18
23
|
href={'#' + panelId}
|
|
19
24
|
id={tabId}
|
|
20
|
-
aria-selected={idx === 0
|
|
25
|
+
aria-selected={idx === 0 ? 'true' : 'false'}
|
|
21
26
|
tabindex={idx !== 0 ? -1 : 0}
|
|
22
27
|
>
|
|
23
28
|
{icon && <Icon name={icon} />}
|
|
@@ -61,7 +66,7 @@ const { html, panels } = processPanels(panelHtml);
|
|
|
61
66
|
color: var(--sl-color-gray-3);
|
|
62
67
|
outline-offset: var(--sl-outline-offset-inside);
|
|
63
68
|
}
|
|
64
|
-
.tab [role='tab'][aria-selected] {
|
|
69
|
+
.tab [role='tab'][aria-selected='true'] {
|
|
65
70
|
color: var(--sl-color-white);
|
|
66
71
|
border-color: var(--sl-color-text-accent);
|
|
67
72
|
font-weight: 600;
|
|
@@ -74,20 +79,31 @@ const { html, panels } = processPanels(panelHtml);
|
|
|
74
79
|
|
|
75
80
|
<script>
|
|
76
81
|
class StarlightTabs extends HTMLElement {
|
|
82
|
+
// A map of sync keys to all tabs that are synced to that key.
|
|
83
|
+
static #syncedTabs = new Map<string, StarlightTabs[]>();
|
|
84
|
+
|
|
77
85
|
tabs: HTMLAnchorElement[];
|
|
78
86
|
panels: HTMLElement[];
|
|
87
|
+
#syncKey: string | undefined;
|
|
79
88
|
|
|
80
89
|
constructor() {
|
|
81
90
|
super();
|
|
82
91
|
const tablist = this.querySelector<HTMLUListElement>('[role="tablist"]')!;
|
|
83
92
|
this.tabs = [...tablist.querySelectorAll<HTMLAnchorElement>('[role="tab"]')];
|
|
84
93
|
this.panels = [...this.querySelectorAll<HTMLElement>(':scope > [role="tabpanel"]')];
|
|
94
|
+
this.#syncKey = this.dataset.syncKey;
|
|
95
|
+
|
|
96
|
+
if (this.#syncKey) {
|
|
97
|
+
const syncedTabs = StarlightTabs.#syncedTabs.get(this.#syncKey) ?? [];
|
|
98
|
+
syncedTabs.push(this);
|
|
99
|
+
StarlightTabs.#syncedTabs.set(this.#syncKey, syncedTabs);
|
|
100
|
+
}
|
|
85
101
|
|
|
86
102
|
this.tabs.forEach((tab, i) => {
|
|
87
103
|
// Handle clicks for mouse users
|
|
88
104
|
tab.addEventListener('click', (e) => {
|
|
89
105
|
e.preventDefault();
|
|
90
|
-
const currentTab = tablist.querySelector('[aria-selected]');
|
|
106
|
+
const currentTab = tablist.querySelector('[aria-selected="true"]');
|
|
91
107
|
if (e.currentTarget !== currentTab) {
|
|
92
108
|
this.switchTab(e.currentTarget as HTMLAnchorElement, i);
|
|
93
109
|
}
|
|
@@ -117,12 +133,17 @@ const { html, panels } = processPanels(panelHtml);
|
|
|
117
133
|
});
|
|
118
134
|
}
|
|
119
135
|
|
|
120
|
-
switchTab(newTab: HTMLAnchorElement | null | undefined, index: number) {
|
|
136
|
+
switchTab(newTab: HTMLAnchorElement | null | undefined, index: number, shouldSync = true) {
|
|
121
137
|
if (!newTab) return;
|
|
122
138
|
|
|
139
|
+
// If tabs should be synced, we store the current position so we can restore it after
|
|
140
|
+
// switching tabs to prevent the page from jumping when the new tab content is of a different
|
|
141
|
+
// height than the previous tab.
|
|
142
|
+
const previousTabsOffset = shouldSync ? this.getBoundingClientRect().top : 0;
|
|
143
|
+
|
|
123
144
|
// Mark all tabs as unselected and hide all tab panels.
|
|
124
145
|
this.tabs.forEach((tab) => {
|
|
125
|
-
tab.
|
|
146
|
+
tab.setAttribute('aria-selected', 'false');
|
|
126
147
|
tab.setAttribute('tabindex', '-1');
|
|
127
148
|
});
|
|
128
149
|
this.panels.forEach((oldPanel) => {
|
|
@@ -135,7 +156,27 @@ const { html, panels } = processPanels(panelHtml);
|
|
|
135
156
|
// Restore active tab to the default tab order.
|
|
136
157
|
newTab.removeAttribute('tabindex');
|
|
137
158
|
newTab.setAttribute('aria-selected', 'true');
|
|
138
|
-
|
|
159
|
+
if (shouldSync) {
|
|
160
|
+
newTab.focus();
|
|
161
|
+
StarlightTabs.#syncTabs(this, newTab.textContent);
|
|
162
|
+
window.scrollTo({
|
|
163
|
+
top: window.scrollY + (this.getBoundingClientRect().top - previousTabsOffset),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static #syncTabs(emitter: StarlightTabs, label: string | null) {
|
|
169
|
+
const syncKey = emitter.#syncKey;
|
|
170
|
+
if (!syncKey || !label) return;
|
|
171
|
+
const syncedTabs = StarlightTabs.#syncedTabs.get(syncKey);
|
|
172
|
+
if (!syncedTabs) return;
|
|
173
|
+
|
|
174
|
+
for (const receiver of syncedTabs) {
|
|
175
|
+
if (receiver === emitter) continue;
|
|
176
|
+
const labelIndex = receiver.tabs.findIndex((tab) => tab.textContent === label);
|
|
177
|
+
if (labelIndex === -1) continue;
|
|
178
|
+
receiver.switchTab(receiver.tabs[labelIndex], labelIndex, false);
|
|
179
|
+
}
|
|
139
180
|
}
|
|
140
181
|
}
|
|
141
182
|
|
|
@@ -168,7 +168,7 @@ function getFileIcon(fileName: string) {
|
|
|
168
168
|
|
|
169
169
|
/** Return the icon name for a file based on its file name. */
|
|
170
170
|
function getFileIconName(fileName: string) {
|
|
171
|
-
let icon = definitions.files[fileName];
|
|
171
|
+
let icon: string | undefined = definitions.files[fileName];
|
|
172
172
|
if (icon) return icon;
|
|
173
173
|
icon = getFileIconTypeFromExtension(fileName);
|
|
174
174
|
if (icon) return icon;
|
|
@@ -2,8 +2,8 @@ import type { i18nSchemaOutput } from '../schemas/i18n';
|
|
|
2
2
|
import builtinTranslations from '../translations/index';
|
|
3
3
|
import type { StarlightConfig } from './user-config';
|
|
4
4
|
|
|
5
|
-
export function createTranslationSystem(
|
|
6
|
-
userTranslations: Record<string,
|
|
5
|
+
export function createTranslationSystem<T extends i18nSchemaOutput>(
|
|
6
|
+
userTranslations: Record<string, T>,
|
|
7
7
|
config: Pick<StarlightConfig, 'defaultLocale' | 'locales'>
|
|
8
8
|
) {
|
|
9
9
|
/** User-configured default locale. */
|
|
@@ -67,18 +67,20 @@ function localeToLang(
|
|
|
67
67
|
return lang || defaultLang || 'en';
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
type BuiltInStrings = (typeof builtinTranslations)['en'];
|
|
71
|
+
|
|
70
72
|
/** Build a dictionary by layering preferred translation sources. */
|
|
71
|
-
function buildDictionary(
|
|
72
|
-
base:
|
|
73
|
-
...dictionaries: (
|
|
74
|
-
) {
|
|
73
|
+
function buildDictionary<T extends Record<string, string | undefined>>(
|
|
74
|
+
base: BuiltInStrings,
|
|
75
|
+
...dictionaries: (T | BuiltInStrings | undefined)[]
|
|
76
|
+
): BuiltInStrings & T {
|
|
75
77
|
const dictionary = { ...base };
|
|
76
78
|
// Iterate over alternate dictionaries to avoid overwriting preceding values with `undefined`.
|
|
77
79
|
for (const dict of dictionaries) {
|
|
78
80
|
for (const key in dict) {
|
|
79
|
-
const value = dict[key];
|
|
81
|
+
const value = dict[key as keyof typeof dict];
|
|
80
82
|
if (value) dictionary[key as keyof typeof dictionary] = value;
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
|
-
return dictionary;
|
|
85
|
+
return dictionary as BuiltInStrings & T;
|
|
84
86
|
}
|
package/utils/route-data.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface PageProps extends Route {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface StarlightRouteData extends Route {
|
|
18
|
+
/** Title of the site. */
|
|
19
|
+
siteTitle: string;
|
|
18
20
|
/** Array of Markdown headings extracted from the current page. */
|
|
19
21
|
headings: MarkdownHeading[];
|
|
20
22
|
/** Site navigation sidebar entries for this page. */
|
|
@@ -40,10 +42,12 @@ export function generateRouteData({
|
|
|
40
42
|
props: PageProps;
|
|
41
43
|
url: URL;
|
|
42
44
|
}): StarlightRouteData {
|
|
43
|
-
const { entry, locale } = props;
|
|
45
|
+
const { entry, locale, lang } = props;
|
|
44
46
|
const sidebar = getSidebar(url.pathname, locale);
|
|
47
|
+
const siteTitle = getSiteTitle(lang);
|
|
45
48
|
return {
|
|
46
49
|
...props,
|
|
50
|
+
siteTitle,
|
|
47
51
|
sidebar,
|
|
48
52
|
hasSidebar: entry.data.template !== 'splash',
|
|
49
53
|
pagination: getPrevNextLinks(sidebar, config.pagination, entry.data),
|
|
@@ -105,3 +109,12 @@ function getEditUrl({ entry, id, isFallback }: PageProps): URL | undefined {
|
|
|
105
109
|
}
|
|
106
110
|
return url ? new URL(url) : undefined;
|
|
107
111
|
}
|
|
112
|
+
|
|
113
|
+
/** Get the site title for a given language. **/
|
|
114
|
+
function getSiteTitle(lang: string): string {
|
|
115
|
+
const defaultLang = config.defaultLocale.lang as string;
|
|
116
|
+
if (lang && config.title[lang]) {
|
|
117
|
+
return config.title[lang] as string;
|
|
118
|
+
}
|
|
119
|
+
return config.title[defaultLang] as string;
|
|
120
|
+
}
|
package/utils/routing.ts
CHANGED
|
@@ -45,12 +45,15 @@ interface Path extends GetStaticPathsItem {
|
|
|
45
45
|
const normalizeIndexSlug = (slug: string) => (slug === 'index' ? '' : slug);
|
|
46
46
|
|
|
47
47
|
/** All entries in the docs content collection. */
|
|
48
|
-
const docs: StarlightDocsEntry[] = (
|
|
49
|
-
(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})
|
|
53
|
-
)
|
|
48
|
+
const docs: StarlightDocsEntry[] = (
|
|
49
|
+
(await getCollection('docs', ({ data }) => {
|
|
50
|
+
// In production, filter out drafts.
|
|
51
|
+
return import.meta.env.MODE !== 'production' || data.draft === false;
|
|
52
|
+
})) ?? []
|
|
53
|
+
).map(({ slug, ...entry }) => ({
|
|
54
|
+
...entry,
|
|
55
|
+
slug: normalizeIndexSlug(slug),
|
|
56
|
+
}));
|
|
54
57
|
|
|
55
58
|
function getRoutes(): Route[] {
|
|
56
59
|
const routes: Route[] = docs.map((entry) => ({
|
package/utils/translations.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { getCollection } from 'astro:content';
|
|
1
|
+
import { getCollection, type CollectionEntry, type DataCollectionKey } from 'astro:content';
|
|
2
2
|
import config from 'virtual:starlight/user-config';
|
|
3
3
|
import type { i18nSchemaOutput } from '../schemas/i18n';
|
|
4
4
|
import { createTranslationSystem } from './createTranslationSystem';
|
|
5
5
|
|
|
6
|
+
type UserI18nSchema = 'i18n' extends DataCollectionKey
|
|
7
|
+
? CollectionEntry<'i18n'>['data']
|
|
8
|
+
: i18nSchemaOutput;
|
|
9
|
+
|
|
6
10
|
/** Get all translation data from the i18n collection, keyed by `id`, which matches locale. */
|
|
7
11
|
async function loadTranslations() {
|
|
8
|
-
let userTranslations: Record<string,
|
|
12
|
+
let userTranslations: Record<string, UserI18nSchema> = {};
|
|
9
13
|
// Briefly override `console.warn()` to silence logging when a project has no i18n collection.
|
|
10
14
|
const warn = console.warn;
|
|
11
15
|
console.warn = () => {};
|
package/utils/user-config.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { LogoConfigSchema } from '../schemas/logo';
|
|
|
8
8
|
import { SidebarItemSchema } from '../schemas/sidebar';
|
|
9
9
|
import { SocialLinksSchema } from '../schemas/social';
|
|
10
10
|
import { TableOfContentsSchema } from '../schemas/tableOfContents';
|
|
11
|
+
import { TitleConfigSchema, TitleTransformConfigSchema } from '../schemas/site-title';
|
|
11
12
|
|
|
12
13
|
const LocaleSchema = z.object({
|
|
13
14
|
/** The label for this language to show in UI, e.g. `"English"`, `"العربية"`, or `"简体中文"`. */
|
|
@@ -33,9 +34,7 @@ const LocaleSchema = z.object({
|
|
|
33
34
|
|
|
34
35
|
const UserConfigSchema = z.object({
|
|
35
36
|
/** Title for your website. Will be used in metadata and as browser tab title. */
|
|
36
|
-
title:
|
|
37
|
-
.string()
|
|
38
|
-
.describe('Title for your website. Will be used in metadata and as browser tab title.'),
|
|
37
|
+
title: TitleConfigSchema(),
|
|
39
38
|
|
|
40
39
|
/** Description metadata for your website. Can be used in page metadata. */
|
|
41
40
|
description: z
|
|
@@ -211,17 +210,21 @@ const UserConfigSchema = z.object({
|
|
|
211
210
|
});
|
|
212
211
|
|
|
213
212
|
export const StarlightConfigSchema = UserConfigSchema.strict().transform(
|
|
214
|
-
({ locales, defaultLocale, ...config }, ctx) => {
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
({ title, locales, defaultLocale, ...config }, ctx) => {
|
|
214
|
+
const configuredLocales = Object.keys(locales ?? {});
|
|
215
|
+
|
|
216
|
+
// This is a multilingual site (more than one locale configured) or a monolingual site with
|
|
217
|
+
// only one locale configured (not a root locale).
|
|
218
|
+
// Monolingual sites with only one non-root locale needs their configuration to be defined in
|
|
219
|
+
// `config.locales` so that slugs can be correctly generated by taking into consideration the
|
|
220
|
+
// base path at which a language is served which is the key of the `config.locales` object.
|
|
221
|
+
if (locales !== undefined && configuredLocales.length >= 1) {
|
|
217
222
|
// Make sure we can find the default locale and if not, help the user set it.
|
|
218
223
|
// We treat the root locale as the default if present and no explicit default is set.
|
|
219
224
|
const defaultLocaleConfig = locales[defaultLocale || 'root'];
|
|
220
225
|
|
|
221
226
|
if (!defaultLocaleConfig) {
|
|
222
|
-
const availableLocales =
|
|
223
|
-
.map((l) => `"${l}"`)
|
|
224
|
-
.join(', ');
|
|
227
|
+
const availableLocales = configuredLocales.map((l) => `"${l}"`).join(', ');
|
|
225
228
|
ctx.addIssue({
|
|
226
229
|
code: 'custom',
|
|
227
230
|
message:
|
|
@@ -232,29 +235,40 @@ export const StarlightConfigSchema = UserConfigSchema.strict().transform(
|
|
|
232
235
|
return z.NEVER;
|
|
233
236
|
}
|
|
234
237
|
|
|
238
|
+
// Transform the title
|
|
239
|
+
const TitleSchema = TitleTransformConfigSchema(defaultLocaleConfig.lang as string);
|
|
240
|
+
const parsedTitle = TitleSchema.parse(title);
|
|
241
|
+
|
|
235
242
|
return {
|
|
236
243
|
...config,
|
|
244
|
+
title: parsedTitle,
|
|
237
245
|
/** Flag indicating if this site has multiple locales set up. */
|
|
238
|
-
isMultilingual:
|
|
246
|
+
isMultilingual: configuredLocales.length > 1,
|
|
239
247
|
/** Full locale object for this site’s default language. */
|
|
240
248
|
defaultLocale: { ...defaultLocaleConfig, locale: defaultLocale },
|
|
241
249
|
locales,
|
|
242
250
|
} as const;
|
|
243
251
|
}
|
|
244
252
|
|
|
245
|
-
// This is a monolingual site, so things are
|
|
253
|
+
// This is a monolingual site with no locales configured or only a root locale, so things are
|
|
254
|
+
// pretty simple.
|
|
255
|
+
/** Full locale object for this site’s default language. */
|
|
256
|
+
const defaultLocaleConfig = {
|
|
257
|
+
label: 'English',
|
|
258
|
+
lang: 'en',
|
|
259
|
+
dir: 'ltr',
|
|
260
|
+
locale: undefined,
|
|
261
|
+
...locales?.root,
|
|
262
|
+
};
|
|
263
|
+
/** Transform the title */
|
|
264
|
+
const TitleSchema = TitleTransformConfigSchema(defaultLocaleConfig.lang);
|
|
265
|
+
const parsedTitle = TitleSchema.parse(title);
|
|
246
266
|
return {
|
|
247
267
|
...config,
|
|
268
|
+
title: parsedTitle,
|
|
248
269
|
/** Flag indicating if this site has multiple locales set up. */
|
|
249
270
|
isMultilingual: false,
|
|
250
|
-
|
|
251
|
-
defaultLocale: {
|
|
252
|
-
label: 'English',
|
|
253
|
-
lang: 'en',
|
|
254
|
-
dir: 'ltr',
|
|
255
|
-
locale: undefined,
|
|
256
|
-
...locales?.root,
|
|
257
|
-
},
|
|
271
|
+
defaultLocale: defaultLocaleConfig,
|
|
258
272
|
locales: undefined,
|
|
259
273
|
} as const;
|
|
260
274
|
}
|
package/virtual.d.ts
CHANGED
|
@@ -44,6 +44,10 @@ declare module 'virtual:starlight/components/FallbackContentNotice' {
|
|
|
44
44
|
const FallbackContentNotice: typeof import('./components/FallbackContentNotice.astro').default;
|
|
45
45
|
export default FallbackContentNotice;
|
|
46
46
|
}
|
|
47
|
+
declare module 'virtual:starlight/components/DraftContentNotice' {
|
|
48
|
+
const DraftContentNotice: typeof import('./components/DraftContentNotice.astro').default;
|
|
49
|
+
export default DraftContentNotice;
|
|
50
|
+
}
|
|
47
51
|
|
|
48
52
|
declare module 'virtual:starlight/components/Footer' {
|
|
49
53
|
const Footer: typeof import('./components/Footer.astro').default;
|