@astrojs/starlight 0.28.6 → 0.29.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 +18 -0
- package/components/Icons.ts +2 -0
- package/integrations/asides.ts +4 -4
- package/integrations/expressive-code/index.ts +5 -1
- package/package.json +6 -6
- package/schemas/social.ts +2 -0
- package/user-components/Aside.astro +2 -2
- package/user-components/rehype-tabs.ts +3 -3
- package/utils/i18n.ts +1 -1
- package/utils/navigation.ts +59 -36
- package/utils/starlight-page.ts +4 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @astrojs/starlight
|
|
2
2
|
|
|
3
|
+
## 0.29.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2551](https://github.com/withastro/starlight/pull/2551) [`154c8e3`](https://github.com/withastro/starlight/commit/154c8e337819c7d7ebf4ff4dd55db0d10607620b) Thanks [@hippotastic](https://github.com/hippotastic)! - Updates the `astro-expressive-code` dependency to the latest version (0.38).
|
|
8
|
+
|
|
9
|
+
The new version allows using `ec.config.mjs` to selectively override individual Expressive Code styles and settings provided by Starlight themes and plugins, speeds up Shiki language loading, and adds the config option `expressiveCode.shiki.injectLangsIntoNestedCodeBlocks`. See the [Expressive Code release notes](https://expressive-code.com/releases/#0380) for full details.
|
|
10
|
+
|
|
11
|
+
- [#2252](https://github.com/withastro/starlight/pull/2252) [`6116db0`](https://github.com/withastro/starlight/commit/6116db03a4157c0f0caa210690ef0dcdd001a287) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Improves build performance for sites with large sidebars
|
|
12
|
+
|
|
13
|
+
This release adds a caching layer to Starlight’s sidebar generation logic, reducing the number of times sidebars need to be regenerated while building a site. Some benchmarks for projects with a complex sidebar saw builds complete more than 35% faster with this change.
|
|
14
|
+
|
|
15
|
+
- [#2503](https://github.com/withastro/starlight/pull/2503) [`a4c8edd`](https://github.com/withastro/starlight/commit/a4c8eddc53993068c0f60159fecc123013827ef0) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Improves the accessibility of asides and tabs by removing some unnecessary HTML landmarks.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#2579](https://github.com/withastro/starlight/pull/2579) [`241966b`](https://github.com/withastro/starlight/commit/241966bd0523a2e82891d622b2a97b2f3646bc41) Thanks [@RafidMuhymin](https://github.com/RafidMuhymin)! - Adds social link icon for Nostr
|
|
20
|
+
|
|
3
21
|
## 0.28.6
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/components/Icons.ts
CHANGED
|
@@ -158,6 +158,8 @@ export const BuiltInIcons = {
|
|
|
158
158
|
'<path d="M6.49 19.04h-.23L5.13 17.9v-.23l1.73-1.71h1.2l.15.15v1.2L6.5 19.04ZM5.13 6.31V6.1l1.13-1.13h.23L8.2 6.68v1.2l-.15.15h-1.2zm9.96 9.09h-1.65l-.14-.13v-3.83c0-.68-.27-1.2-1.1-1.23c-.42 0-.9 0-1.43.02l-.07.08v4.96l-.14.14H8.9l-.13-.14V8.73l.13-.14h3.7a2.6 2.6 0 0 1 2.61 2.6v4.08l-.13.14Zm-8.37-2.44H.14L0 12.82v-1.64l.14-.14h6.58l.14.14v1.64zm17.14 0h-6.58l-.14-.14v-1.64l.14-.14h6.58l.14.14v1.64zM11.05 6.55V1.64l.14-.14h1.65l.14.14v4.9l-.14.14h-1.65zm0 15.81v-4.9l.14-.14h1.65l.14.13v4.91l-.14.14h-1.65z"/>',
|
|
159
159
|
deno: '<path d="M12 0a12 12 0 1 1 0 24 12 12 0 0 1 0-24m-.47 6.8c-3.49 0-6.2 2.19-6.2 4.92 0 2.58 2.5 4.23 6.37 4.15h.12l.42-.02-.1.28v.03l.09.22v.03l.02.04.02.07.02.04.01.05.02.05.02.07.02.08.02.06.02.08.02.09.02.09.03.1.01.06.03.1.02.1.03.15.02.07.02.11.03.12.02.12.04.17.02.15.04.2.02.1.03.15.03.15.04.22.04.23.04.23.04.24.04.24.04.26.04.26.04.2.05.34.02.14.06.36.04.3.04.22.04.31.03.16a10.76 10.76 0 0 0 6.53-3.41l.05-.06-.24-.89-.64-2.37-.39-1.47-.35-1.3-.21-.78-.14-.5-.08-.3-.07-.26-.03-.11-.02-.07-.01-.03v-.03a6.04 6.04 0 0 0-2.05-2.97 6.75 6.75 0 0 0-4.25-1.35M8.47 19.3a.59.59 0 0 0-.72.4v.01l-.53 1.96q.5.24 1.01.43l.08.03.57-2.11V20a.59.59 0 0 0-.41-.7m3.26-1.43a.59.59 0 0 0-.71.4v.01l-.8 2.96v.01a.59.59 0 0 0 1.12.3l.8-2.96v-.02l.02-.06v-.02l-.02-.1-.02-.14-.02-.08a.58.58 0 0 0-.37-.3Zm-5.55-3.04a1 1 0 0 0-.04.09v.02l-.8 2.95v.02a.59.59 0 0 0 1.13.3v-.01l.72-2.68a5.3 5.3 0 0 1-1.01-.7Zm-1.9-3.4a.59.59 0 0 0-.72.4v.02l-.8 2.95v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7m17.87-.68a.59.59 0 0 0-.72.4v.02l-.8 2.95v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7M2.55 6.81a10.7 10.7 0 0 0-1.26 3.93.59.59 0 0 0 1-.22v-.02l.8-2.95v-.01a.59.59 0 0 0-.55-.73m17.59.02a.59.59 0 0 0-.72.4v.01l-.8 2.96v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7Zm-7.85 1.93a.75.75 0 1 1 0 1.5.75.75 0 0 1 0-1.5M6.01 4.03a.59.59 0 0 0-.71.4v.02L4.5 7.4v.01a.59.59 0 0 0 1.12.3l.8-2.96v-.01a.59.59 0 0 0-.41-.7Zm10.24.56a.59.59 0 0 0-.71.4V5L15 7q.52.26.99.6l.05.04.62-2.32V5.3a.59.59 0 0 0-.41-.7m-5.21-3.34a11 11 0 0 0-1.12.16l-.07.01L9.1 4.2v.01a.59.59 0 0 0 1.13.3l.8-2.96v-.01a.6.6 0 0 0 0-.27m7.34 2.04-.16.58v.02a.59.59 0 0 0 1.13.3V4.2l.02-.07a11 11 0 0 0-.92-.77zm-4.64-1.94-.28 1.05a.59.59 0 0 0 1.13.31v-.01l.3-1.1q-.52-.15-1.06-.24z"/>',
|
|
160
160
|
jsr: '<path d="M3.7 5.54v3.7H0v7.38h7.38v1.84h12.93v-3.7H24V7.39h-7.38V5.54Zm1.84 1.85h1.85v7.38H1.84v-3.7h1.84v1.85h1.85zm3.7 0h5.53v1.84h-3.7v1.85h3.7v5.53H9.23v-1.84h3.7v-1.85h-3.7Zm7.38 1.84h5.53v3.7h-1.84v-1.85h-1.85v5.54h-1.84z"/>',
|
|
161
|
+
nostr:
|
|
162
|
+
'<path d="M21.6 10.6v9.7a.7.7 0 0 1-.6.6h-8a.7.7 0 0 1-.6-.6v-1.8c0-2.2.3-4.4.8-5.3a2 2 0 0 1 1.3-1c1-.4 2.9-.2 3.7-.2 0 0 2.3 0 2.3-1.3 0-1-1-1-1-1-1.2 0-2 0-2.6-.2-1-.4-1-1.1-1-1.3 0-2.7-4-3-7.5-2.4-3.9.7 0 6.2 0 13.5v1a.7.7 0 0 1-.7.6H3.8a.7.7 0 0 1-.6-.6V3.5a.7.7 0 0 1 .6-.6h3.7a.7.7 0 0 1 .7.6c0 .6.6.9 1 .6 1.3-1 3-1.5 5-1.5 4.2 0 7.4 2.5 7.4 8zm-7-2a1.4 1.4 0 1 0-2.9 0 1.4 1.4 0 0 0 2.9 0z"/>',
|
|
161
163
|
};
|
|
162
164
|
|
|
163
165
|
export const Icons = {
|
package/integrations/asides.ts
CHANGED
|
@@ -107,10 +107,10 @@ function transformUnhandledDirective(
|
|
|
107
107
|
* ```astro
|
|
108
108
|
* <aside class="starlight-aside starlight-aside--tip" aria-label="Did you know?">
|
|
109
109
|
* <p class="starlight-aside__title" aria-hidden="true">Did you know?</p>
|
|
110
|
-
* <
|
|
110
|
+
* <div class="starlight-aside__content">
|
|
111
111
|
* <p>Astro helps you build faster websites with “Islands Architecture”.</p>
|
|
112
|
-
* </
|
|
113
|
-
* </
|
|
112
|
+
* </div>
|
|
113
|
+
* </aside>
|
|
114
114
|
* ```
|
|
115
115
|
*/
|
|
116
116
|
function remarkAsides(options: AsidesOptions): Plugin<[], Root> {
|
|
@@ -204,7 +204,7 @@ function remarkAsides(options: AsidesOptions): Plugin<[], Root> {
|
|
|
204
204
|
),
|
|
205
205
|
...titleNode,
|
|
206
206
|
]),
|
|
207
|
-
h('
|
|
207
|
+
h('div', { class: 'starlight-aside__content' }, node.children),
|
|
208
208
|
]
|
|
209
209
|
);
|
|
210
210
|
|
|
@@ -8,6 +8,7 @@ import type { AstroIntegration } from 'astro';
|
|
|
8
8
|
import type { StarlightConfig } from '../../types';
|
|
9
9
|
import type { createTranslationSystemFromFs } from '../../utils/translations-fs';
|
|
10
10
|
import { pathToLocale } from '../shared/pathToLocale';
|
|
11
|
+
import { slugToLocale } from '../shared/slugToLocale';
|
|
11
12
|
import {
|
|
12
13
|
applyStarlightUiThemeColors,
|
|
13
14
|
preprocessThemes,
|
|
@@ -152,7 +153,10 @@ export function getStarlightEcConfigPreprocessor({
|
|
|
152
153
|
},
|
|
153
154
|
...otherStyleOverrides,
|
|
154
155
|
},
|
|
155
|
-
getBlockLocale: ({ file }) =>
|
|
156
|
+
getBlockLocale: ({ file }) =>
|
|
157
|
+
file.url
|
|
158
|
+
? slugToLocale(file.url.pathname.slice(1), starlightConfig)
|
|
159
|
+
: pathToLocale(file.path, { starlightConfig, astroConfig }),
|
|
156
160
|
plugins,
|
|
157
161
|
...rest,
|
|
158
162
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/starlight",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Build beautiful, high-performance documentation websites with Astro",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -170,14 +170,14 @@
|
|
|
170
170
|
"astro": "^4.14.0"
|
|
171
171
|
},
|
|
172
172
|
"devDependencies": {
|
|
173
|
-
"@astrojs/markdown-remark": "^5.
|
|
173
|
+
"@astrojs/markdown-remark": "^5.3.0",
|
|
174
174
|
"@playwright/test": "^1.45.0",
|
|
175
175
|
"@types/js-yaml": "^4.0.9",
|
|
176
176
|
"@types/node": "^18.16.19",
|
|
177
177
|
"@vitest/coverage-v8": "^1.6.0",
|
|
178
|
-
"astro": "^4.
|
|
179
|
-
"
|
|
180
|
-
"
|
|
178
|
+
"astro": "^4.16.10",
|
|
179
|
+
"linkedom": "^0.18.4",
|
|
180
|
+
"vitest": "^1.6.0"
|
|
181
181
|
},
|
|
182
182
|
"dependencies": {
|
|
183
183
|
"@astrojs/mdx": "^3.1.3",
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
"@pagefind/default-ui": "^1.0.3",
|
|
186
186
|
"@types/hast": "^3.0.4",
|
|
187
187
|
"@types/mdast": "^4.0.4",
|
|
188
|
-
"astro-expressive-code": "^0.
|
|
188
|
+
"astro-expressive-code": "^0.38.3",
|
|
189
189
|
"bcp-47": "^2.1.0",
|
|
190
190
|
"hast-util-from-html": "^2.0.1",
|
|
191
191
|
"hast-util-select": "^6.0.2",
|
package/schemas/social.ts
CHANGED
|
@@ -35,6 +35,7 @@ export const socialLinks = [
|
|
|
35
35
|
'zulip',
|
|
36
36
|
'pinterest',
|
|
37
37
|
'tiktok',
|
|
38
|
+
'nostr',
|
|
38
39
|
] as const;
|
|
39
40
|
|
|
40
41
|
export const SocialLinksSchema = () =>
|
|
@@ -85,6 +86,7 @@ export const SocialLinksSchema = () =>
|
|
|
85
86
|
zulip: 'Zulip',
|
|
86
87
|
pinterest: 'Pinterest',
|
|
87
88
|
tiktok: 'TikTok',
|
|
89
|
+
nostr: 'Nostr',
|
|
88
90
|
}[key];
|
|
89
91
|
labelledLinks[key] = { label, url };
|
|
90
92
|
}
|
|
@@ -29,7 +29,7 @@ if (!title) {
|
|
|
29
29
|
<p class="starlight-aside__title" aria-hidden="true">
|
|
30
30
|
<Icon name={icons[type]} class="starlight-aside__icon" />{title}
|
|
31
31
|
</p>
|
|
32
|
-
<
|
|
32
|
+
<div class="starlight-aside__content">
|
|
33
33
|
<slot />
|
|
34
|
-
</
|
|
34
|
+
</div>
|
|
35
35
|
</aside>
|
|
@@ -47,7 +47,7 @@ const getIDs = () => {
|
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Rehype processor to extract tab panel data and turn each
|
|
50
|
-
* `<starlight-tab-item>` into a `<
|
|
50
|
+
* `<starlight-tab-item>` into a `<div>` with the necessary
|
|
51
51
|
* attributes.
|
|
52
52
|
*/
|
|
53
53
|
const tabsProcessor = rehype()
|
|
@@ -73,8 +73,8 @@ const tabsProcessor = rehype()
|
|
|
73
73
|
// Remove `<TabItem>` props
|
|
74
74
|
delete node.properties.dataLabel;
|
|
75
75
|
delete node.properties.dataIcon;
|
|
76
|
-
// Turn into `<
|
|
77
|
-
node.tagName = '
|
|
76
|
+
// Turn into `<div>` with required attributes
|
|
77
|
+
node.tagName = 'div';
|
|
78
78
|
node.properties.id = ids.panelId;
|
|
79
79
|
node.properties['aria-labelledby'] = ids.tabId;
|
|
80
80
|
node.properties.role = 'tabpanel';
|
package/utils/i18n.ts
CHANGED
|
@@ -79,7 +79,7 @@ function getAstroI18nConfig(config: StarlightConfig): NonNullable<AstroConfig['i
|
|
|
79
79
|
? Object.entries(config.locales).map(([locale, localeConfig]) => {
|
|
80
80
|
return {
|
|
81
81
|
codes: [localeConfig?.lang ?? locale],
|
|
82
|
-
path: locale === 'root' ? localeConfig?.lang ?? BuiltInDefaultLocale.lang : locale,
|
|
82
|
+
path: locale === 'root' ? (localeConfig?.lang ?? BuiltInDefaultLocale.lang) : locale,
|
|
83
83
|
};
|
|
84
84
|
})
|
|
85
85
|
: [config.defaultLocale.lang],
|
package/utils/navigation.ts
CHANGED
|
@@ -20,6 +20,8 @@ import type { StarlightConfig } from './user-config';
|
|
|
20
20
|
const DirKey = Symbol('DirKey');
|
|
21
21
|
const SlugKey = Symbol('SlugKey');
|
|
22
22
|
|
|
23
|
+
const neverPathFormatter = createPathFormatter({ trailingSlash: 'never' });
|
|
24
|
+
|
|
23
25
|
export interface Link {
|
|
24
26
|
type: 'link';
|
|
25
27
|
label: string;
|
|
@@ -73,11 +75,11 @@ function configItemToEntry(
|
|
|
73
75
|
routes: Route[]
|
|
74
76
|
): SidebarEntry {
|
|
75
77
|
if ('link' in item) {
|
|
76
|
-
return linkFromSidebarLinkItem(item, locale
|
|
78
|
+
return linkFromSidebarLinkItem(item, locale);
|
|
77
79
|
} else if ('autogenerate' in item) {
|
|
78
80
|
return groupFromAutogenerateConfig(item, locale, routes, currentPathname);
|
|
79
81
|
} else if ('slug' in item) {
|
|
80
|
-
return linkFromInternalSidebarLinkItem(item, locale
|
|
82
|
+
return linkFromInternalSidebarLinkItem(item, locale);
|
|
81
83
|
} else {
|
|
82
84
|
const label = pickLang(item.translations, localeToLang(locale)) || item.label;
|
|
83
85
|
return {
|
|
@@ -121,11 +123,7 @@ function groupFromAutogenerateConfig(
|
|
|
121
123
|
const isAbsolute = (link: string) => /^https?:\/\//.test(link);
|
|
122
124
|
|
|
123
125
|
/** Create a link entry from a manual link item in user config. */
|
|
124
|
-
function linkFromSidebarLinkItem(
|
|
125
|
-
item: SidebarLinkItem,
|
|
126
|
-
locale: string | undefined,
|
|
127
|
-
currentPathname: string
|
|
128
|
-
) {
|
|
126
|
+
function linkFromSidebarLinkItem(item: SidebarLinkItem, locale: string | undefined) {
|
|
129
127
|
let href = item.link;
|
|
130
128
|
if (!isAbsolute(href)) {
|
|
131
129
|
href = ensureLeadingSlash(href);
|
|
@@ -133,20 +131,13 @@ function linkFromSidebarLinkItem(
|
|
|
133
131
|
if (locale) href = '/' + locale + href;
|
|
134
132
|
}
|
|
135
133
|
const label = pickLang(item.translations, localeToLang(locale)) || item.label;
|
|
136
|
-
return makeSidebarLink(
|
|
137
|
-
href,
|
|
138
|
-
label,
|
|
139
|
-
currentPathname,
|
|
140
|
-
getSidebarBadge(item.badge, locale, label),
|
|
141
|
-
item.attrs
|
|
142
|
-
);
|
|
134
|
+
return makeSidebarLink(href, label, getSidebarBadge(item.badge, locale, label), item.attrs);
|
|
143
135
|
}
|
|
144
136
|
|
|
145
137
|
/** Create a link entry from an automatic internal link item in user config. */
|
|
146
138
|
function linkFromInternalSidebarLinkItem(
|
|
147
139
|
item: InternalSidebarLinkItem,
|
|
148
|
-
locale: string | undefined
|
|
149
|
-
currentPathname: string
|
|
140
|
+
locale: string | undefined
|
|
150
141
|
) {
|
|
151
142
|
// Astro passes root `index.[md|mdx]` entries with a slug of `index`
|
|
152
143
|
const slug = item.slug === 'index' ? '' : item.slug;
|
|
@@ -169,50 +160,39 @@ function linkFromInternalSidebarLinkItem(
|
|
|
169
160
|
}
|
|
170
161
|
const label =
|
|
171
162
|
pickLang(item.translations, localeToLang(locale)) || item.label || entry.entry.data.title;
|
|
172
|
-
return makeSidebarLink(
|
|
173
|
-
entry.slug,
|
|
174
|
-
label,
|
|
175
|
-
currentPathname,
|
|
176
|
-
getSidebarBadge(item.badge, locale, label),
|
|
177
|
-
item.attrs
|
|
178
|
-
);
|
|
163
|
+
return makeSidebarLink(entry.slug, label, getSidebarBadge(item.badge, locale, label), item.attrs);
|
|
179
164
|
}
|
|
180
165
|
|
|
181
166
|
/** Process sidebar link options to create a link entry. */
|
|
182
167
|
function makeSidebarLink(
|
|
183
168
|
href: string,
|
|
184
169
|
label: string,
|
|
185
|
-
currentPathname: string,
|
|
186
170
|
badge?: Badge,
|
|
187
171
|
attrs?: LinkHTMLAttributes
|
|
188
172
|
): Link {
|
|
189
173
|
if (!isAbsolute(href)) {
|
|
190
174
|
href = formatPath(href);
|
|
191
175
|
}
|
|
192
|
-
|
|
193
|
-
return makeLink({ label, href, isCurrent, badge, attrs });
|
|
176
|
+
return makeLink({ label, href, badge, attrs });
|
|
194
177
|
}
|
|
195
178
|
|
|
196
179
|
/** Create a link entry */
|
|
197
180
|
function makeLink({
|
|
198
|
-
isCurrent = false,
|
|
199
181
|
attrs = {},
|
|
200
182
|
badge = undefined,
|
|
201
183
|
...opts
|
|
202
184
|
}: {
|
|
203
185
|
label: string;
|
|
204
186
|
href: string;
|
|
205
|
-
isCurrent?: boolean;
|
|
206
187
|
badge?: Badge | undefined;
|
|
207
188
|
attrs?: LinkHTMLAttributes | undefined;
|
|
208
189
|
}): Link {
|
|
209
|
-
return { type: 'link', ...opts, badge, isCurrent, attrs };
|
|
190
|
+
return { type: 'link', ...opts, badge, isCurrent: false, attrs };
|
|
210
191
|
}
|
|
211
192
|
|
|
212
193
|
/** Test if two paths are equivalent even if formatted differently. */
|
|
213
194
|
function pathsMatch(pathA: string, pathB: string) {
|
|
214
|
-
|
|
215
|
-
return format(pathA) === format(pathB);
|
|
195
|
+
return neverPathFormatter(pathA) === neverPathFormatter(pathB);
|
|
216
196
|
}
|
|
217
197
|
|
|
218
198
|
/** Get the segments leading to a page. */
|
|
@@ -268,11 +248,10 @@ function treeify(routes: Route[], baseDir: string): Dir {
|
|
|
268
248
|
}
|
|
269
249
|
|
|
270
250
|
/** Create a link entry for a given content collection entry. */
|
|
271
|
-
function linkFromRoute(route: Route
|
|
251
|
+
function linkFromRoute(route: Route): Link {
|
|
272
252
|
return makeSidebarLink(
|
|
273
253
|
slugToPathname(route.slug),
|
|
274
254
|
route.entry.data.sidebar.label || route.entry.data.title,
|
|
275
|
-
currentPathname,
|
|
276
255
|
route.entry.data.sidebar.badge,
|
|
277
256
|
route.entry.data.sidebar.attrs
|
|
278
257
|
);
|
|
@@ -286,7 +265,7 @@ function getOrder(routeOrDir: Route | Dir): number {
|
|
|
286
265
|
return isDir(routeOrDir)
|
|
287
266
|
? Math.min(...Object.values(routeOrDir).flatMap(getOrder))
|
|
288
267
|
: // If no order value is found, set it to the largest number possible.
|
|
289
|
-
routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE;
|
|
268
|
+
(routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE);
|
|
290
269
|
}
|
|
291
270
|
|
|
292
271
|
/** Sort a directory’s entries by user-specified order or alphabetically if no order specified. */
|
|
@@ -333,7 +312,7 @@ function dirToItem(
|
|
|
333
312
|
): SidebarEntry {
|
|
334
313
|
return isDir(dirOrRoute)
|
|
335
314
|
? groupFromDir(dirOrRoute, fullPath, dirName, currentPathname, locale, collapsed)
|
|
336
|
-
: linkFromRoute(dirOrRoute
|
|
315
|
+
: linkFromRoute(dirOrRoute);
|
|
337
316
|
}
|
|
338
317
|
|
|
339
318
|
/** Create a sidebar entry for a given content directory. */
|
|
@@ -348,9 +327,25 @@ function sidebarFromDir(
|
|
|
348
327
|
);
|
|
349
328
|
}
|
|
350
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Intermediate sidebar represents sidebar entries generated from the user config for a specific
|
|
332
|
+
* locale and do not contain any information about the current page.
|
|
333
|
+
* These representations are cached per locale to avoid regenerating them for each page.
|
|
334
|
+
* When generating the final sidebar for a page, the intermediate sidebar is cloned and the current
|
|
335
|
+
* page is marked as such.
|
|
336
|
+
*
|
|
337
|
+
* @see getSidebarFromIntermediateSidebar
|
|
338
|
+
*/
|
|
339
|
+
const intermediateSidebars = new Map<string | undefined, SidebarEntry[]>();
|
|
340
|
+
|
|
351
341
|
/** Get the sidebar for the current page using the global config. */
|
|
352
342
|
export function getSidebar(pathname: string, locale: string | undefined): SidebarEntry[] {
|
|
353
|
-
|
|
343
|
+
let intermediateSidebar = intermediateSidebars.get(locale);
|
|
344
|
+
if (!intermediateSidebar) {
|
|
345
|
+
intermediateSidebar = getSidebarFromConfig(config.sidebar, pathname, locale);
|
|
346
|
+
intermediateSidebars.set(locale, intermediateSidebar);
|
|
347
|
+
}
|
|
348
|
+
return getSidebarFromIntermediateSidebar(intermediateSidebar, pathname);
|
|
354
349
|
}
|
|
355
350
|
|
|
356
351
|
/** Get the sidebar for the current page using the specified sidebar config. */
|
|
@@ -368,6 +363,34 @@ export function getSidebarFromConfig(
|
|
|
368
363
|
}
|
|
369
364
|
}
|
|
370
365
|
|
|
366
|
+
/** Transform an intermediate sidebar into a sidebar for the current page. */
|
|
367
|
+
function getSidebarFromIntermediateSidebar(
|
|
368
|
+
intermediateSidebar: SidebarEntry[],
|
|
369
|
+
pathname: string
|
|
370
|
+
): SidebarEntry[] {
|
|
371
|
+
const sidebar = structuredClone(intermediateSidebar);
|
|
372
|
+
setIntermediateSidebarCurrentEntry(sidebar, pathname);
|
|
373
|
+
return sidebar;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/** Marks the current page as such in an intermediate sidebar. */
|
|
377
|
+
function setIntermediateSidebarCurrentEntry(
|
|
378
|
+
intermediateSidebar: SidebarEntry[],
|
|
379
|
+
pathname: string
|
|
380
|
+
): boolean {
|
|
381
|
+
for (const entry of intermediateSidebar) {
|
|
382
|
+
if (entry.type === 'link' && pathsMatch(encodeURI(entry.href), pathname)) {
|
|
383
|
+
entry.isCurrent = true;
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (entry.type === 'group' && setIntermediateSidebarCurrentEntry(entry.entries, pathname)) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
|
|
371
394
|
/** Generates a deterministic string based on the content of the passed sidebar. */
|
|
372
395
|
export function getSidebarHash(sidebar: SidebarEntry[]): string {
|
|
373
396
|
let hash = 0;
|
package/utils/starlight-page.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from './route-data';
|
|
13
13
|
import type { StarlightDocsEntry } from './routing';
|
|
14
14
|
import { slugToLocaleData, urlToSlug } from './slugs';
|
|
15
|
-
import { getPrevNextLinks, getSidebarFromConfig } from './navigation';
|
|
15
|
+
import { getPrevNextLinks, getSidebar, getSidebarFromConfig } from './navigation';
|
|
16
16
|
import { docsSchema } from '../schema';
|
|
17
17
|
import type { Prettify, RemoveIndexSignature } from './types';
|
|
18
18
|
import { DeprecatedLabelsPropProxy } from './i18n';
|
|
@@ -115,11 +115,9 @@ export async function generateStarlightPageRouteData({
|
|
|
115
115
|
const pageFrontmatter = await getStarlightPageFrontmatter(frontmatter);
|
|
116
116
|
const id = `${stripLeadingAndTrailingSlashes(slug)}.md`;
|
|
117
117
|
const localeData = slugToLocaleData(slug);
|
|
118
|
-
const sidebar =
|
|
119
|
-
|
|
120
|
-
url.pathname,
|
|
121
|
-
localeData.locale
|
|
122
|
-
);
|
|
118
|
+
const sidebar = props.sidebar
|
|
119
|
+
? getSidebarFromConfig(validateSidebarProp(props.sidebar), url.pathname, localeData.locale)
|
|
120
|
+
: getSidebar(url.pathname, localeData.locale);
|
|
123
121
|
const headings = props.headings ?? [];
|
|
124
122
|
const pageDocsEntry: StarlightPageDocsEntry = {
|
|
125
123
|
id,
|