@astrojs/starlight 0.41.11 → 0.42.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/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/components/MobileMenuToggle.astro +65 -0
- package/{components → dist/components}/PageFrame.astro +32 -8
- package/dist/components-internals/Icons.d.ts +415 -0
- package/dist/components-internals/Icons.js +140 -0
- package/dist/components-internals/SidebarPersistState.d.ts +1 -0
- package/dist/components-internals/SidebarPersistState.js +53 -0
- package/dist/components-internals/TableOfContents/starlight-toc.d.ts +18 -0
- package/dist/components-internals/TableOfContents/starlight-toc.js +88 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/{expressive-code.d.ts → dist/expressive-code.d.ts} +6 -13
- package/dist/expressive-code.js +31 -0
- package/dist/global.d.ts +62 -0
- package/dist/global.js +2 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +109 -0
- package/dist/integrations/aside-utils.d.ts +9 -0
- package/dist/integrations/aside-utils.js +35 -0
- package/dist/integrations/expressive-code/hast.d.ts +1 -0
- package/dist/integrations/expressive-code/hast.js +2 -0
- package/dist/integrations/expressive-code/index.d.ts +60 -0
- package/dist/integrations/expressive-code/index.js +48 -0
- package/dist/integrations/expressive-code/preprocessor.d.ts +17 -0
- package/dist/integrations/expressive-code/preprocessor.js +76 -0
- package/dist/integrations/expressive-code/themes/night-owl-dark.js +4 -0
- package/dist/integrations/expressive-code/themes/night-owl-light.js +4 -0
- package/dist/integrations/expressive-code/theming.d.ts +16 -0
- package/dist/integrations/expressive-code/theming.js +71 -0
- package/dist/integrations/expressive-code/translations.d.ts +8 -0
- package/dist/integrations/expressive-code/translations.js +26 -0
- package/dist/integrations/markdown-icon.d.ts +8 -0
- package/dist/integrations/markdown-icon.js +14 -0
- package/dist/integrations/markdown-plugins.d.ts +18 -0
- package/dist/integrations/markdown-plugins.js +36 -0
- package/dist/integrations/markdown-processor.d.ts +29 -0
- package/dist/integrations/markdown-processor.js +44 -0
- package/dist/integrations/pagefind.d.ts +7 -0
- package/dist/integrations/pagefind.js +34 -0
- package/dist/integrations/rehype-code-rtl-support.d.ts +21 -0
- package/dist/integrations/rehype-code-rtl-support.js +36 -0
- package/dist/integrations/rehype-heading-links.d.ts +10 -0
- package/dist/integrations/rehype-heading-links.js +57 -0
- package/dist/integrations/remark-asides.d.ts +32 -0
- package/dist/integrations/remark-asides.js +166 -0
- package/dist/integrations/remark-rehype.d.ts +17 -0
- package/dist/integrations/remark-rehype.js +51 -0
- package/dist/integrations/satteri.d.ts +13 -0
- package/dist/integrations/satteri.js +209 -0
- package/dist/integrations/shared/absolutePathToLang.d.ts +10 -0
- package/dist/integrations/shared/absolutePathToLang.js +13 -0
- package/dist/integrations/shared/localeToLang.d.ts +10 -0
- package/dist/integrations/shared/localeToLang.js +13 -0
- package/dist/integrations/shared/slugToLocale.d.ts +12 -0
- package/dist/integrations/shared/slugToLocale.js +15 -0
- package/dist/integrations/sitemap.d.ts +12 -0
- package/dist/integrations/sitemap.js +19 -0
- package/dist/integrations/vite-layer-order.d.ts +15 -0
- package/dist/integrations/vite-layer-order.js +56 -0
- package/dist/integrations/vite-lazy-barrel-optimization.d.ts +12 -0
- package/dist/integrations/vite-lazy-barrel-optimization.js +33 -0
- package/dist/integrations/vite-virtual-modules.d.ts +14 -0
- package/dist/integrations/vite-virtual-modules.js +108 -0
- package/dist/internal.d.ts +3 -0
- package/dist/internal.js +3 -0
- package/dist/loaders.d.ts +20 -0
- package/dist/loaders.js +49 -0
- package/dist/locals.d.ts +15 -0
- package/dist/locals.js +33 -0
- package/dist/package.js +4 -0
- package/{props.ts → dist/props.d.ts} +6 -4
- package/dist/props.js +1 -0
- package/dist/route-data.d.ts +7 -0
- package/dist/route-data.js +6 -0
- package/dist/schema.d.ts +426 -0
- package/dist/schema.js +103 -0
- package/dist/schemas/badge.d.ts +86 -0
- package/dist/schemas/badge.js +39 -0
- package/dist/schemas/components.d.ts +236 -0
- package/dist/schemas/components.js +36 -0
- package/dist/schemas/expressiveCode.d.ts +7 -0
- package/dist/schemas/expressiveCode.js +5 -0
- package/dist/schemas/favicon.d.ts +9 -0
- package/dist/schemas/favicon.js +32 -0
- package/dist/schemas/head.d.ts +33 -0
- package/dist/schemas/head.js +41 -0
- package/dist/schemas/hero.d.ts +319 -0
- package/dist/schemas/hero.js +73 -0
- package/dist/schemas/i18n.d.ts +125 -0
- package/dist/schemas/i18n.js +76 -0
- package/dist/schemas/icon.d.ts +284 -0
- package/dist/schemas/icon.js +7 -0
- package/dist/schemas/locale.d.ts +20 -0
- package/dist/schemas/locale.js +11 -0
- package/dist/schemas/logo.d.ts +32 -0
- package/dist/schemas/logo.js +14 -0
- package/dist/schemas/pagefind.d.ts +166 -0
- package/dist/schemas/pagefind.js +31 -0
- package/dist/schemas/prevNextLink.d.ts +10 -0
- package/dist/schemas/prevNextLink.js +14 -0
- package/dist/schemas/sidebar.d.ts +205 -0
- package/dist/schemas/sidebar.js +71 -0
- package/dist/schemas/site-title.d.ts +7 -0
- package/dist/schemas/site-title.js +17 -0
- package/dist/schemas/social.d.ts +292 -0
- package/dist/schemas/social.js +18 -0
- package/dist/schemas/tableOfContents.d.ts +24 -0
- package/dist/schemas/tableOfContents.js +16 -0
- package/dist/translations/ar.js +36 -0
- package/dist/translations/ca.js +46 -0
- package/dist/translations/cs.js +46 -0
- package/dist/translations/da.js +33 -0
- package/dist/translations/de.js +33 -0
- package/dist/translations/el.js +33 -0
- package/dist/translations/en.js +33 -0
- package/dist/translations/es.js +46 -0
- package/dist/translations/fa.js +33 -0
- package/dist/translations/fi.js +33 -0
- package/dist/translations/fr.js +36 -0
- package/dist/translations/gl.js +46 -0
- package/dist/translations/he.js +33 -0
- package/dist/translations/hi.js +36 -0
- package/dist/translations/hu.js +46 -0
- package/dist/translations/id.js +33 -0
- package/dist/translations/index.d.ts +48 -0
- package/dist/translations/index.js +75 -0
- package/dist/translations/it.js +36 -0
- package/dist/translations/ja.js +36 -0
- package/dist/translations/ko.js +36 -0
- package/dist/translations/lv.js +33 -0
- package/dist/translations/nb.js +33 -0
- package/dist/translations/nl.js +33 -0
- package/dist/translations/pl.js +36 -0
- package/dist/translations/pt.js +36 -0
- package/dist/translations/ro.js +33 -0
- package/dist/translations/ru.js +36 -0
- package/dist/translations/sk.js +33 -0
- package/dist/translations/sv.js +33 -0
- package/dist/translations/th.js +33 -0
- package/dist/translations/tr.js +33 -0
- package/dist/translations/uk.js +33 -0
- package/dist/translations/vi.js +33 -0
- package/dist/translations/zh-CN.js +36 -0
- package/dist/translations/zh-TW.js +36 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -0
- package/{user-components → dist/user-components}/FileTree.astro +1 -1
- package/{user-components → dist/user-components}/Steps.astro +1 -1
- package/{user-components → dist/user-components}/TabItem.astro +1 -1
- package/{user-components → dist/user-components}/Tabs.astro +1 -1
- package/dist/user-components/file-tree-icons.d.ts +178 -0
- package/dist/user-components/file-tree-icons.js +632 -0
- package/dist/user-components/file-tree-processor.d.ts +16 -0
- package/dist/user-components/file-tree-processor.js +132 -0
- package/dist/user-components/steps-processor.d.ts +10 -0
- package/dist/user-components/steps-processor.js +39 -0
- package/dist/user-components/tabs-processor.d.ts +23 -0
- package/dist/user-components/tabs-processor.js +70 -0
- package/dist/utils/base.d.ts +7 -0
- package/dist/utils/base.js +15 -0
- package/dist/utils/canonical.d.ts +10 -0
- package/dist/utils/canonical.js +14 -0
- package/dist/utils/collection-fs.d.ts +13 -0
- package/dist/utils/collection-fs.js +19 -0
- package/{utils/collection.ts → dist/utils/collection.d.ts} +9 -20
- package/dist/utils/collection.js +26 -0
- package/dist/utils/createPathFormatter.d.ts +9 -0
- package/dist/utils/createPathFormatter.js +35 -0
- package/dist/utils/createTranslationSystem.d.ts +23 -0
- package/dist/utils/createTranslationSystem.js +84 -0
- package/dist/utils/error-map.d.ts +23 -0
- package/dist/utils/error-map.js +125 -0
- package/dist/utils/format-path.d.ts +4 -0
- package/dist/utils/format-path.js +9 -0
- package/dist/utils/generateToC.d.ts +14 -0
- package/dist/utils/generateToC.js +25 -0
- package/dist/utils/git.d.ts +12 -0
- package/dist/utils/git.js +71 -0
- package/dist/utils/gitInlined.d.ts +6 -0
- package/dist/utils/gitInlined.js +11 -0
- package/dist/utils/head.d.ts +7 -0
- package/dist/utils/head.js +233 -0
- package/dist/utils/i18n.d.ts +50 -0
- package/dist/utils/i18n.js +141 -0
- package/dist/utils/localizedUrl.d.ts +8 -0
- package/dist/utils/localizedUrl.js +28 -0
- package/dist/utils/navigation.d.ts +19 -0
- package/dist/utils/navigation.js +353 -0
- package/dist/utils/path.d.ts +21 -0
- package/dist/utils/path.js +51 -0
- package/dist/utils/plugins.d.ts +721 -0
- package/dist/utils/plugins.js +174 -0
- package/dist/utils/routing/data.d.ts +20 -0
- package/dist/utils/routing/data.js +127 -0
- package/dist/utils/routing/index.d.ts +21 -0
- package/dist/utils/routing/index.js +106 -0
- package/dist/utils/routing/middleware.d.ts +11 -0
- package/dist/utils/routing/middleware.js +65 -0
- package/dist/utils/routing/types.d.ts +93 -0
- package/dist/utils/routing/types.js +1 -0
- package/dist/utils/slugs.d.ts +45 -0
- package/dist/utils/slugs.js +104 -0
- package/dist/utils/starlight-page.d.ts +36 -0
- package/dist/utils/starlight-page.js +120 -0
- package/dist/utils/translations-fs.d.ts +15 -0
- package/dist/utils/translations-fs.js +39 -0
- package/dist/utils/translations.d.ts +20 -0
- package/dist/utils/translations.js +29 -0
- package/dist/utils/types.d.ts +5 -0
- package/dist/utils/types.js +1 -0
- package/dist/utils/url.d.ts +7 -0
- package/{utils/url.ts → dist/utils/url.js} +5 -4
- package/dist/utils/user-config.d.ts +2055 -0
- package/dist/utils/user-config.js +136 -0
- package/dist/utils/validateLogoImports.d.ts +5 -0
- package/dist/utils/validateLogoImports.js +16 -0
- package/dist/utils/zodDeepMerge.d.ts +16 -0
- package/dist/utils/zodDeepMerge.js +53 -0
- package/package.json +60 -34
- package/CHANGELOG.md +0 -3051
- package/components/MobileMenuToggle.astro +0 -114
- package/components-internals/Icons.ts +0 -248
- package/components-internals/SidebarPersistState.ts +0 -71
- package/components-internals/TableOfContents/starlight-toc.ts +0 -127
- package/constants.ts +0 -4
- package/expressive-code.mjs +0 -23
- package/global.d.ts +0 -11
- package/i18n.d.ts +0 -18
- package/index.ts +0 -200
- package/integrations/aside-utils.ts +0 -41
- package/integrations/expressive-code/hast.d.ts +0 -5
- package/integrations/expressive-code/hast.mjs +0 -9
- package/integrations/expressive-code/index.ts +0 -125
- package/integrations/expressive-code/preprocessor.ts +0 -126
- package/integrations/expressive-code/themes/night-owl-dark.jsonc +0 -1796
- package/integrations/expressive-code/themes/night-owl-light.jsonc +0 -1695
- package/integrations/expressive-code/theming.ts +0 -105
- package/integrations/expressive-code/translations.ts +0 -36
- package/integrations/markdown-icon.ts +0 -13
- package/integrations/markdown-plugins.ts +0 -71
- package/integrations/markdown-processor.ts +0 -64
- package/integrations/pagefind.ts +0 -60
- package/integrations/rehype-code-rtl-support.ts +0 -37
- package/integrations/rehype-heading-links.ts +0 -79
- package/integrations/remark-asides.ts +0 -219
- package/integrations/remark-rehype.ts +0 -87
- package/integrations/satteri.ts +0 -265
- package/integrations/shared/absolutePathToLang.ts +0 -26
- package/integrations/shared/localeToLang.ts +0 -15
- package/integrations/shared/slugToLocale.ts +0 -18
- package/integrations/sitemap.ts +0 -23
- package/integrations/vite-layer-order.ts +0 -69
- package/integrations/vite-lazy-barrel-optimization.ts +0 -40
- package/integrations/vite-virtual-modules.ts +0 -175
- package/internal.ts +0 -6
- package/loaders.ts +0 -63
- package/locals.d.ts +0 -43
- package/locals.ts +0 -43
- package/route-data.ts +0 -11
- package/schema.ts +0 -167
- package/schemas/badge.ts +0 -40
- package/schemas/components.ts +0 -265
- package/schemas/expressiveCode.ts +0 -12
- package/schemas/favicon.ts +0 -40
- package/schemas/head.ts +0 -50
- package/schemas/hero.ts +0 -69
- package/schemas/i18n.ts +0 -244
- package/schemas/icon.ts +0 -7
- package/schemas/logo.ts +0 -28
- package/schemas/pagefind.ts +0 -128
- package/schemas/prevNextLink.ts +0 -18
- package/schemas/sidebar.ts +0 -163
- package/schemas/site-title.ts +0 -20
- package/schemas/social.ts +0 -23
- package/schemas/tableOfContents.ts +0 -21
- package/translations/README.md +0 -14
- package/translations/ar.json +0 -33
- package/translations/ca.json +0 -43
- package/translations/cs.json +0 -43
- package/translations/da.json +0 -30
- package/translations/de.json +0 -30
- package/translations/el.json +0 -30
- package/translations/en.json +0 -30
- package/translations/es.json +0 -43
- package/translations/fa.json +0 -30
- package/translations/fi.json +0 -30
- package/translations/fr.json +0 -33
- package/translations/gl.json +0 -43
- package/translations/he.json +0 -30
- package/translations/hi.json +0 -33
- package/translations/hu.json +0 -43
- package/translations/id.json +0 -30
- package/translations/index.ts +0 -76
- package/translations/it.json +0 -33
- package/translations/ja.json +0 -33
- package/translations/ko.json +0 -33
- package/translations/lv.json +0 -30
- package/translations/nb.json +0 -30
- package/translations/nl.json +0 -30
- package/translations/pl.json +0 -33
- package/translations/pt.json +0 -33
- package/translations/ro.json +0 -30
- package/translations/ru.json +0 -33
- package/translations/sk.json +0 -30
- package/translations/sv.json +0 -30
- package/translations/th.json +0 -30
- package/translations/tr.json +0 -30
- package/translations/uk.json +0 -30
- package/translations/vi.json +0 -30
- package/translations/zh-CN.json +0 -33
- package/translations/zh-TW.json +0 -33
- package/types.ts +0 -7
- package/user-components/file-tree-icons.ts +0 -782
- package/user-components/rehype-file-tree.ts +0 -251
- package/user-components/rehype-steps.ts +0 -85
- package/user-components/rehype-tabs.ts +0 -121
- package/utils/base.ts +0 -15
- package/utils/canonical.ts +0 -19
- package/utils/collection-fs.ts +0 -20
- package/utils/createPathFormatter.ts +0 -60
- package/utils/createTranslationSystem.ts +0 -137
- package/utils/error-map.ts +0 -222
- package/utils/format-path.ts +0 -7
- package/utils/generateToC.ts +0 -33
- package/utils/git.ts +0 -121
- package/utils/gitInlined.ts +0 -20
- package/utils/head.ts +0 -235
- package/utils/i18n.ts +0 -221
- package/utils/localizedUrl.ts +0 -51
- package/utils/navigation.ts +0 -574
- package/utils/path.ts +0 -58
- package/utils/plugins.ts +0 -498
- package/utils/routing/data.ts +0 -154
- package/utils/routing/index.ts +0 -139
- package/utils/routing/middleware.ts +0 -81
- package/utils/routing/types.ts +0 -101
- package/utils/slugs.ts +0 -119
- package/utils/starlight-page.ts +0 -205
- package/utils/translations-fs.ts +0 -54
- package/utils/translations.ts +0 -57
- package/utils/types.ts +0 -15
- package/utils/user-config.ts +0 -348
- package/utils/validateLogoImports.ts +0 -21
- package/utils/zodDeepMerge.ts +0 -144
- package/virtual-internal.d.ts +0 -149
- package/virtual.d.ts +0 -27
- /package/{components → dist/components}/AnchorHeading.astro +0 -0
- /package/{components → dist/components}/Banner.astro +0 -0
- /package/{components → dist/components}/ContentNotice.astro +0 -0
- /package/{components → dist/components}/ContentPanel.astro +0 -0
- /package/{components → dist/components}/DraftContentNotice.astro +0 -0
- /package/{components → dist/components}/EditLink.astro +0 -0
- /package/{components → dist/components}/FallbackContentNotice.astro +0 -0
- /package/{components → dist/components}/Footer.astro +0 -0
- /package/{components → dist/components}/Head.astro +0 -0
- /package/{components → dist/components}/Header.astro +0 -0
- /package/{components → dist/components}/Hero.astro +0 -0
- /package/{components → dist/components}/LanguageSelect.astro +0 -0
- /package/{components → dist/components}/LastUpdated.astro +0 -0
- /package/{components → dist/components}/MarkdownContent.astro +0 -0
- /package/{components → dist/components}/MobileMenuFooter.astro +0 -0
- /package/{components → dist/components}/MobileTableOfContents.astro +0 -0
- /package/{components → dist/components}/Page.astro +0 -0
- /package/{components → dist/components}/PageSidebar.astro +0 -0
- /package/{components → dist/components}/PageTitle.astro +0 -0
- /package/{components → dist/components}/Pagination.astro +0 -0
- /package/{components → dist/components}/Search.astro +0 -0
- /package/{components → dist/components}/Select.astro +0 -0
- /package/{components → dist/components}/Sidebar.astro +0 -0
- /package/{components → dist/components}/SidebarPersister.astro +0 -0
- /package/{components → dist/components}/SidebarRestorePoint.astro +0 -0
- /package/{components → dist/components}/SidebarSublist.astro +0 -0
- /package/{components → dist/components}/SiteTitle.astro +0 -0
- /package/{components → dist/components}/SkipLink.astro +0 -0
- /package/{components → dist/components}/SocialIcons.astro +0 -0
- /package/{components → dist/components}/StarlightPage.astro +0 -0
- /package/{components → dist/components}/TableOfContents.astro +0 -0
- /package/{components → dist/components}/ThemeProvider.astro +0 -0
- /package/{components → dist/components}/ThemeSelect.astro +0 -0
- /package/{components → dist/components}/TwoColumnContent.astro +0 -0
- /package/{components-internals → dist/components-internals}/TableOfContents/TableOfContentsList.astro +0 -0
- /package/{components.ts → dist/components.ts} +0 -0
- /package/{routes → dist/routes}/common.astro +0 -0
- /package/{routes → dist/routes}/ssr/404.astro +0 -0
- /package/{routes → dist/routes}/ssr/index.astro +0 -0
- /package/{routes → dist/routes}/static/404.astro +0 -0
- /package/{routes → dist/routes}/static/index.astro +0 -0
- /package/{style → dist/style}/anchor-links.css +0 -0
- /package/{style → dist/style}/asides.css +0 -0
- /package/{style → dist/style}/layers.css +0 -0
- /package/{style → dist/style}/markdown.css +0 -0
- /package/{style → dist/style}/print.css +0 -0
- /package/{style → dist/style}/props.css +0 -0
- /package/{style → dist/style}/reset.css +0 -0
- /package/{style → dist/style}/util.css +0 -0
- /package/{user-components → dist/user-components}/Aside.astro +0 -0
- /package/{user-components → dist/user-components}/Badge.astro +0 -0
- /package/{user-components → dist/user-components}/Card.astro +0 -0
- /package/{user-components → dist/user-components}/CardGrid.astro +0 -0
- /package/{user-components → dist/user-components}/Icon.astro +0 -0
- /package/{user-components → dist/user-components}/LinkButton.astro +0 -0
- /package/{user-components → dist/user-components}/LinkCard.astro +0 -0
package/utils/navigation.ts
DELETED
|
@@ -1,574 +0,0 @@
|
|
|
1
|
-
import { AstroError } from 'astro/errors';
|
|
2
|
-
import project from 'virtual:starlight/project-context';
|
|
3
|
-
import config from 'virtual:starlight/user-config';
|
|
4
|
-
import type { Badge, I18nBadge, I18nBadgeConfig } from '../schemas/badge';
|
|
5
|
-
import type { PrevNextLinkConfig } from '../schemas/prevNextLink';
|
|
6
|
-
import type {
|
|
7
|
-
AutoSidebarEntries,
|
|
8
|
-
InternalSidebarLinkItem,
|
|
9
|
-
LinkHTMLAttributes,
|
|
10
|
-
SidebarItem,
|
|
11
|
-
SidebarLinkItem,
|
|
12
|
-
} from '../schemas/sidebar';
|
|
13
|
-
import { getCollectionPathFromRoot } from './collection';
|
|
14
|
-
import { createPathFormatter } from './createPathFormatter';
|
|
15
|
-
import { formatPath } from './format-path';
|
|
16
|
-
import { BuiltInDefaultLocale, pickLang } from './i18n';
|
|
17
|
-
import {
|
|
18
|
-
ensureLeadingSlash,
|
|
19
|
-
ensureTrailingSlash,
|
|
20
|
-
stripExtension,
|
|
21
|
-
stripLeadingAndTrailingSlashes,
|
|
22
|
-
} from './path';
|
|
23
|
-
import { getLocaleRoutes, getRouteById } from './routing';
|
|
24
|
-
import type {
|
|
25
|
-
SidebarGroup,
|
|
26
|
-
SidebarLink,
|
|
27
|
-
SidebarManualLink,
|
|
28
|
-
PaginationLinks,
|
|
29
|
-
Route,
|
|
30
|
-
SidebarEntry,
|
|
31
|
-
SidebarAutoLink,
|
|
32
|
-
SidebarAutoGroup,
|
|
33
|
-
SidebarAutogenerateRouteData,
|
|
34
|
-
} from './routing/types';
|
|
35
|
-
import { localeToLang, localizedFilePath, slugToPathname } from './slugs';
|
|
36
|
-
import { hasProtocol } from './url';
|
|
37
|
-
import type { StarlightConfig } from './user-config';
|
|
38
|
-
|
|
39
|
-
const DirKey = Symbol('DirKey');
|
|
40
|
-
const SlugKey = Symbol('SlugKey');
|
|
41
|
-
|
|
42
|
-
const rootAutogenerate: SidebarAutogenerateRouteData = { directory: '' };
|
|
43
|
-
|
|
44
|
-
const neverPathFormatter = createPathFormatter({ trailingSlash: 'never' });
|
|
45
|
-
const sidebarCollator = new Intl.Collator(localeToLang(undefined));
|
|
46
|
-
|
|
47
|
-
const docsCollectionPathFromRoot = getCollectionPathFromRoot('docs', project);
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* A representation of the route structure. For each object entry:
|
|
51
|
-
* if it’s a folder, the key is the directory name, and value is the directory
|
|
52
|
-
* content; if it’s a route entry, the key is the last segment of the route, and value
|
|
53
|
-
* is the full entry.
|
|
54
|
-
*/
|
|
55
|
-
interface Dir {
|
|
56
|
-
[DirKey]: undefined;
|
|
57
|
-
[SlugKey]: string;
|
|
58
|
-
[item: string]: Dir | Route;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** Create a new directory object. */
|
|
62
|
-
function makeDir(slug: string): Dir {
|
|
63
|
-
const dir = {} as Dir;
|
|
64
|
-
// Add DirKey and SlugKey as non-enumerable properties so that `Object.entries(dir)` ignores them.
|
|
65
|
-
Object.defineProperty(dir, DirKey, { enumerable: false });
|
|
66
|
-
Object.defineProperty(dir, SlugKey, { value: slug, enumerable: false });
|
|
67
|
-
return dir;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Test if the passed object is a directory record. */
|
|
71
|
-
function isDir(data: Record<string, unknown>): data is Dir {
|
|
72
|
-
return DirKey in data;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Convert an item in a user’s sidebar config to a sidebar entry. */
|
|
76
|
-
function configItemToEntry(
|
|
77
|
-
item: SidebarItem,
|
|
78
|
-
locale: string | undefined,
|
|
79
|
-
routes: Route[]
|
|
80
|
-
): SidebarEntry | SidebarEntry[] {
|
|
81
|
-
if ('link' in item) {
|
|
82
|
-
return linkFromSidebarLinkItem(item, locale);
|
|
83
|
-
} else if ('autogenerate' in item) {
|
|
84
|
-
return entriesFromAutogenerateConfig(item, locale, routes);
|
|
85
|
-
} else if ('slug' in item) {
|
|
86
|
-
return linkFromInternalSidebarLinkItem(item, locale);
|
|
87
|
-
} else {
|
|
88
|
-
const label = pickLang(item.translations, localeToLang(locale)) || item.label;
|
|
89
|
-
return {
|
|
90
|
-
type: 'group',
|
|
91
|
-
label,
|
|
92
|
-
entries: item.items.flatMap((i) => configItemToEntry(i, locale, routes)),
|
|
93
|
-
collapsed: item.collapsed,
|
|
94
|
-
badge: getSidebarBadge(item.badge, locale, label),
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Autogenerate links and groups from a user’s sidebar config. */
|
|
100
|
-
function entriesFromAutogenerateConfig(
|
|
101
|
-
item: AutoSidebarEntries,
|
|
102
|
-
locale: string | undefined,
|
|
103
|
-
routes: Route[]
|
|
104
|
-
): (SidebarAutoLink | SidebarGroup)[] {
|
|
105
|
-
const { attrs, collapsed, directory } = item.autogenerate;
|
|
106
|
-
const localeDir = locale ? locale + '/' + directory : directory;
|
|
107
|
-
const autogenerate = { directory };
|
|
108
|
-
const dirDocs = routes.filter((doc) => {
|
|
109
|
-
const filePathFromContentDir = getRoutePathRelativeToCollectionRoot(doc, locale);
|
|
110
|
-
return (
|
|
111
|
-
// Match against `foo.md` or `foo/index.md`.
|
|
112
|
-
stripExtension(filePathFromContentDir) === localeDir ||
|
|
113
|
-
// Match against `foo/anything/else.md`.
|
|
114
|
-
filePathFromContentDir.startsWith(localeDir + '/')
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
const tree = treeify(dirDocs, locale, localeDir);
|
|
118
|
-
return sidebarFromDir(tree, { collapsed: collapsed ?? false, attrs }, autogenerate);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Create a link entry from a manual link item in user config. */
|
|
122
|
-
function linkFromSidebarLinkItem(item: SidebarLinkItem, locale: string | undefined) {
|
|
123
|
-
let href = item.link;
|
|
124
|
-
if (!hasProtocol(href)) {
|
|
125
|
-
href = ensureLeadingSlash(href);
|
|
126
|
-
// Inject current locale into link.
|
|
127
|
-
if (locale) href = '/' + locale + href;
|
|
128
|
-
}
|
|
129
|
-
const label = pickLang(item.translations, localeToLang(locale)) || item.label;
|
|
130
|
-
return makeSidebarLink({
|
|
131
|
-
href,
|
|
132
|
-
label,
|
|
133
|
-
badge: getSidebarBadge(item.badge, locale, label),
|
|
134
|
-
attrs: item.attrs,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/** Create a link entry from an automatic internal link item in user config. */
|
|
139
|
-
function linkFromInternalSidebarLinkItem(
|
|
140
|
-
item: InternalSidebarLinkItem,
|
|
141
|
-
locale: string | undefined
|
|
142
|
-
) {
|
|
143
|
-
// Astro passes root `index.[md|mdx]` entries with a slug of `index`
|
|
144
|
-
const slug = item.slug === 'index' ? '' : item.slug;
|
|
145
|
-
const localizedSlug = locale ? (slug ? locale + '/' + slug : locale) : slug;
|
|
146
|
-
const route = getRouteById(localizedSlug);
|
|
147
|
-
if (!route) {
|
|
148
|
-
const hasExternalSlashes = item.slug.at(0) === '/' || item.slug.at(-1) === '/';
|
|
149
|
-
if (hasExternalSlashes) {
|
|
150
|
-
throw new AstroError(
|
|
151
|
-
`The slug \`"${item.slug}"\` specified in the Starlight sidebar config must not start or end with a slash.`,
|
|
152
|
-
`Please try updating \`"${item.slug}"\` to \`"${stripLeadingAndTrailingSlashes(item.slug)}"\`.`
|
|
153
|
-
);
|
|
154
|
-
} else {
|
|
155
|
-
throw new AstroError(
|
|
156
|
-
`The slug \`"${item.slug}"\` specified in the Starlight sidebar config does not exist.`,
|
|
157
|
-
'Update the Starlight config to reference a valid entry slug in the docs content collection.\n' +
|
|
158
|
-
'Learn more about Astro content collection slugs at https://docs.astro.build/en/reference/modules/astro-content/#getentry'
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
const frontmatter = route.entry.data;
|
|
163
|
-
const label =
|
|
164
|
-
pickLang(item.translations, localeToLang(locale)) ||
|
|
165
|
-
item.label ||
|
|
166
|
-
frontmatter.sidebar?.label ||
|
|
167
|
-
frontmatter.title;
|
|
168
|
-
const badge = item.badge ?? frontmatter.sidebar?.badge;
|
|
169
|
-
const attrs = { ...frontmatter.sidebar?.attrs, ...item.attrs };
|
|
170
|
-
return makeSidebarLink({
|
|
171
|
-
href: slugToPathname(route.id),
|
|
172
|
-
label,
|
|
173
|
-
badge: getSidebarBadge(badge, locale, label),
|
|
174
|
-
attrs,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
interface MakeLinkOptions {
|
|
179
|
-
autogenerate?: SidebarAutogenerateRouteData | undefined;
|
|
180
|
-
href: string;
|
|
181
|
-
label: string;
|
|
182
|
-
badge?: Badge | undefined;
|
|
183
|
-
attrs?: LinkHTMLAttributes | undefined;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/** Process sidebar link options to create a link entry. */
|
|
187
|
-
function makeSidebarLink(opts: MakeLinkOptions & { autogenerate?: undefined }): SidebarManualLink;
|
|
188
|
-
function makeSidebarLink(
|
|
189
|
-
opts: MakeLinkOptions & { autogenerate: SidebarAutogenerateRouteData }
|
|
190
|
-
): SidebarAutoLink;
|
|
191
|
-
function makeSidebarLink({ attrs, badge, href, label, autogenerate }: MakeLinkOptions) {
|
|
192
|
-
if (!hasProtocol(href)) {
|
|
193
|
-
href = formatPath(href);
|
|
194
|
-
}
|
|
195
|
-
return makeLink({ label, href, badge, attrs, autogenerate });
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/** Create a link entry */
|
|
199
|
-
function makeLink({ attrs = {}, badge, autogenerate, ...opts }: MakeLinkOptions): SidebarLink {
|
|
200
|
-
return {
|
|
201
|
-
type: 'link',
|
|
202
|
-
...opts,
|
|
203
|
-
badge,
|
|
204
|
-
isCurrent: false,
|
|
205
|
-
attrs,
|
|
206
|
-
...(autogenerate ? { autogenerate } : {}),
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** Get the segments leading to a page. */
|
|
211
|
-
function getBreadcrumbs(path: string, baseDir: string): string[] {
|
|
212
|
-
// Strip extension from path.
|
|
213
|
-
const pathWithoutExt = stripExtension(path);
|
|
214
|
-
// Index paths will match `baseDir` and don’t include breadcrumbs.
|
|
215
|
-
if (pathWithoutExt === baseDir) return [];
|
|
216
|
-
// Ensure base directory ends in a trailing slash.
|
|
217
|
-
baseDir = ensureTrailingSlash(baseDir);
|
|
218
|
-
// Strip base directory from path if present.
|
|
219
|
-
const relativePath = pathWithoutExt.startsWith(baseDir)
|
|
220
|
-
? pathWithoutExt.replace(baseDir, '')
|
|
221
|
-
: pathWithoutExt;
|
|
222
|
-
|
|
223
|
-
return relativePath.split('/');
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/** Return the path of a route relative to the root of the collection. */
|
|
227
|
-
function getRoutePathRelativeToCollectionRoot(route: Route, locale: string | undefined) {
|
|
228
|
-
// Use a localized filePath relative to the collection
|
|
229
|
-
return localizedFilePath(
|
|
230
|
-
route.entry.filePath.replace(`${docsCollectionPathFromRoot}/`, ''),
|
|
231
|
-
locale
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** Turn a flat array of routes into a tree structure. */
|
|
236
|
-
function treeify(routes: Route[], locale: string | undefined, baseDir: string): Dir {
|
|
237
|
-
const treeRoot: Dir = makeDir(baseDir);
|
|
238
|
-
routes
|
|
239
|
-
// Remove any entries that should be hidden
|
|
240
|
-
.filter((doc) => !doc.entry.data.sidebar.hidden)
|
|
241
|
-
// Compute the path of each entry from the root of the collection ahead of time.
|
|
242
|
-
.map((doc) => [getRoutePathRelativeToCollectionRoot(doc, locale), doc] as const)
|
|
243
|
-
// Sort by depth, to build the tree depth first.
|
|
244
|
-
.sort(([a], [b]) => b.split('/').length - a.split('/').length)
|
|
245
|
-
// Build the tree
|
|
246
|
-
.forEach(([filePathFromContentDir, doc]) => {
|
|
247
|
-
const parts = getBreadcrumbs(filePathFromContentDir, baseDir);
|
|
248
|
-
let currentNode = treeRoot;
|
|
249
|
-
|
|
250
|
-
parts.forEach((part, index) => {
|
|
251
|
-
const isLeaf = index === parts.length - 1;
|
|
252
|
-
|
|
253
|
-
// Handle directory index pages by renaming them to `index`
|
|
254
|
-
if (isLeaf && Object.hasOwn(currentNode, part)) {
|
|
255
|
-
currentNode = currentNode[part] as Dir;
|
|
256
|
-
part = 'index';
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Recurse down the tree if this isn’t the leaf node.
|
|
260
|
-
if (!isLeaf) {
|
|
261
|
-
const path = currentNode[SlugKey];
|
|
262
|
-
currentNode[part] ||= makeDir(stripLeadingAndTrailingSlashes(path + '/' + part));
|
|
263
|
-
currentNode = currentNode[part] as Dir;
|
|
264
|
-
} else {
|
|
265
|
-
currentNode[part] = doc;
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
return treeRoot;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** Create a link entry for a given content collection entry. */
|
|
274
|
-
function linkFromRoute(
|
|
275
|
-
route: Route,
|
|
276
|
-
attrs: LinkHTMLAttributes | undefined,
|
|
277
|
-
autogenerate: SidebarAutogenerateRouteData
|
|
278
|
-
): SidebarAutoLink {
|
|
279
|
-
return makeSidebarLink({
|
|
280
|
-
href: slugToPathname(route.id),
|
|
281
|
-
label: route.entry.data.sidebar.label || route.entry.data.title,
|
|
282
|
-
badge: route.entry.data.sidebar.badge,
|
|
283
|
-
attrs: { ...attrs, ...route.entry.data.sidebar.attrs },
|
|
284
|
-
autogenerate,
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Get the sort weight for a given route or directory. Lower numbers rank higher.
|
|
290
|
-
* Directories have the weight of the lowest weighted route they contain.
|
|
291
|
-
*/
|
|
292
|
-
function getOrder(routeOrDir: Route | Dir): number {
|
|
293
|
-
const cachedOrder = orderByEntry.get(routeOrDir);
|
|
294
|
-
if (cachedOrder !== undefined) return cachedOrder;
|
|
295
|
-
const order = isDir(routeOrDir)
|
|
296
|
-
? Math.min(...Object.values(routeOrDir).flatMap(getOrder))
|
|
297
|
-
: // If no order value is found, set it to the largest number possible.
|
|
298
|
-
(routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE);
|
|
299
|
-
orderByEntry.set(routeOrDir, order);
|
|
300
|
-
return order;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const orderByEntry = new WeakMap<Dir | Route, number>();
|
|
304
|
-
|
|
305
|
-
/** Sort a directory’s entries by user-specified order or alphabetically if no order specified. */
|
|
306
|
-
function sortDirEntries(dir: [string, Dir | Route][]): [string, Dir | Route][] {
|
|
307
|
-
return dir.sort(([_keyA, a], [_keyB, b]) => {
|
|
308
|
-
const [aOrder, bOrder] = [getOrder(a), getOrder(b)];
|
|
309
|
-
// Pages are sorted by order in ascending order.
|
|
310
|
-
if (aOrder !== bOrder) return aOrder < bOrder ? -1 : 1;
|
|
311
|
-
// If two pages have the same order value they will be sorted by their slug.
|
|
312
|
-
return sidebarCollator.compare(isDir(a) ? a[SlugKey] : a.id, isDir(b) ? b[SlugKey] : b.id);
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
interface SidebarDirOptions {
|
|
317
|
-
collapsed: boolean;
|
|
318
|
-
attrs: LinkHTMLAttributes | undefined;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
interface SidebarDirContext extends SidebarDirOptions {
|
|
322
|
-
fullPath: string;
|
|
323
|
-
dirName: string;
|
|
324
|
-
autogenerate: SidebarAutogenerateRouteData;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/** Create a group entry for a given content collection directory. */
|
|
328
|
-
function groupFromDir(dir: Dir, context: SidebarDirContext): SidebarAutoGroup {
|
|
329
|
-
const { fullPath, dirName, collapsed, autogenerate } = context;
|
|
330
|
-
const entries = sortDirEntries(Object.entries(dir)).map(([key, dirOrRoute]) =>
|
|
331
|
-
dirToItem(dirOrRoute, { ...context, fullPath: `${fullPath}/${key}`, dirName: key })
|
|
332
|
-
);
|
|
333
|
-
return {
|
|
334
|
-
type: 'group',
|
|
335
|
-
label: dirName,
|
|
336
|
-
entries,
|
|
337
|
-
collapsed,
|
|
338
|
-
badge: undefined,
|
|
339
|
-
autogenerate,
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/** Create a sidebar entry for a directory or content entry. */
|
|
344
|
-
function dirToItem(
|
|
345
|
-
dirOrRoute: Dir[string],
|
|
346
|
-
context: SidebarDirContext
|
|
347
|
-
): SidebarAutoGroup | SidebarAutoLink {
|
|
348
|
-
const { attrs, autogenerate } = context;
|
|
349
|
-
return isDir(dirOrRoute)
|
|
350
|
-
? groupFromDir(dirOrRoute, context)
|
|
351
|
-
: linkFromRoute(dirOrRoute, attrs, autogenerate);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** Create a sidebar entry for a given content directory. */
|
|
355
|
-
function sidebarFromDir(
|
|
356
|
-
tree: Dir,
|
|
357
|
-
options: SidebarDirOptions,
|
|
358
|
-
autogenerate: SidebarAutogenerateRouteData = rootAutogenerate
|
|
359
|
-
) {
|
|
360
|
-
return sortDirEntries(Object.entries(tree)).map(([key, dirOrRoute]) =>
|
|
361
|
-
dirToItem(dirOrRoute, { ...options, fullPath: key, dirName: key, autogenerate })
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Intermediate sidebar represents sidebar entries generated from the user config for a specific
|
|
367
|
-
* locale. These representations are cached per locale to avoid regenerating them for each page.
|
|
368
|
-
* When generating the final sidebar for a page, the current page entry in the sidebar is marked
|
|
369
|
-
* with `isCurrent` and cached. Subsequent runs then reset the previous current entry before marking
|
|
370
|
-
* the new current page.
|
|
371
|
-
*
|
|
372
|
-
* Sidebars, like all route data, are deep cloned before the data is passed to users for mutation,
|
|
373
|
-
* so optimising with a single mutable object per locale is safe.
|
|
374
|
-
*
|
|
375
|
-
* @see getSidebarFromIntermediateSidebar
|
|
376
|
-
*/
|
|
377
|
-
const intermediateSidebars = new Map<string | undefined, SidebarEntry[]>();
|
|
378
|
-
const lastCurrentEntryByLocale = new Map<string | undefined, SidebarLink>();
|
|
379
|
-
|
|
380
|
-
/** Get the sidebar for the current page using the global config. */
|
|
381
|
-
export function getSidebar(pathname: string, locale: string | undefined): SidebarEntry[] {
|
|
382
|
-
let intermediateSidebar = intermediateSidebars.get(locale);
|
|
383
|
-
if (!intermediateSidebar) {
|
|
384
|
-
intermediateSidebar = getIntermediateSidebarFromConfig(config.sidebar, locale);
|
|
385
|
-
intermediateSidebars.set(locale, intermediateSidebar);
|
|
386
|
-
}
|
|
387
|
-
setIntermediateSidebarCurrentEntry(intermediateSidebar, pathname, locale);
|
|
388
|
-
return intermediateSidebar;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/** Get the sidebar for the current page using the specified sidebar config. */
|
|
392
|
-
export function getSidebarFromConfig(
|
|
393
|
-
sidebarConfig: StarlightConfig['sidebar'],
|
|
394
|
-
pathname: string,
|
|
395
|
-
locale: string | undefined
|
|
396
|
-
): SidebarEntry[] {
|
|
397
|
-
const sidebar = getIntermediateSidebarFromConfig(sidebarConfig, locale);
|
|
398
|
-
const currentEntry = getSidebarCurrentEntry(sidebar, pathname);
|
|
399
|
-
if (currentEntry) currentEntry.isCurrent = true;
|
|
400
|
-
return sidebar;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/** Get the intermediate sidebar for a locale using the specified sidebar config. */
|
|
404
|
-
function getIntermediateSidebarFromConfig(
|
|
405
|
-
sidebarConfig: StarlightConfig['sidebar'],
|
|
406
|
-
locale: string | undefined
|
|
407
|
-
): SidebarEntry[] {
|
|
408
|
-
const routes = getLocaleRoutes(locale);
|
|
409
|
-
if (sidebarConfig) {
|
|
410
|
-
return sidebarConfig.flatMap((group) => configItemToEntry(group, locale, routes));
|
|
411
|
-
} else {
|
|
412
|
-
const tree = treeify(routes, locale, locale || '');
|
|
413
|
-
return sidebarFromDir(tree, { collapsed: false, attrs: undefined });
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/** Marks the current page in an intermediate sidebar. */
|
|
418
|
-
function setIntermediateSidebarCurrentEntry(
|
|
419
|
-
intermediateSidebar: SidebarEntry[],
|
|
420
|
-
pathname: string,
|
|
421
|
-
locale: string | undefined
|
|
422
|
-
): void {
|
|
423
|
-
// Reset the `isCurrent` flag in this sidebar if it was previously set.
|
|
424
|
-
const lastCurrentEntry = lastCurrentEntryByLocale.get(locale);
|
|
425
|
-
if (lastCurrentEntry) {
|
|
426
|
-
lastCurrentEntry.isCurrent = false;
|
|
427
|
-
}
|
|
428
|
-
// Find the new current entry.
|
|
429
|
-
const entry = getSidebarCurrentEntry(intermediateSidebar, pathname);
|
|
430
|
-
// Mark it as current and store it to be reset later.
|
|
431
|
-
if (entry) {
|
|
432
|
-
entry.isCurrent = true;
|
|
433
|
-
lastCurrentEntryByLocale.set(locale, entry);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/** Finds the current page in a sidebar. */
|
|
438
|
-
function getSidebarCurrentEntry(sidebar: SidebarEntry[], pathname: string): SidebarLink | null {
|
|
439
|
-
let entriesByPath = sidebarEntriesByPath.get(sidebar);
|
|
440
|
-
if (!entriesByPath) {
|
|
441
|
-
entriesByPath = new Map();
|
|
442
|
-
for (const entry of flattenSidebar(sidebar)) {
|
|
443
|
-
const path = neverPathFormatter(encodeURI(entry.href));
|
|
444
|
-
if (!entriesByPath.has(path)) entriesByPath.set(path, entry);
|
|
445
|
-
}
|
|
446
|
-
sidebarEntriesByPath.set(sidebar, entriesByPath);
|
|
447
|
-
}
|
|
448
|
-
return entriesByPath.get(neverPathFormatter(pathname)) ?? null;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const sidebarEntriesByPath = new WeakMap<SidebarEntry[], Map<string, SidebarLink>>();
|
|
452
|
-
|
|
453
|
-
/** Generates a deterministic string based on the content of the passed sidebar. */
|
|
454
|
-
export function getSidebarHash(sidebar: SidebarEntry[]): string {
|
|
455
|
-
let hash = 0;
|
|
456
|
-
const sidebarIdentity = recursivelyBuildSidebarIdentity(sidebar);
|
|
457
|
-
for (let i = 0; i < sidebarIdentity.length; i++) {
|
|
458
|
-
const char = sidebarIdentity.charCodeAt(i);
|
|
459
|
-
hash = (hash << 5) - hash + char;
|
|
460
|
-
}
|
|
461
|
-
return (hash >>> 0).toString(36).padStart(7, '0');
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/** Recurses through a sidebar tree to generate a string concatenating labels and link hrefs. */
|
|
465
|
-
function recursivelyBuildSidebarIdentity(sidebar: SidebarEntry[]): string {
|
|
466
|
-
return sidebar
|
|
467
|
-
.flatMap((entry) =>
|
|
468
|
-
entry.type === 'group'
|
|
469
|
-
? entry.label + recursivelyBuildSidebarIdentity(entry.entries)
|
|
470
|
-
: entry.label + entry.href
|
|
471
|
-
)
|
|
472
|
-
.join('');
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/** Turn the nested tree structure of a sidebar into a flat list of all the links. */
|
|
476
|
-
export function flattenSidebar(sidebar: SidebarEntry[]): SidebarLink[] {
|
|
477
|
-
const cachedSidebar = flattenedSidebars.get(sidebar);
|
|
478
|
-
if (cachedSidebar) return cachedSidebar;
|
|
479
|
-
const flattenedSidebar = sidebar.flatMap((entry) =>
|
|
480
|
-
entry.type === 'group' ? flattenSidebar(entry.entries) : entry
|
|
481
|
-
);
|
|
482
|
-
flattenedSidebars.set(sidebar, flattenedSidebar);
|
|
483
|
-
return flattenedSidebar;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const flattenedSidebars = new WeakMap<SidebarEntry[], SidebarLink[]>();
|
|
487
|
-
|
|
488
|
-
/** Get previous/next pages in the sidebar or the ones from the frontmatter if any. */
|
|
489
|
-
export function getPrevNextLinks(
|
|
490
|
-
sidebar: SidebarEntry[],
|
|
491
|
-
paginationEnabled: boolean,
|
|
492
|
-
config: {
|
|
493
|
-
prev?: PrevNextLinkConfig;
|
|
494
|
-
next?: PrevNextLinkConfig;
|
|
495
|
-
}
|
|
496
|
-
): PaginationLinks {
|
|
497
|
-
const entries = flattenSidebar(sidebar);
|
|
498
|
-
const currentIndex = entries.findIndex((entry) => entry.isCurrent);
|
|
499
|
-
const prev = applyPrevNextLinkConfig(entries[currentIndex - 1], paginationEnabled, config.prev);
|
|
500
|
-
const next = applyPrevNextLinkConfig(
|
|
501
|
-
currentIndex > -1 ? entries[currentIndex + 1] : undefined,
|
|
502
|
-
paginationEnabled,
|
|
503
|
-
config.next
|
|
504
|
-
);
|
|
505
|
-
return { prev, next };
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/** Apply a prev/next link config to a navigation link. */
|
|
509
|
-
function applyPrevNextLinkConfig(
|
|
510
|
-
link: SidebarLink | undefined,
|
|
511
|
-
paginationEnabled: boolean,
|
|
512
|
-
config: PrevNextLinkConfig | undefined
|
|
513
|
-
): SidebarLink | undefined {
|
|
514
|
-
// Explicitly remove the link.
|
|
515
|
-
if (config === false) return undefined;
|
|
516
|
-
// Use the generated link if any.
|
|
517
|
-
else if (config === true) return link;
|
|
518
|
-
// If a link exists, update its label if needed.
|
|
519
|
-
else if (typeof config === 'string' && link) {
|
|
520
|
-
return { ...link, label: config };
|
|
521
|
-
} else if (typeof config === 'object') {
|
|
522
|
-
if (link) {
|
|
523
|
-
// If a link exists, update both its label and href if needed.
|
|
524
|
-
return {
|
|
525
|
-
...link,
|
|
526
|
-
label: config.label ?? link.label,
|
|
527
|
-
href: config.link ?? link.href,
|
|
528
|
-
// Explicitly remove sidebar link attributes for prev/next links.
|
|
529
|
-
attrs: {},
|
|
530
|
-
};
|
|
531
|
-
} else if (config.link && config.label) {
|
|
532
|
-
// If there is no link and the frontmatter contains both a URL and a label,
|
|
533
|
-
// create a new link.
|
|
534
|
-
return makeLink({ href: config.link, label: config.label });
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
// Otherwise, if the global config is enabled, return the generated link if any.
|
|
538
|
-
return paginationEnabled ? link : undefined;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/** Get a sidebar badge for a given item. */
|
|
542
|
-
function getSidebarBadge(
|
|
543
|
-
config: I18nBadgeConfig,
|
|
544
|
-
locale: string | undefined,
|
|
545
|
-
itemLabel: string
|
|
546
|
-
): Badge | undefined {
|
|
547
|
-
if (!config) return;
|
|
548
|
-
if (typeof config === 'string') {
|
|
549
|
-
return { variant: 'default', text: config };
|
|
550
|
-
}
|
|
551
|
-
return { ...config, text: getSidebarBadgeText(config.text, locale, itemLabel) };
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
/** Get the badge text for a sidebar item. */
|
|
555
|
-
function getSidebarBadgeText(
|
|
556
|
-
text: I18nBadge['text'],
|
|
557
|
-
locale: string | undefined,
|
|
558
|
-
itemLabel: string
|
|
559
|
-
): string {
|
|
560
|
-
if (typeof text === 'string') return text;
|
|
561
|
-
const defaultLang =
|
|
562
|
-
config.defaultLocale?.lang || config.defaultLocale?.locale || BuiltInDefaultLocale.lang;
|
|
563
|
-
const defaultText = text[defaultLang];
|
|
564
|
-
|
|
565
|
-
if (!defaultText) {
|
|
566
|
-
throw new AstroError(
|
|
567
|
-
`The badge text for "${itemLabel}" must have a key for the default language "${defaultLang}".`,
|
|
568
|
-
'Update the Starlight config to include a badge text for the default language.\n' +
|
|
569
|
-
'Learn more about sidebar badges internationalization at https://starlight.astro.build/guides/sidebar/#internationalization-with-badges'
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
return pickLang(text, localeToLang(locale)) || defaultText;
|
|
574
|
-
}
|
package/utils/path.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/** Ensure the passed path starts with a leading slash. */
|
|
2
|
-
export function ensureLeadingSlash(href: string): string {
|
|
3
|
-
if (href[0] !== '/') href = '/' + href;
|
|
4
|
-
return href;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
/** Ensure the passed path ends with a trailing slash. */
|
|
8
|
-
export function ensureTrailingSlash(href: string): string {
|
|
9
|
-
if (href[href.length - 1] !== '/') href += '/';
|
|
10
|
-
return href;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** Ensure the passed path starts and ends with slashes. */
|
|
14
|
-
export function ensureLeadingAndTrailingSlashes(href: string): string {
|
|
15
|
-
href = ensureLeadingSlash(href);
|
|
16
|
-
href = ensureTrailingSlash(href);
|
|
17
|
-
return href;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Ensure the passed path does not start with a leading slash. */
|
|
21
|
-
export function stripLeadingSlash(href: string) {
|
|
22
|
-
if (href[0] === '/') href = href.slice(1);
|
|
23
|
-
return href;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Ensure the passed path does not end with a trailing slash. */
|
|
27
|
-
export function stripTrailingSlash(href: string) {
|
|
28
|
-
if (href[href.length - 1] === '/') href = href.slice(0, -1);
|
|
29
|
-
return href;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Ensure the passed path does not start and end with slashes. */
|
|
33
|
-
export function stripLeadingAndTrailingSlashes(href: string): string {
|
|
34
|
-
href = stripLeadingSlash(href);
|
|
35
|
-
href = stripTrailingSlash(href);
|
|
36
|
-
return href;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Remove the extension from a path. */
|
|
40
|
-
export function stripHtmlExtension(path: string) {
|
|
41
|
-
const pathWithoutTrailingSlash = stripTrailingSlash(path);
|
|
42
|
-
return pathWithoutTrailingSlash.endsWith('.html') ? pathWithoutTrailingSlash.slice(0, -5) : path;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Add '.html' extension to a path. */
|
|
46
|
-
export function ensureHtmlExtension(path: string) {
|
|
47
|
-
path = stripLeadingAndTrailingSlashes(path);
|
|
48
|
-
if (!path.endsWith('.html')) {
|
|
49
|
-
path = path ? path + '.html' : '/index.html';
|
|
50
|
-
}
|
|
51
|
-
return ensureLeadingSlash(path);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Remove the extension from a path. */
|
|
55
|
-
export function stripExtension(path: string) {
|
|
56
|
-
const periodIndex = path.lastIndexOf('.');
|
|
57
|
-
return path.slice(0, periodIndex > -1 ? periodIndex : undefined);
|
|
58
|
-
}
|