@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
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { AstroError } from "astro/errors";
|
|
2
|
+
import { locales } from "astro/zod";
|
|
3
|
+
//#region src/utils/error-map.ts
|
|
4
|
+
/**
|
|
5
|
+
* This is a modified version of Astro's error map.
|
|
6
|
+
* source: https://github.com/withastro/astro/blob/main/packages/astro/src/content/error-map.ts
|
|
7
|
+
*/
|
|
8
|
+
const zodErrorMap = locales.en().localeError;
|
|
9
|
+
/**
|
|
10
|
+
* Parse data with a Zod schema and throw a nicely formatted error if it is invalid.
|
|
11
|
+
*
|
|
12
|
+
* @param schema The Zod schema to use to parse the input.
|
|
13
|
+
* @param input Input data that should match the schema.
|
|
14
|
+
* @param message Error message preamble to use if the input fails to parse.
|
|
15
|
+
* @returns Validated data parsed by Zod.
|
|
16
|
+
*/
|
|
17
|
+
function parseWithFriendlyErrors(schema, input, message) {
|
|
18
|
+
return processParsedData(schema.safeParse(input, {
|
|
19
|
+
error: errorMap,
|
|
20
|
+
reportInput: true
|
|
21
|
+
}), message);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Asynchronously parse data with a Zod schema that contains asynchronous refinements or transforms
|
|
25
|
+
* and throw a nicely formatted error if it is invalid.
|
|
26
|
+
*
|
|
27
|
+
* @param schema The Zod schema to use to parse the input.
|
|
28
|
+
* @param input Input data that should match the schema.
|
|
29
|
+
* @param message Error message preamble to use if the input fails to parse.
|
|
30
|
+
* @returns Validated data parsed by Zod.
|
|
31
|
+
*/
|
|
32
|
+
async function parseAsyncWithFriendlyErrors(schema, input, message) {
|
|
33
|
+
return processParsedData(await schema.safeParseAsync(input, {
|
|
34
|
+
error: errorMap,
|
|
35
|
+
reportInput: true
|
|
36
|
+
}), message);
|
|
37
|
+
}
|
|
38
|
+
function processParsedData(parsedData, message) {
|
|
39
|
+
if (!parsedData.success) throw new AstroError(message, parsedData.error.issues.map((i) => i.message).join("\n"));
|
|
40
|
+
return parsedData.data;
|
|
41
|
+
}
|
|
42
|
+
const errorMap = (issue) => {
|
|
43
|
+
const baseErrorPath = flattenErrorPath(issue.path ?? []);
|
|
44
|
+
if (issue.code === "invalid_union") {
|
|
45
|
+
const unionErrors = issue.errors.flat();
|
|
46
|
+
const typeOrLiteralErrByPath = /* @__PURE__ */ new Map();
|
|
47
|
+
for (const unionError of unionErrors) if (unionError.code === "invalid_type") {
|
|
48
|
+
const flattenedErrorPath = flattenErrorPath([baseErrorPath, ...unionError.path]);
|
|
49
|
+
if (typeOrLiteralErrByPath.has(flattenedErrorPath)) typeOrLiteralErrByPath.get(flattenedErrorPath).expected.push(unionError.expected);
|
|
50
|
+
else typeOrLiteralErrByPath.set(flattenedErrorPath, {
|
|
51
|
+
code: unionError.code,
|
|
52
|
+
received: parsedType(issue.input),
|
|
53
|
+
expected: [unionError.expected],
|
|
54
|
+
message: unionError.message
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const messages = [prefix(baseErrorPath, "Did not match union.")];
|
|
58
|
+
const details = [...typeOrLiteralErrByPath.entries()].filter(([, error]) => error.expected.length === unionErrors.length).map(([key, error]) => key === baseErrorPath ? `> ${getTypeErrMsg(error)}` : `> ${prefix(key, getTypeErrMsg(error))}`);
|
|
59
|
+
if (details.length === 0) {
|
|
60
|
+
const expectedShapes = [];
|
|
61
|
+
for (const unionError of issue.errors) {
|
|
62
|
+
const expectedShape = [];
|
|
63
|
+
for (const issue of unionError) {
|
|
64
|
+
if (issue.code === "invalid_type" && issue.expected === "never") continue;
|
|
65
|
+
if (issue.code === "invalid_union") return errorMap({
|
|
66
|
+
...issue,
|
|
67
|
+
input: issue.input,
|
|
68
|
+
path: [baseErrorPath, ...issue.path]
|
|
69
|
+
});
|
|
70
|
+
const relativePath = flattenErrorPath(issue.path).replace(baseErrorPath, "").replace(leadingPeriod, "");
|
|
71
|
+
if (issue.code === "invalid_type") expectedShape.push(relativePath ? `${relativePath}: ${issue.expected}` : issue.expected);
|
|
72
|
+
else if (issue.code === "custom") expectedShape.push(relativePath);
|
|
73
|
+
}
|
|
74
|
+
if (expectedShape.length === 1 && !expectedShape[0]?.includes(":")) expectedShapes.push(expectedShape.join(""));
|
|
75
|
+
else if (expectedShape.length > 0) expectedShapes.push(`{ ${expectedShape.join("; ")} }`);
|
|
76
|
+
}
|
|
77
|
+
if (expectedShapes.length) {
|
|
78
|
+
details.push("> Expected type `" + expectedShapes.join(" | ") + "`");
|
|
79
|
+
details.push("> Received `" + stringify(issue.input) + "`");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return messages.concat(details).join("\n");
|
|
83
|
+
} else if (issue.code === "invalid_type") return prefix(baseErrorPath, getTypeErrMsg({
|
|
84
|
+
code: issue.code,
|
|
85
|
+
received: parsedType(issue.input),
|
|
86
|
+
expected: [issue.expected],
|
|
87
|
+
message: issue.message
|
|
88
|
+
}));
|
|
89
|
+
else if (issue.message) return prefix(baseErrorPath, issue.message);
|
|
90
|
+
else {
|
|
91
|
+
const defaultError = zodErrorMap(issue);
|
|
92
|
+
if (!defaultError) return;
|
|
93
|
+
return prefix(baseErrorPath, typeof defaultError === "string" ? defaultError : defaultError.message);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const getTypeErrMsg = (error) => {
|
|
97
|
+
if (typeof error.received === "undefined" || error.received === "undefined") return error.message ?? "Required";
|
|
98
|
+
const expectedDeduped = new Set(error.expected);
|
|
99
|
+
return `Expected type \`${unionExpectedVals(expectedDeduped)}\`, received \`${stringify(error.received)}\``;
|
|
100
|
+
};
|
|
101
|
+
const prefix = (key, msg) => key.length ? `**${key}**: ${msg}` : msg;
|
|
102
|
+
const unionExpectedVals = (expectedVals) => [...expectedVals].map((expectedVal) => stringify(expectedVal)).join(" | ");
|
|
103
|
+
const flattenErrorPath = (errorPath) => errorPath.join(".");
|
|
104
|
+
/** `JSON.stringify()` a value with spaces around object/array entries. */
|
|
105
|
+
const stringify = (val) => JSON.stringify(val, null, 1).split(newlinePlusWhitespace).join(" ");
|
|
106
|
+
const newlinePlusWhitespace = /\n\s*/;
|
|
107
|
+
const leadingPeriod = /^\./;
|
|
108
|
+
/**
|
|
109
|
+
* In Zod 4, we don't necessarily get a human-readable representation of input data types. For such
|
|
110
|
+
* cases, we use the same logic as Zod's own `parsedType()` function.
|
|
111
|
+
* @see https://github.com/colinhacks/zod/blob/73b071d7d08825dedb6b48b78718739118ee1308/packages/zod/src/v4/locales/en.ts#L5
|
|
112
|
+
*/
|
|
113
|
+
const parsedType = (data) => {
|
|
114
|
+
const t = typeof data;
|
|
115
|
+
switch (t) {
|
|
116
|
+
case "number": return Number.isNaN(data) ? "NaN" : "number";
|
|
117
|
+
case "object":
|
|
118
|
+
if (Array.isArray(data)) return "array";
|
|
119
|
+
if (data === null) return "null";
|
|
120
|
+
if (data && Object.getPrototypeOf(data) !== Object.prototype && data.constructor) return data.constructor.name;
|
|
121
|
+
}
|
|
122
|
+
return t;
|
|
123
|
+
};
|
|
124
|
+
//#endregion
|
|
125
|
+
export { parseAsyncWithFriendlyErrors, parseWithFriendlyErrors };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createPathFormatter } from "./createPathFormatter.js";
|
|
2
|
+
import project from "virtual:starlight/project-context";
|
|
3
|
+
//#region src/utils/format-path.ts
|
|
4
|
+
const formatPath = createPathFormatter({
|
|
5
|
+
format: project.build.format,
|
|
6
|
+
trailingSlash: project.trailingSlash
|
|
7
|
+
});
|
|
8
|
+
//#endregion
|
|
9
|
+
export { formatPath };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MarkdownHeading } from "astro";
|
|
2
|
+
//#region src/utils/generateToC.d.ts
|
|
3
|
+
interface TocItem extends MarkdownHeading {
|
|
4
|
+
children: TocItem[];
|
|
5
|
+
}
|
|
6
|
+
interface TocOpts {
|
|
7
|
+
minHeadingLevel: number;
|
|
8
|
+
maxHeadingLevel: number;
|
|
9
|
+
title: string;
|
|
10
|
+
}
|
|
11
|
+
/** Convert the flat headings array generated by Astro into a nested tree structure. */
|
|
12
|
+
declare function generateToC(headings: MarkdownHeading[], { minHeadingLevel, maxHeadingLevel, title }: TocOpts): TocItem[];
|
|
13
|
+
//#endregion
|
|
14
|
+
export { TocItem, generateToC };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PAGE_TITLE_ID } from "../constants.js";
|
|
2
|
+
//#region src/utils/generateToC.ts
|
|
3
|
+
/** Convert the flat headings array generated by Astro into a nested tree structure. */
|
|
4
|
+
function generateToC(headings, { minHeadingLevel, maxHeadingLevel, title }) {
|
|
5
|
+
headings = headings.filter(({ depth }) => depth >= minHeadingLevel && depth <= maxHeadingLevel);
|
|
6
|
+
const toc = [{
|
|
7
|
+
depth: 2,
|
|
8
|
+
slug: PAGE_TITLE_ID,
|
|
9
|
+
text: title,
|
|
10
|
+
children: []
|
|
11
|
+
}];
|
|
12
|
+
for (const heading of headings) injectChild(toc, {
|
|
13
|
+
...heading,
|
|
14
|
+
children: []
|
|
15
|
+
});
|
|
16
|
+
return toc;
|
|
17
|
+
}
|
|
18
|
+
/** Inject a ToC entry as deep in the tree as its `depth` property requires. */
|
|
19
|
+
function injectChild(items, item) {
|
|
20
|
+
const lastItem = items.at(-1);
|
|
21
|
+
if (!lastItem || lastItem.depth >= item.depth) items.push(item);
|
|
22
|
+
else return injectChild(lastItem.children, item);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { generateToC };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/utils/git.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Git module to be used from the dev server and from the integration.
|
|
4
|
+
*/
|
|
5
|
+
type GitAPI = {
|
|
6
|
+
getNewestCommitDate: (file: string) => Date;
|
|
7
|
+
};
|
|
8
|
+
declare const makeAPI: (directory: string) => GitAPI;
|
|
9
|
+
declare function getNewestCommitDate(file: string): Date;
|
|
10
|
+
declare function getAllNewestCommitDate(rootPath: string, docsPath: string): [string, number][];
|
|
11
|
+
//#endregion
|
|
12
|
+
export { GitAPI, getAllNewestCommitDate, getNewestCommitDate, makeAPI };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { basename, dirname, relative, resolve } from "node:path";
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
//#region src/utils/git.ts
|
|
5
|
+
/**
|
|
6
|
+
* Git module to be used from the dev server and from the integration.
|
|
7
|
+
*/
|
|
8
|
+
const makeAPI = (directory) => {
|
|
9
|
+
return { getNewestCommitDate: (file) => getNewestCommitDate(resolve(directory, file)) };
|
|
10
|
+
};
|
|
11
|
+
function getNewestCommitDate(file) {
|
|
12
|
+
const result = spawnSync("git", [
|
|
13
|
+
"log",
|
|
14
|
+
"--format=%ct",
|
|
15
|
+
"--max-count=1",
|
|
16
|
+
basename(file)
|
|
17
|
+
], {
|
|
18
|
+
cwd: dirname(file),
|
|
19
|
+
encoding: "utf-8"
|
|
20
|
+
});
|
|
21
|
+
if (result.error) throw new Error(`Failed to retrieve the git history for file "${file}"`);
|
|
22
|
+
const match = result.stdout.trim().match(/^(?<timestamp>\d+)$/);
|
|
23
|
+
if (!match?.groups?.timestamp) throw new Error(`Failed to validate the timestamp for file "${file}"`);
|
|
24
|
+
const timestamp = Number(match.groups.timestamp);
|
|
25
|
+
return /* @__PURE__ */ new Date(timestamp * 1e3);
|
|
26
|
+
}
|
|
27
|
+
function getRepoRoot(directory) {
|
|
28
|
+
const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
|
|
29
|
+
cwd: directory,
|
|
30
|
+
encoding: "utf-8"
|
|
31
|
+
});
|
|
32
|
+
if (result.error) return directory;
|
|
33
|
+
try {
|
|
34
|
+
return realpathSync(result.stdout.trim());
|
|
35
|
+
} catch {
|
|
36
|
+
return directory;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function getAllNewestCommitDate(rootPath, docsPath) {
|
|
40
|
+
const repoRoot = getRepoRoot(docsPath);
|
|
41
|
+
const gitLog = spawnSync("git", [
|
|
42
|
+
"log",
|
|
43
|
+
"--format=t:%ct",
|
|
44
|
+
"--name-status",
|
|
45
|
+
"--",
|
|
46
|
+
docsPath
|
|
47
|
+
], {
|
|
48
|
+
cwd: repoRoot,
|
|
49
|
+
encoding: "utf-8",
|
|
50
|
+
maxBuffer: 10485760
|
|
51
|
+
});
|
|
52
|
+
if (gitLog.error) return [];
|
|
53
|
+
let runningDate = Date.now();
|
|
54
|
+
const latestDates = /* @__PURE__ */ new Map();
|
|
55
|
+
for (const logLine of gitLog.stdout.split("\n")) {
|
|
56
|
+
if (logLine.startsWith("t:")) runningDate = Number.parseInt(logLine.slice(2)) * 1e3;
|
|
57
|
+
const tabSplit = logLine.lastIndexOf(" ");
|
|
58
|
+
if (tabSplit === -1) continue;
|
|
59
|
+
const fileName = logLine.slice(tabSplit + 1);
|
|
60
|
+
const currentLatest = latestDates.get(fileName) || 0;
|
|
61
|
+
latestDates.set(fileName, Math.max(currentLatest, runningDate));
|
|
62
|
+
}
|
|
63
|
+
return Array.from(latestDates.entries()).map(([file, date]) => {
|
|
64
|
+
const fileFullPath = resolve(repoRoot, file);
|
|
65
|
+
let fileInDirectory = relative(rootPath, fileFullPath);
|
|
66
|
+
fileInDirectory = fileInDirectory?.replace(/\\/g, "/");
|
|
67
|
+
return [fileInDirectory, date];
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { getAllNewestCommitDate, getNewestCommitDate, makeAPI };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/utils/gitInlined.ts
|
|
2
|
+
const makeAPI = (data) => {
|
|
3
|
+
const trackedDocsFiles = new Map(data);
|
|
4
|
+
return { getNewestCommitDate: (file) => {
|
|
5
|
+
const timestamp = trackedDocsFiles.get(file);
|
|
6
|
+
if (!timestamp) throw new Error(`Failed to retrieve the git history for file "${file}"`);
|
|
7
|
+
return new Date(timestamp);
|
|
8
|
+
} };
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { makeAPI };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HeadConfig } from "../schemas/head.js";
|
|
2
|
+
import { PageProps, RouteDataContext } from "./routing/data.js";
|
|
3
|
+
//#region src/utils/head.d.ts
|
|
4
|
+
/** Get the head for the current page. */
|
|
5
|
+
declare function getHead({ entry, lang }: PageProps, context: RouteDataContext, siteTitle: string): HeadConfig;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { getHead };
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { HeadConfigSchema } from "../schemas/head.js";
|
|
2
|
+
import { fileWithBase } from "./base.js";
|
|
3
|
+
import { formatCanonical } from "./canonical.js";
|
|
4
|
+
import { version } from "../package.js";
|
|
5
|
+
import { localizedUrl } from "./localizedUrl.js";
|
|
6
|
+
import { isAbsoluteUrl } from "./url.js";
|
|
7
|
+
import config from "virtual:starlight/user-config";
|
|
8
|
+
import project from "virtual:starlight/project-context";
|
|
9
|
+
//#region src/utils/head.ts
|
|
10
|
+
const HeadSchema = HeadConfigSchema({ source: "content" });
|
|
11
|
+
/** Get the head for the current page. */
|
|
12
|
+
function getHead({ entry, lang }, context, siteTitle) {
|
|
13
|
+
const { data } = entry;
|
|
14
|
+
const canonical = context.site ? new URL(context.url.pathname, context.site) : void 0;
|
|
15
|
+
const canonicalHref = canonical?.href ? formatCanonical(canonical.href, {
|
|
16
|
+
format: project.build.format,
|
|
17
|
+
trailingSlash: project.trailingSlash
|
|
18
|
+
}) : void 0;
|
|
19
|
+
const description = data.description || config.description;
|
|
20
|
+
const headDefaults = [
|
|
21
|
+
{
|
|
22
|
+
tag: "meta",
|
|
23
|
+
attrs: { charset: "utf-8" }
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tag: "meta",
|
|
27
|
+
attrs: {
|
|
28
|
+
name: "viewport",
|
|
29
|
+
content: "width=device-width, initial-scale=1"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
tag: "title",
|
|
34
|
+
content: `${data.title} ${config.titleDelimiter} ${siteTitle}`
|
|
35
|
+
},
|
|
36
|
+
...canonicalHref !== void 0 ? [{
|
|
37
|
+
tag: "link",
|
|
38
|
+
attrs: {
|
|
39
|
+
rel: "canonical",
|
|
40
|
+
href: canonicalHref
|
|
41
|
+
}
|
|
42
|
+
}] : [],
|
|
43
|
+
{
|
|
44
|
+
tag: "meta",
|
|
45
|
+
attrs: {
|
|
46
|
+
name: "generator",
|
|
47
|
+
content: context.generator
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
tag: "meta",
|
|
52
|
+
attrs: {
|
|
53
|
+
name: "generator",
|
|
54
|
+
content: `Starlight v${version}`
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
tag: "link",
|
|
59
|
+
attrs: {
|
|
60
|
+
rel: "shortcut icon",
|
|
61
|
+
href: isAbsoluteUrl(config.favicon.href) ? config.favicon.href : fileWithBase(config.favicon.href),
|
|
62
|
+
type: config.favicon.type
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
tag: "meta",
|
|
67
|
+
attrs: {
|
|
68
|
+
property: "og:title",
|
|
69
|
+
content: data.title
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
tag: "meta",
|
|
74
|
+
attrs: {
|
|
75
|
+
property: "og:type",
|
|
76
|
+
content: "article"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
...canonicalHref !== void 0 ? [{
|
|
80
|
+
tag: "meta",
|
|
81
|
+
attrs: {
|
|
82
|
+
property: "og:url",
|
|
83
|
+
content: canonicalHref
|
|
84
|
+
}
|
|
85
|
+
}] : [],
|
|
86
|
+
{
|
|
87
|
+
tag: "meta",
|
|
88
|
+
attrs: {
|
|
89
|
+
property: "og:locale",
|
|
90
|
+
content: lang
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
...description !== void 0 ? [{
|
|
94
|
+
tag: "meta",
|
|
95
|
+
attrs: {
|
|
96
|
+
property: "og:description",
|
|
97
|
+
content: description
|
|
98
|
+
}
|
|
99
|
+
}] : [],
|
|
100
|
+
{
|
|
101
|
+
tag: "meta",
|
|
102
|
+
attrs: {
|
|
103
|
+
property: "og:site_name",
|
|
104
|
+
content: siteTitle
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
tag: "meta",
|
|
109
|
+
attrs: {
|
|
110
|
+
name: "twitter:card",
|
|
111
|
+
content: "summary_large_image"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
if (description) headDefaults.push({
|
|
116
|
+
tag: "meta",
|
|
117
|
+
attrs: {
|
|
118
|
+
name: "description",
|
|
119
|
+
content: description
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
if (canonical && config.isMultilingual) {
|
|
123
|
+
for (const locale in config.locales) {
|
|
124
|
+
const localeOpts = config.locales[locale];
|
|
125
|
+
if (!localeOpts) continue;
|
|
126
|
+
headDefaults.push({
|
|
127
|
+
tag: "link",
|
|
128
|
+
attrs: {
|
|
129
|
+
rel: "alternate",
|
|
130
|
+
hreflang: localeOpts.lang,
|
|
131
|
+
href: localizedUrl(canonical, locale, project.trailingSlash).href
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
headDefaults.push({
|
|
136
|
+
tag: "link",
|
|
137
|
+
attrs: {
|
|
138
|
+
rel: "alternate",
|
|
139
|
+
hreflang: "x-default",
|
|
140
|
+
href: localizedUrl(canonical, config.defaultLocale.locale, project.trailingSlash).href
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (context.site) headDefaults.push({
|
|
145
|
+
tag: "link",
|
|
146
|
+
attrs: {
|
|
147
|
+
rel: "sitemap",
|
|
148
|
+
href: fileWithBase("/sitemap-index.xml")
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
const twitterLink = config.social?.find(({ icon }) => icon === "twitter" || icon === "x.com");
|
|
152
|
+
if (twitterLink) headDefaults.push({
|
|
153
|
+
tag: "meta",
|
|
154
|
+
attrs: {
|
|
155
|
+
name: "twitter:site",
|
|
156
|
+
content: new URL(twitterLink.href).pathname.replace("/", "@")
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return createHead(headDefaults, config.head, data.head);
|
|
160
|
+
}
|
|
161
|
+
/** Create a fully parsed, merged, and sorted head entry array from multiple sources. */
|
|
162
|
+
function createHead(defaults, ...heads) {
|
|
163
|
+
let head = HeadSchema.parse(defaults);
|
|
164
|
+
for (const next of heads) head = mergeHead(head, next);
|
|
165
|
+
return sortHead(head);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Test if a head config object contains a matching `<title>`, `<meta>`, `<link rel="canonical">`
|
|
169
|
+
* or `<link rel="sitemap">` tag.
|
|
170
|
+
*
|
|
171
|
+
* For example, will return true if `head` already contains
|
|
172
|
+
* `<meta name="description" content="A">` and the passed `tag`
|
|
173
|
+
* is `<meta name="description" content="B">`. Tests against `name`,
|
|
174
|
+
* `property`, and `http-equiv` attributes for `<meta>` tags.
|
|
175
|
+
*/
|
|
176
|
+
function hasTag(head, entry) {
|
|
177
|
+
switch (entry.tag) {
|
|
178
|
+
case "title": return head.some(({ tag }) => tag === "title");
|
|
179
|
+
case "meta": return hasOneOf(head, entry, [
|
|
180
|
+
"name",
|
|
181
|
+
"property",
|
|
182
|
+
"http-equiv"
|
|
183
|
+
]);
|
|
184
|
+
case "link": return head.some(({ attrs }) => entry.attrs?.rel === "canonical" && attrs?.rel === "canonical" || entry.attrs?.rel === "sitemap" && attrs?.rel === "sitemap");
|
|
185
|
+
default: return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Test if a head config object contains a tag of the same type
|
|
190
|
+
* as `entry` and a matching attribute for one of the passed `keys`.
|
|
191
|
+
*/
|
|
192
|
+
function hasOneOf(head, entry, keys) {
|
|
193
|
+
const attr = getAttr(keys, entry);
|
|
194
|
+
if (!attr) return false;
|
|
195
|
+
const [key, val] = attr;
|
|
196
|
+
return head.some(({ tag, attrs }) => tag === entry.tag && attrs?.[key] === val);
|
|
197
|
+
}
|
|
198
|
+
/** Find the first matching key–value pair in a head entry’s attributes. */
|
|
199
|
+
function getAttr(keys, entry) {
|
|
200
|
+
let attr;
|
|
201
|
+
for (const key of keys) {
|
|
202
|
+
const val = entry.attrs?.[key];
|
|
203
|
+
if (val) {
|
|
204
|
+
attr = [key, val];
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return attr;
|
|
209
|
+
}
|
|
210
|
+
/** Merge two heads, overwriting entries in the first head that exist in the second. */
|
|
211
|
+
function mergeHead(oldHead, newHead) {
|
|
212
|
+
return [...oldHead.filter((tag) => !hasTag(newHead, tag)), ...newHead];
|
|
213
|
+
}
|
|
214
|
+
/** Sort head tags to place important tags first and relegate “SEO” meta tags. */
|
|
215
|
+
function sortHead(head) {
|
|
216
|
+
return head.sort((a, b) => {
|
|
217
|
+
const aImportance = getImportance(a);
|
|
218
|
+
const bImportance = getImportance(b);
|
|
219
|
+
return aImportance > bImportance ? -1 : bImportance > aImportance ? 1 : 0;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/** Get the relative importance of a specific head tag. */
|
|
223
|
+
function getImportance(entry) {
|
|
224
|
+
if (entry.tag === "meta" && entry.attrs && ("charset" in entry.attrs || "http-equiv" in entry.attrs || entry.attrs.name === "viewport")) return 100;
|
|
225
|
+
if (entry.tag === "title") return 90;
|
|
226
|
+
if (entry.tag !== "meta") {
|
|
227
|
+
if (entry.tag === "link" && entry.attrs && "rel" in entry.attrs && entry.attrs.rel === "shortcut icon") return 70;
|
|
228
|
+
return 80;
|
|
229
|
+
}
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
export { getHead };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { StarlightConfig } from "./user-config.js";
|
|
2
|
+
import { AstroConfig } from "astro";
|
|
3
|
+
//#region src/utils/i18n.d.ts
|
|
4
|
+
/** Information about the built-in default locale used as a fallback when no locales are defined. */
|
|
5
|
+
declare const BuiltInDefaultLocale: {
|
|
6
|
+
lang: string;
|
|
7
|
+
label: string;
|
|
8
|
+
dir: "rtl" | "ltr";
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Processes the Astro and Starlight i18n configurations to generate/update them accordingly:
|
|
12
|
+
*
|
|
13
|
+
* - If no Astro and Starlight i18n configurations are provided, the built-in default locale is
|
|
14
|
+
* used in Starlight and the generated Astro i18n configuration will match it.
|
|
15
|
+
* - If only a Starlight i18n configuration is provided, an equivalent Astro i18n configuration is
|
|
16
|
+
* generated.
|
|
17
|
+
* - If only an Astro i18n configuration is provided, an equivalent Starlight i18n configuration is
|
|
18
|
+
* used.
|
|
19
|
+
* - If both an Astro and Starlight i18n configurations are provided, an error is thrown.
|
|
20
|
+
*/
|
|
21
|
+
declare function processI18nConfig(starlightConfig: StarlightConfig, astroI18nConfig: AstroConfig['i18n']): {
|
|
22
|
+
astroI18nConfig: {
|
|
23
|
+
defaultLocale: string;
|
|
24
|
+
locales: (string | {
|
|
25
|
+
path: string;
|
|
26
|
+
codes: [string, ...string[]];
|
|
27
|
+
})[];
|
|
28
|
+
routing: "manual" | {
|
|
29
|
+
prefixDefaultLocale: boolean;
|
|
30
|
+
redirectToDefaultLocale: boolean;
|
|
31
|
+
fallbackType: "redirect" | "rewrite";
|
|
32
|
+
};
|
|
33
|
+
domains?: Record<string, string> | undefined;
|
|
34
|
+
fallback?: Record<string, string> | undefined;
|
|
35
|
+
};
|
|
36
|
+
starlightConfig: StarlightConfig;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Get the string for the passed language from a dictionary object.
|
|
40
|
+
*
|
|
41
|
+
* TODO: Make this clever. Currently a simple key look-up, but should use
|
|
42
|
+
* BCP-47 mapping so that e.g. `en-US` returns `en` strings, and use the
|
|
43
|
+
* site’s default locale as a last resort.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* pickLang({ en: 'Hello', fr: 'Bonjour' }, 'en'); // => 'Hello'
|
|
47
|
+
*/
|
|
48
|
+
declare function pickLang<T extends Record<string, string>>(dictionary: T, lang: keyof T): string | undefined;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { BuiltInDefaultLocale, pickLang, processI18nConfig };
|