@astrojs/starlight 0.41.10 → 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.
Files changed (402) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +13 -0
  2. package/dist/components/MobileMenuToggle.astro +65 -0
  3. package/{components → dist/components}/PageFrame.astro +32 -8
  4. package/dist/components-internals/Icons.d.ts +415 -0
  5. package/dist/components-internals/Icons.js +140 -0
  6. package/dist/components-internals/SidebarPersistState.d.ts +1 -0
  7. package/dist/components-internals/SidebarPersistState.js +53 -0
  8. package/dist/components-internals/TableOfContents/starlight-toc.d.ts +18 -0
  9. package/dist/components-internals/TableOfContents/starlight-toc.js +88 -0
  10. package/dist/constants.d.ts +4 -0
  11. package/dist/constants.js +4 -0
  12. package/{expressive-code.d.ts → dist/expressive-code.d.ts} +6 -13
  13. package/dist/expressive-code.js +31 -0
  14. package/dist/global.d.ts +62 -0
  15. package/dist/global.js +2 -0
  16. package/dist/index.d.ts +7 -0
  17. package/dist/index.js +109 -0
  18. package/dist/integrations/aside-utils.d.ts +9 -0
  19. package/dist/integrations/aside-utils.js +35 -0
  20. package/dist/integrations/expressive-code/hast.d.ts +1 -0
  21. package/dist/integrations/expressive-code/hast.js +2 -0
  22. package/dist/integrations/expressive-code/index.d.ts +60 -0
  23. package/dist/integrations/expressive-code/index.js +48 -0
  24. package/dist/integrations/expressive-code/preprocessor.d.ts +17 -0
  25. package/dist/integrations/expressive-code/preprocessor.js +76 -0
  26. package/dist/integrations/expressive-code/themes/night-owl-dark.js +4 -0
  27. package/dist/integrations/expressive-code/themes/night-owl-light.js +4 -0
  28. package/dist/integrations/expressive-code/theming.d.ts +16 -0
  29. package/dist/integrations/expressive-code/theming.js +71 -0
  30. package/dist/integrations/expressive-code/translations.d.ts +8 -0
  31. package/dist/integrations/expressive-code/translations.js +26 -0
  32. package/dist/integrations/markdown-icon.d.ts +8 -0
  33. package/dist/integrations/markdown-icon.js +14 -0
  34. package/dist/integrations/markdown-plugins.d.ts +18 -0
  35. package/dist/integrations/markdown-plugins.js +36 -0
  36. package/dist/integrations/markdown-processor.d.ts +29 -0
  37. package/dist/integrations/markdown-processor.js +44 -0
  38. package/dist/integrations/pagefind.d.ts +7 -0
  39. package/dist/integrations/pagefind.js +34 -0
  40. package/dist/integrations/rehype-code-rtl-support.d.ts +21 -0
  41. package/dist/integrations/rehype-code-rtl-support.js +36 -0
  42. package/dist/integrations/rehype-heading-links.d.ts +10 -0
  43. package/dist/integrations/rehype-heading-links.js +57 -0
  44. package/dist/integrations/remark-asides.d.ts +32 -0
  45. package/dist/integrations/remark-asides.js +166 -0
  46. package/dist/integrations/remark-rehype.d.ts +17 -0
  47. package/dist/integrations/remark-rehype.js +51 -0
  48. package/dist/integrations/satteri.d.ts +13 -0
  49. package/dist/integrations/satteri.js +209 -0
  50. package/dist/integrations/shared/absolutePathToLang.d.ts +10 -0
  51. package/dist/integrations/shared/absolutePathToLang.js +13 -0
  52. package/dist/integrations/shared/localeToLang.d.ts +10 -0
  53. package/dist/integrations/shared/localeToLang.js +13 -0
  54. package/dist/integrations/shared/slugToLocale.d.ts +12 -0
  55. package/dist/integrations/shared/slugToLocale.js +15 -0
  56. package/dist/integrations/sitemap.d.ts +12 -0
  57. package/dist/integrations/sitemap.js +19 -0
  58. package/dist/integrations/vite-layer-order.d.ts +15 -0
  59. package/dist/integrations/vite-layer-order.js +56 -0
  60. package/dist/integrations/vite-lazy-barrel-optimization.d.ts +12 -0
  61. package/dist/integrations/vite-lazy-barrel-optimization.js +33 -0
  62. package/dist/integrations/vite-virtual-modules.d.ts +14 -0
  63. package/dist/integrations/vite-virtual-modules.js +108 -0
  64. package/dist/internal.d.ts +3 -0
  65. package/dist/internal.js +3 -0
  66. package/dist/loaders.d.ts +20 -0
  67. package/dist/loaders.js +49 -0
  68. package/dist/locals.d.ts +15 -0
  69. package/dist/locals.js +33 -0
  70. package/dist/package.js +4 -0
  71. package/{props.ts → dist/props.d.ts} +6 -4
  72. package/dist/props.js +1 -0
  73. package/dist/route-data.d.ts +7 -0
  74. package/dist/route-data.js +6 -0
  75. package/dist/schema.d.ts +426 -0
  76. package/dist/schema.js +103 -0
  77. package/dist/schemas/badge.d.ts +86 -0
  78. package/dist/schemas/badge.js +39 -0
  79. package/dist/schemas/components.d.ts +236 -0
  80. package/dist/schemas/components.js +36 -0
  81. package/dist/schemas/expressiveCode.d.ts +7 -0
  82. package/dist/schemas/expressiveCode.js +5 -0
  83. package/dist/schemas/favicon.d.ts +9 -0
  84. package/dist/schemas/favicon.js +32 -0
  85. package/dist/schemas/head.d.ts +33 -0
  86. package/dist/schemas/head.js +41 -0
  87. package/dist/schemas/hero.d.ts +319 -0
  88. package/dist/schemas/hero.js +73 -0
  89. package/dist/schemas/i18n.d.ts +125 -0
  90. package/dist/schemas/i18n.js +76 -0
  91. package/dist/schemas/icon.d.ts +284 -0
  92. package/dist/schemas/icon.js +7 -0
  93. package/dist/schemas/locale.d.ts +20 -0
  94. package/dist/schemas/locale.js +11 -0
  95. package/dist/schemas/logo.d.ts +32 -0
  96. package/dist/schemas/logo.js +14 -0
  97. package/dist/schemas/pagefind.d.ts +166 -0
  98. package/dist/schemas/pagefind.js +31 -0
  99. package/dist/schemas/prevNextLink.d.ts +10 -0
  100. package/dist/schemas/prevNextLink.js +14 -0
  101. package/dist/schemas/sidebar.d.ts +205 -0
  102. package/dist/schemas/sidebar.js +71 -0
  103. package/dist/schemas/site-title.d.ts +7 -0
  104. package/dist/schemas/site-title.js +17 -0
  105. package/dist/schemas/social.d.ts +292 -0
  106. package/dist/schemas/social.js +18 -0
  107. package/dist/schemas/tableOfContents.d.ts +24 -0
  108. package/dist/schemas/tableOfContents.js +16 -0
  109. package/{style → dist/style}/anchor-links.css +13 -1
  110. package/dist/translations/ar.js +36 -0
  111. package/dist/translations/ca.js +46 -0
  112. package/dist/translations/cs.js +46 -0
  113. package/dist/translations/da.js +33 -0
  114. package/dist/translations/de.js +33 -0
  115. package/dist/translations/el.js +33 -0
  116. package/dist/translations/en.js +33 -0
  117. package/dist/translations/es.js +46 -0
  118. package/dist/translations/fa.js +33 -0
  119. package/dist/translations/fi.js +33 -0
  120. package/dist/translations/fr.js +36 -0
  121. package/dist/translations/gl.js +46 -0
  122. package/dist/translations/he.js +33 -0
  123. package/dist/translations/hi.js +36 -0
  124. package/dist/translations/hu.js +46 -0
  125. package/dist/translations/id.js +33 -0
  126. package/dist/translations/index.d.ts +48 -0
  127. package/dist/translations/index.js +75 -0
  128. package/dist/translations/it.js +36 -0
  129. package/dist/translations/ja.js +36 -0
  130. package/dist/translations/ko.js +36 -0
  131. package/dist/translations/lv.js +33 -0
  132. package/dist/translations/nb.js +33 -0
  133. package/dist/translations/nl.js +33 -0
  134. package/dist/translations/pl.js +36 -0
  135. package/dist/translations/pt.js +36 -0
  136. package/dist/translations/ro.js +33 -0
  137. package/dist/translations/ru.js +36 -0
  138. package/dist/translations/sk.js +33 -0
  139. package/dist/translations/sv.js +33 -0
  140. package/dist/translations/th.js +33 -0
  141. package/dist/translations/tr.js +33 -0
  142. package/dist/translations/uk.js +33 -0
  143. package/dist/translations/vi.js +33 -0
  144. package/dist/translations/zh-CN.js +36 -0
  145. package/dist/translations/zh-TW.js +36 -0
  146. package/dist/types.d.ts +4 -0
  147. package/dist/types.js +1 -0
  148. package/{user-components → dist/user-components}/FileTree.astro +1 -1
  149. package/{user-components → dist/user-components}/Steps.astro +1 -1
  150. package/{user-components → dist/user-components}/TabItem.astro +1 -1
  151. package/{user-components → dist/user-components}/Tabs.astro +1 -1
  152. package/dist/user-components/file-tree-icons.d.ts +178 -0
  153. package/dist/user-components/file-tree-icons.js +632 -0
  154. package/dist/user-components/file-tree-processor.d.ts +16 -0
  155. package/dist/user-components/file-tree-processor.js +132 -0
  156. package/dist/user-components/steps-processor.d.ts +10 -0
  157. package/dist/user-components/steps-processor.js +39 -0
  158. package/dist/user-components/tabs-processor.d.ts +23 -0
  159. package/dist/user-components/tabs-processor.js +70 -0
  160. package/dist/utils/base.d.ts +7 -0
  161. package/dist/utils/base.js +15 -0
  162. package/dist/utils/canonical.d.ts +10 -0
  163. package/dist/utils/canonical.js +14 -0
  164. package/dist/utils/collection-fs.d.ts +13 -0
  165. package/dist/utils/collection-fs.js +19 -0
  166. package/{utils/collection.ts → dist/utils/collection.d.ts} +9 -20
  167. package/dist/utils/collection.js +26 -0
  168. package/dist/utils/createPathFormatter.d.ts +9 -0
  169. package/dist/utils/createPathFormatter.js +35 -0
  170. package/dist/utils/createTranslationSystem.d.ts +23 -0
  171. package/dist/utils/createTranslationSystem.js +84 -0
  172. package/dist/utils/error-map.d.ts +23 -0
  173. package/dist/utils/error-map.js +125 -0
  174. package/dist/utils/format-path.d.ts +4 -0
  175. package/dist/utils/format-path.js +9 -0
  176. package/dist/utils/generateToC.d.ts +14 -0
  177. package/dist/utils/generateToC.js +25 -0
  178. package/dist/utils/git.d.ts +12 -0
  179. package/dist/utils/git.js +71 -0
  180. package/dist/utils/gitInlined.d.ts +6 -0
  181. package/dist/utils/gitInlined.js +11 -0
  182. package/dist/utils/head.d.ts +7 -0
  183. package/dist/utils/head.js +233 -0
  184. package/dist/utils/i18n.d.ts +50 -0
  185. package/dist/utils/i18n.js +141 -0
  186. package/dist/utils/localizedUrl.d.ts +8 -0
  187. package/dist/utils/localizedUrl.js +28 -0
  188. package/dist/utils/navigation.d.ts +19 -0
  189. package/dist/utils/navigation.js +353 -0
  190. package/dist/utils/path.d.ts +21 -0
  191. package/dist/utils/path.js +51 -0
  192. package/dist/utils/plugins.d.ts +721 -0
  193. package/dist/utils/plugins.js +174 -0
  194. package/dist/utils/routing/data.d.ts +20 -0
  195. package/dist/utils/routing/data.js +127 -0
  196. package/dist/utils/routing/index.d.ts +21 -0
  197. package/dist/utils/routing/index.js +106 -0
  198. package/dist/utils/routing/middleware.d.ts +11 -0
  199. package/dist/utils/routing/middleware.js +65 -0
  200. package/dist/utils/routing/types.d.ts +93 -0
  201. package/dist/utils/routing/types.js +1 -0
  202. package/dist/utils/slugs.d.ts +45 -0
  203. package/dist/utils/slugs.js +104 -0
  204. package/dist/utils/starlight-page.d.ts +36 -0
  205. package/dist/utils/starlight-page.js +120 -0
  206. package/dist/utils/translations-fs.d.ts +15 -0
  207. package/dist/utils/translations-fs.js +39 -0
  208. package/dist/utils/translations.d.ts +20 -0
  209. package/dist/utils/translations.js +29 -0
  210. package/dist/utils/types.d.ts +5 -0
  211. package/dist/utils/types.js +1 -0
  212. package/dist/utils/url.d.ts +7 -0
  213. package/{utils/url.ts → dist/utils/url.js} +5 -4
  214. package/dist/utils/user-config.d.ts +2055 -0
  215. package/dist/utils/user-config.js +136 -0
  216. package/dist/utils/validateLogoImports.d.ts +5 -0
  217. package/dist/utils/validateLogoImports.js +16 -0
  218. package/dist/utils/zodDeepMerge.d.ts +16 -0
  219. package/dist/utils/zodDeepMerge.js +53 -0
  220. package/package.json +62 -33
  221. package/CHANGELOG.md +0 -3043
  222. package/components/MobileMenuToggle.astro +0 -114
  223. package/components-internals/Icons.ts +0 -248
  224. package/components-internals/SidebarPersistState.ts +0 -71
  225. package/components-internals/TableOfContents/starlight-toc.ts +0 -127
  226. package/constants.ts +0 -4
  227. package/expressive-code.mjs +0 -23
  228. package/global.d.ts +0 -11
  229. package/i18n.d.ts +0 -18
  230. package/index.ts +0 -200
  231. package/integrations/aside-utils.ts +0 -41
  232. package/integrations/expressive-code/hast.d.ts +0 -5
  233. package/integrations/expressive-code/hast.mjs +0 -9
  234. package/integrations/expressive-code/index.ts +0 -125
  235. package/integrations/expressive-code/preprocessor.ts +0 -126
  236. package/integrations/expressive-code/themes/night-owl-dark.jsonc +0 -1796
  237. package/integrations/expressive-code/themes/night-owl-light.jsonc +0 -1695
  238. package/integrations/expressive-code/theming.ts +0 -105
  239. package/integrations/expressive-code/translations.ts +0 -36
  240. package/integrations/markdown-icon.ts +0 -13
  241. package/integrations/markdown-plugins.ts +0 -71
  242. package/integrations/markdown-processor.ts +0 -64
  243. package/integrations/pagefind.ts +0 -60
  244. package/integrations/rehype-code-rtl-support.ts +0 -37
  245. package/integrations/rehype-heading-links.ts +0 -79
  246. package/integrations/remark-asides.ts +0 -219
  247. package/integrations/remark-rehype.ts +0 -87
  248. package/integrations/satteri.ts +0 -265
  249. package/integrations/shared/absolutePathToLang.ts +0 -26
  250. package/integrations/shared/localeToLang.ts +0 -15
  251. package/integrations/shared/slugToLocale.ts +0 -18
  252. package/integrations/sitemap.ts +0 -23
  253. package/integrations/vite-layer-order.ts +0 -69
  254. package/integrations/vite-lazy-barrel-optimization.ts +0 -40
  255. package/integrations/vite-virtual-modules.ts +0 -175
  256. package/internal.ts +0 -6
  257. package/loaders.ts +0 -63
  258. package/locals.d.ts +0 -43
  259. package/locals.ts +0 -43
  260. package/route-data.ts +0 -11
  261. package/schema.ts +0 -167
  262. package/schemas/badge.ts +0 -40
  263. package/schemas/components.ts +0 -265
  264. package/schemas/expressiveCode.ts +0 -12
  265. package/schemas/favicon.ts +0 -40
  266. package/schemas/head.ts +0 -50
  267. package/schemas/hero.ts +0 -69
  268. package/schemas/i18n.ts +0 -244
  269. package/schemas/icon.ts +0 -7
  270. package/schemas/logo.ts +0 -28
  271. package/schemas/pagefind.ts +0 -128
  272. package/schemas/prevNextLink.ts +0 -18
  273. package/schemas/sidebar.ts +0 -163
  274. package/schemas/site-title.ts +0 -20
  275. package/schemas/social.ts +0 -23
  276. package/schemas/tableOfContents.ts +0 -21
  277. package/translations/README.md +0 -14
  278. package/translations/ar.json +0 -33
  279. package/translations/ca.json +0 -43
  280. package/translations/cs.json +0 -43
  281. package/translations/da.json +0 -30
  282. package/translations/de.json +0 -30
  283. package/translations/el.json +0 -30
  284. package/translations/en.json +0 -30
  285. package/translations/es.json +0 -43
  286. package/translations/fa.json +0 -30
  287. package/translations/fi.json +0 -30
  288. package/translations/fr.json +0 -33
  289. package/translations/gl.json +0 -43
  290. package/translations/he.json +0 -30
  291. package/translations/hi.json +0 -33
  292. package/translations/hu.json +0 -43
  293. package/translations/id.json +0 -30
  294. package/translations/index.ts +0 -76
  295. package/translations/it.json +0 -33
  296. package/translations/ja.json +0 -33
  297. package/translations/ko.json +0 -33
  298. package/translations/lv.json +0 -30
  299. package/translations/nb.json +0 -30
  300. package/translations/nl.json +0 -30
  301. package/translations/pl.json +0 -33
  302. package/translations/pt.json +0 -33
  303. package/translations/ro.json +0 -30
  304. package/translations/ru.json +0 -33
  305. package/translations/sk.json +0 -30
  306. package/translations/sv.json +0 -30
  307. package/translations/th.json +0 -30
  308. package/translations/tr.json +0 -30
  309. package/translations/uk.json +0 -30
  310. package/translations/vi.json +0 -30
  311. package/translations/zh-CN.json +0 -33
  312. package/translations/zh-TW.json +0 -33
  313. package/types.ts +0 -7
  314. package/user-components/file-tree-icons.ts +0 -782
  315. package/user-components/rehype-file-tree.ts +0 -251
  316. package/user-components/rehype-steps.ts +0 -85
  317. package/user-components/rehype-tabs.ts +0 -121
  318. package/utils/base.ts +0 -15
  319. package/utils/canonical.ts +0 -19
  320. package/utils/collection-fs.ts +0 -20
  321. package/utils/createPathFormatter.ts +0 -60
  322. package/utils/createTranslationSystem.ts +0 -137
  323. package/utils/error-map.ts +0 -222
  324. package/utils/format-path.ts +0 -7
  325. package/utils/generateToC.ts +0 -33
  326. package/utils/git.ts +0 -121
  327. package/utils/gitInlined.ts +0 -20
  328. package/utils/head.ts +0 -235
  329. package/utils/i18n.ts +0 -221
  330. package/utils/localizedUrl.ts +0 -51
  331. package/utils/navigation.ts +0 -566
  332. package/utils/path.ts +0 -58
  333. package/utils/plugins.ts +0 -498
  334. package/utils/routing/data.ts +0 -154
  335. package/utils/routing/index.ts +0 -135
  336. package/utils/routing/middleware.ts +0 -81
  337. package/utils/routing/types.ts +0 -101
  338. package/utils/slugs.ts +0 -119
  339. package/utils/starlight-page.ts +0 -205
  340. package/utils/translations-fs.ts +0 -54
  341. package/utils/translations.ts +0 -57
  342. package/utils/types.ts +0 -15
  343. package/utils/user-config.ts +0 -348
  344. package/utils/validateLogoImports.ts +0 -21
  345. package/utils/zodDeepMerge.ts +0 -144
  346. package/virtual-internal.d.ts +0 -149
  347. package/virtual.d.ts +0 -27
  348. /package/{components → dist/components}/AnchorHeading.astro +0 -0
  349. /package/{components → dist/components}/Banner.astro +0 -0
  350. /package/{components → dist/components}/ContentNotice.astro +0 -0
  351. /package/{components → dist/components}/ContentPanel.astro +0 -0
  352. /package/{components → dist/components}/DraftContentNotice.astro +0 -0
  353. /package/{components → dist/components}/EditLink.astro +0 -0
  354. /package/{components → dist/components}/FallbackContentNotice.astro +0 -0
  355. /package/{components → dist/components}/Footer.astro +0 -0
  356. /package/{components → dist/components}/Head.astro +0 -0
  357. /package/{components → dist/components}/Header.astro +0 -0
  358. /package/{components → dist/components}/Hero.astro +0 -0
  359. /package/{components → dist/components}/LanguageSelect.astro +0 -0
  360. /package/{components → dist/components}/LastUpdated.astro +0 -0
  361. /package/{components → dist/components}/MarkdownContent.astro +0 -0
  362. /package/{components → dist/components}/MobileMenuFooter.astro +0 -0
  363. /package/{components → dist/components}/MobileTableOfContents.astro +0 -0
  364. /package/{components → dist/components}/Page.astro +0 -0
  365. /package/{components → dist/components}/PageSidebar.astro +0 -0
  366. /package/{components → dist/components}/PageTitle.astro +0 -0
  367. /package/{components → dist/components}/Pagination.astro +0 -0
  368. /package/{components → dist/components}/Search.astro +0 -0
  369. /package/{components → dist/components}/Select.astro +0 -0
  370. /package/{components → dist/components}/Sidebar.astro +0 -0
  371. /package/{components → dist/components}/SidebarPersister.astro +0 -0
  372. /package/{components → dist/components}/SidebarRestorePoint.astro +0 -0
  373. /package/{components → dist/components}/SidebarSublist.astro +0 -0
  374. /package/{components → dist/components}/SiteTitle.astro +0 -0
  375. /package/{components → dist/components}/SkipLink.astro +0 -0
  376. /package/{components → dist/components}/SocialIcons.astro +0 -0
  377. /package/{components → dist/components}/StarlightPage.astro +0 -0
  378. /package/{components → dist/components}/TableOfContents.astro +0 -0
  379. /package/{components → dist/components}/ThemeProvider.astro +0 -0
  380. /package/{components → dist/components}/ThemeSelect.astro +0 -0
  381. /package/{components → dist/components}/TwoColumnContent.astro +0 -0
  382. /package/{components-internals → dist/components-internals}/TableOfContents/TableOfContentsList.astro +0 -0
  383. /package/{components.ts → dist/components.ts} +0 -0
  384. /package/{routes → dist/routes}/common.astro +0 -0
  385. /package/{routes → dist/routes}/ssr/404.astro +0 -0
  386. /package/{routes → dist/routes}/ssr/index.astro +0 -0
  387. /package/{routes → dist/routes}/static/404.astro +0 -0
  388. /package/{routes → dist/routes}/static/index.astro +0 -0
  389. /package/{style → dist/style}/asides.css +0 -0
  390. /package/{style → dist/style}/layers.css +0 -0
  391. /package/{style → dist/style}/markdown.css +0 -0
  392. /package/{style → dist/style}/print.css +0 -0
  393. /package/{style → dist/style}/props.css +0 -0
  394. /package/{style → dist/style}/reset.css +0 -0
  395. /package/{style → dist/style}/util.css +0 -0
  396. /package/{user-components → dist/user-components}/Aside.astro +0 -0
  397. /package/{user-components → dist/user-components}/Badge.astro +0 -0
  398. /package/{user-components → dist/user-components}/Card.astro +0 -0
  399. /package/{user-components → dist/user-components}/CardGrid.astro +0 -0
  400. /package/{user-components → dist/user-components}/Icon.astro +0 -0
  401. /package/{user-components → dist/user-components}/LinkButton.astro +0 -0
  402. /package/{user-components → dist/user-components}/LinkCard.astro +0 -0
@@ -0,0 +1,141 @@
1
+ import { AstroError } from "astro/errors";
2
+ //#region src/utils/i18n.ts
3
+ /**
4
+ * A list of well-known right-to-left languages used as a fallback when determining the text
5
+ * direction of a locale is not supported by the `Intl.Locale` API in the current environment.
6
+ *
7
+ * @see getLocaleDir()
8
+ * @see https://en.wikipedia.org/wiki/IETF_language_tag#List_of_common_primary_language_subtags
9
+ */
10
+ const wellKnownRTL = [
11
+ "ar",
12
+ "fa",
13
+ "he",
14
+ "prs",
15
+ "ps",
16
+ "syc",
17
+ "ug",
18
+ "ur"
19
+ ];
20
+ /** Information about the built-in default locale used as a fallback when no locales are defined. */
21
+ const BuiltInDefaultLocale = {
22
+ ...getLocaleInfo("en"),
23
+ lang: "en"
24
+ };
25
+ /**
26
+ * Processes the Astro and Starlight i18n configurations to generate/update them accordingly:
27
+ *
28
+ * - If no Astro and Starlight i18n configurations are provided, the built-in default locale is
29
+ * used in Starlight and the generated Astro i18n configuration will match it.
30
+ * - If only a Starlight i18n configuration is provided, an equivalent Astro i18n configuration is
31
+ * generated.
32
+ * - If only an Astro i18n configuration is provided, an equivalent Starlight i18n configuration is
33
+ * used.
34
+ * - If both an Astro and Starlight i18n configurations are provided, an error is thrown.
35
+ */
36
+ function processI18nConfig(starlightConfig, astroI18nConfig) {
37
+ if (astroI18nConfig && !starlightConfig.isUsingBuiltInDefaultLocale) throw new AstroError("Cannot provide both an Astro `i18n` configuration and a Starlight `locales` configuration.", "Remove one of the two configurations.\nSee more at https://starlight.astro.build/guides/i18n/");
38
+ else if (astroI18nConfig) return {
39
+ astroI18nConfig,
40
+ starlightConfig: {
41
+ ...starlightConfig,
42
+ ...getStarlightI18nConfig(astroI18nConfig)
43
+ }
44
+ };
45
+ return {
46
+ astroI18nConfig: getAstroI18nConfig(starlightConfig),
47
+ starlightConfig
48
+ };
49
+ }
50
+ /** Generate an Astro i18n configuration based on a Starlight configuration. */
51
+ function getAstroI18nConfig(config) {
52
+ return {
53
+ defaultLocale: (config.defaultLocale.locale === "root" ? config.defaultLocale.lang : config.defaultLocale.locale ?? config.defaultLocale.lang) ?? BuiltInDefaultLocale.lang,
54
+ locales: config.locales ? Object.entries(config.locales).map(([locale, localeConfig]) => {
55
+ return {
56
+ codes: [localeConfig?.lang ?? locale],
57
+ path: locale === "root" ? localeConfig?.lang ?? BuiltInDefaultLocale.lang : locale
58
+ };
59
+ }) : [config.defaultLocale.lang],
60
+ routing: {
61
+ prefixDefaultLocale: config.isMultilingual && config.locales?.root === void 0 || !config.isMultilingual && config.locales !== void 0,
62
+ redirectToDefaultLocale: false,
63
+ fallbackType: "redirect"
64
+ }
65
+ };
66
+ }
67
+ /** Generate a Starlight i18n configuration based on an Astro configuration. */
68
+ function getStarlightI18nConfig(astroI18nConfig) {
69
+ if (astroI18nConfig.routing === "manual") throw new AstroError("Starlight is not compatible with the `manual` routing option in the Astro i18n configuration.");
70
+ const prefixDefaultLocale = astroI18nConfig.routing.prefixDefaultLocale;
71
+ const isMultilingual = astroI18nConfig.locales.length > 1;
72
+ const isMonolingualWithRootLocale = !isMultilingual && !prefixDefaultLocale;
73
+ const locales = isMonolingualWithRootLocale ? void 0 : Object.fromEntries(astroI18nConfig.locales.map((locale) => [isDefaultAstroLocale(astroI18nConfig, locale) && !prefixDefaultLocale ? "root" : isAstroLocaleExtendedConfig(locale) ? locale.path : locale, inferStarlightLocaleFromAstroLocale(locale)]));
74
+ const defaultAstroLocale = astroI18nConfig.locales.find((locale) => isDefaultAstroLocale(astroI18nConfig, locale));
75
+ if (!defaultAstroLocale) throw new AstroError("Astro default locale not found.", "This should never happen. Please open a new issue: https://github.com/withastro/starlight/issues/new?template=---01-bug-report.yml");
76
+ return {
77
+ isMultilingual,
78
+ locales,
79
+ defaultLocale: {
80
+ ...inferStarlightLocaleFromAstroLocale(defaultAstroLocale),
81
+ locale: isMonolingualWithRootLocale || isMultilingual && !prefixDefaultLocale ? void 0 : isAstroLocaleExtendedConfig(defaultAstroLocale) ? defaultAstroLocale.codes[0] : defaultAstroLocale
82
+ }
83
+ };
84
+ }
85
+ /** Infer Starlight locale information based on a locale from an Astro i18n configuration. */
86
+ function inferStarlightLocaleFromAstroLocale(astroLocale) {
87
+ const lang = isAstroLocaleExtendedConfig(astroLocale) ? astroLocale.codes[0] : astroLocale;
88
+ return {
89
+ ...getLocaleInfo(lang),
90
+ lang
91
+ };
92
+ }
93
+ /** Check if the passed locale is the default locale in an Astro i18n configuration. */
94
+ function isDefaultAstroLocale(astroI18nConfig, locale) {
95
+ return (isAstroLocaleExtendedConfig(locale) ? locale.path : locale) === astroI18nConfig.defaultLocale;
96
+ }
97
+ /**
98
+ * Check if the passed Astro locale is using the object variant.
99
+ * @see AstroLocaleExtendedConfig
100
+ */
101
+ function isAstroLocaleExtendedConfig(locale) {
102
+ return typeof locale !== "string";
103
+ }
104
+ /** Returns the locale information such as a label and a direction based on a BCP-47 tag. */
105
+ function getLocaleInfo(lang) {
106
+ try {
107
+ const locale = new Intl.Locale(lang);
108
+ const label = new Intl.DisplayNames(locale, { type: "language" }).of(lang);
109
+ if (!label || lang === label) throw new Error("Label not found.");
110
+ return {
111
+ label: label[0]?.toLocaleUpperCase(locale) + label.slice(1),
112
+ dir: getLocaleDir(locale)
113
+ };
114
+ } catch {
115
+ throw new AstroError(`Failed to get locale information for the '${lang}' locale.`, "Make sure to provide a valid BCP-47 tags (e.g. en, ar, or zh-CN).");
116
+ }
117
+ }
118
+ /**
119
+ * Returns the direction of the passed locale.
120
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo
121
+ */
122
+ function getLocaleDir(locale) {
123
+ if ("textInfo" in locale) return locale.textInfo.direction;
124
+ else if ("getTextInfo" in locale) return locale.getTextInfo().direction;
125
+ return wellKnownRTL.includes(locale.language) ? "rtl" : "ltr";
126
+ }
127
+ /**
128
+ * Get the string for the passed language from a dictionary object.
129
+ *
130
+ * TODO: Make this clever. Currently a simple key look-up, but should use
131
+ * BCP-47 mapping so that e.g. `en-US` returns `en` strings, and use the
132
+ * site’s default locale as a last resort.
133
+ *
134
+ * @example
135
+ * pickLang({ en: 'Hello', fr: 'Bonjour' }, 'en'); // => 'Hello'
136
+ */
137
+ function pickLang(dictionary, lang) {
138
+ return dictionary[lang];
139
+ }
140
+ //#endregion
141
+ export { BuiltInDefaultLocale, pickLang, processI18nConfig };
@@ -0,0 +1,8 @@
1
+ import { AstroConfig } from "astro";
2
+ //#region src/utils/localizedUrl.d.ts
3
+ /**
4
+ * Get the equivalent of the passed URL for the passed locale.
5
+ */
6
+ declare function localizedUrl(url: URL, locale: string | undefined, trailingSlash: AstroConfig['trailingSlash']): URL;
7
+ //#endregion
8
+ export { localizedUrl };
@@ -0,0 +1,28 @@
1
+ import { stripTrailingSlash } from "./path.js";
2
+ import config from "virtual:starlight/user-config";
3
+ //#region src/utils/localizedUrl.ts
4
+ /**
5
+ * Get the equivalent of the passed URL for the passed locale.
6
+ */
7
+ function localizedUrl(url, locale, trailingSlash) {
8
+ url = new URL(url);
9
+ if (!config.locales) return url;
10
+ if (locale === "root") locale = "";
11
+ /** Base URL with trailing `/` stripped. */
12
+ const base = stripTrailingSlash(import.meta.env.BASE_URL);
13
+ const hasBase = url.pathname.startsWith(base);
14
+ if (hasBase) url.pathname = url.pathname.replace(base, "");
15
+ const [_leadingSlash, baseSegment] = url.pathname.split("/");
16
+ const isRootHtml = baseSegment?.endsWith(".html");
17
+ const baseSlug = isRootHtml ? baseSegment?.slice(0, -5) : baseSegment;
18
+ if (baseSlug && baseSlug in config.locales) if (locale) url.pathname = url.pathname.replace(baseSlug, locale);
19
+ else if (isRootHtml) url.pathname = "/index.html";
20
+ else url.pathname = url.pathname.replace("/" + baseSlug, "");
21
+ else if (locale) if (baseSegment === "index.html") url.pathname = "/" + locale + ".html";
22
+ else url.pathname = "/" + locale + url.pathname;
23
+ if (hasBase) url.pathname = base + url.pathname;
24
+ if (trailingSlash === "never") url.pathname = stripTrailingSlash(url.pathname);
25
+ return url;
26
+ }
27
+ //#endregion
28
+ export { localizedUrl };
@@ -0,0 +1,19 @@
1
+ import { StarlightConfig } from "./user-config.js";
2
+ import { PaginationLinks, SidebarEntry, SidebarLink } from "./routing/types.js";
3
+ import { PrevNextLinkConfig } from "../schemas/prevNextLink.js";
4
+ //#region src/utils/navigation.d.ts
5
+ /** Get the sidebar for the current page using the global config. */
6
+ declare function getSidebar(pathname: string, locale: string | undefined): SidebarEntry[];
7
+ /** Get the sidebar for the current page using the specified sidebar config. */
8
+ declare function getSidebarFromConfig(sidebarConfig: StarlightConfig['sidebar'], pathname: string, locale: string | undefined): SidebarEntry[];
9
+ /** Generates a deterministic string based on the content of the passed sidebar. */
10
+ declare function getSidebarHash(sidebar: SidebarEntry[]): string;
11
+ /** Turn the nested tree structure of a sidebar into a flat list of all the links. */
12
+ declare function flattenSidebar(sidebar: SidebarEntry[]): SidebarLink[];
13
+ /** Get previous/next pages in the sidebar or the ones from the frontmatter if any. */
14
+ declare function getPrevNextLinks(sidebar: SidebarEntry[], paginationEnabled: boolean, config: {
15
+ prev?: PrevNextLinkConfig;
16
+ next?: PrevNextLinkConfig;
17
+ }): PaginationLinks;
18
+ //#endregion
19
+ export { flattenSidebar, getPrevNextLinks, getSidebar, getSidebarFromConfig, getSidebarHash };
@@ -0,0 +1,353 @@
1
+ import { getCollectionPathFromRoot } from "./collection.js";
2
+ import { ensureLeadingSlash, ensureTrailingSlash, stripExtension, stripLeadingAndTrailingSlashes } from "./path.js";
3
+ import { BuiltInDefaultLocale, pickLang } from "./i18n.js";
4
+ import { createPathFormatter } from "./createPathFormatter.js";
5
+ import { formatPath } from "./format-path.js";
6
+ import { hasProtocol } from "./url.js";
7
+ import { localeToLang, localizedFilePath, slugToPathname } from "./slugs.js";
8
+ import { getLocaleRoutes, getRouteById } from "./routing/index.js";
9
+ import { AstroError } from "astro/errors";
10
+ import config from "virtual:starlight/user-config";
11
+ import project from "virtual:starlight/project-context";
12
+ //#region src/utils/navigation.ts
13
+ const DirKey = Symbol("DirKey");
14
+ const SlugKey = Symbol("SlugKey");
15
+ const rootAutogenerate = { directory: "" };
16
+ const neverPathFormatter = createPathFormatter({ trailingSlash: "never" });
17
+ const sidebarCollator = new Intl.Collator(localeToLang(void 0));
18
+ const docsCollectionPathFromRoot = getCollectionPathFromRoot("docs", project);
19
+ /** Create a new directory object. */
20
+ function makeDir(slug) {
21
+ const dir = {};
22
+ Object.defineProperty(dir, DirKey, { enumerable: false });
23
+ Object.defineProperty(dir, SlugKey, {
24
+ value: slug,
25
+ enumerable: false
26
+ });
27
+ return dir;
28
+ }
29
+ /** Test if the passed object is a directory record. */
30
+ function isDir(data) {
31
+ return DirKey in data;
32
+ }
33
+ /** Convert an item in a user’s sidebar config to a sidebar entry. */
34
+ function configItemToEntry(item, locale, routes) {
35
+ if ("link" in item) return linkFromSidebarLinkItem(item, locale);
36
+ else if ("autogenerate" in item) return entriesFromAutogenerateConfig(item, locale, routes);
37
+ else if ("slug" in item) return linkFromInternalSidebarLinkItem(item, locale);
38
+ else {
39
+ const label = pickLang(item.translations, localeToLang(locale)) || item.label;
40
+ return {
41
+ type: "group",
42
+ label,
43
+ entries: item.items.flatMap((i) => configItemToEntry(i, locale, routes)),
44
+ collapsed: item.collapsed,
45
+ badge: getSidebarBadge(item.badge, locale, label)
46
+ };
47
+ }
48
+ }
49
+ /** Autogenerate links and groups from a user’s sidebar config. */
50
+ function entriesFromAutogenerateConfig(item, locale, routes) {
51
+ const { attrs, collapsed, directory } = item.autogenerate;
52
+ const localeDir = locale ? locale + "/" + directory : directory;
53
+ const autogenerate = { directory };
54
+ return sidebarFromDir(treeify(routes.filter((doc) => {
55
+ const filePathFromContentDir = getRoutePathRelativeToCollectionRoot(doc, locale);
56
+ return stripExtension(filePathFromContentDir) === localeDir || filePathFromContentDir.startsWith(localeDir + "/");
57
+ }), locale, localeDir), {
58
+ collapsed: collapsed ?? false,
59
+ attrs
60
+ }, autogenerate);
61
+ }
62
+ /** Create a link entry from a manual link item in user config. */
63
+ function linkFromSidebarLinkItem(item, locale) {
64
+ let href = item.link;
65
+ if (!hasProtocol(href)) {
66
+ href = ensureLeadingSlash(href);
67
+ if (locale) href = "/" + locale + href;
68
+ }
69
+ const label = pickLang(item.translations, localeToLang(locale)) || item.label;
70
+ return makeSidebarLink({
71
+ href,
72
+ label,
73
+ badge: getSidebarBadge(item.badge, locale, label),
74
+ attrs: item.attrs
75
+ });
76
+ }
77
+ /** Create a link entry from an automatic internal link item in user config. */
78
+ function linkFromInternalSidebarLinkItem(item, locale) {
79
+ const slug = item.slug === "index" ? "" : item.slug;
80
+ const localizedSlug = locale ? slug ? locale + "/" + slug : locale : slug;
81
+ const route = getRouteById(localizedSlug);
82
+ if (!route) if (item.slug.at(0) === "/" || item.slug.at(-1) === "/") throw new AstroError(`The slug \`"${item.slug}"\` specified in the Starlight sidebar config must not start or end with a slash.`, `Please try updating \`"${item.slug}"\` to \`"${stripLeadingAndTrailingSlashes(item.slug)}"\`.`);
83
+ else throw new AstroError(`The slug \`"${item.slug}"\` specified in the Starlight sidebar config does not exist.`, "Update the Starlight config to reference a valid entry slug in the docs content collection.\nLearn more about Astro content collection slugs at https://docs.astro.build/en/reference/modules/astro-content/#getentry");
84
+ const frontmatter = route.entry.data;
85
+ const label = pickLang(item.translations, localeToLang(locale)) || item.label || frontmatter.sidebar?.label || frontmatter.title;
86
+ const badge = item.badge ?? frontmatter.sidebar?.badge;
87
+ const attrs = {
88
+ ...frontmatter.sidebar?.attrs,
89
+ ...item.attrs
90
+ };
91
+ return makeSidebarLink({
92
+ href: slugToPathname(route.id),
93
+ label,
94
+ badge: getSidebarBadge(badge, locale, label),
95
+ attrs
96
+ });
97
+ }
98
+ function makeSidebarLink({ attrs, badge, href, label, autogenerate }) {
99
+ if (!hasProtocol(href)) href = formatPath(href);
100
+ return makeLink({
101
+ label,
102
+ href,
103
+ badge,
104
+ attrs,
105
+ autogenerate
106
+ });
107
+ }
108
+ /** Create a link entry */
109
+ function makeLink({ attrs = {}, badge, autogenerate, ...opts }) {
110
+ return {
111
+ type: "link",
112
+ ...opts,
113
+ badge,
114
+ isCurrent: false,
115
+ attrs,
116
+ ...autogenerate ? { autogenerate } : {}
117
+ };
118
+ }
119
+ /** Get the segments leading to a page. */
120
+ function getBreadcrumbs(path, baseDir) {
121
+ const pathWithoutExt = stripExtension(path);
122
+ if (pathWithoutExt === baseDir) return [];
123
+ baseDir = ensureTrailingSlash(baseDir);
124
+ return (pathWithoutExt.startsWith(baseDir) ? pathWithoutExt.replace(baseDir, "") : pathWithoutExt).split("/");
125
+ }
126
+ /** Return the path of a route relative to the root of the collection. */
127
+ function getRoutePathRelativeToCollectionRoot(route, locale) {
128
+ return localizedFilePath(route.entry.filePath.replace(`${docsCollectionPathFromRoot}/`, ""), locale);
129
+ }
130
+ /** Turn a flat array of routes into a tree structure. */
131
+ function treeify(routes, locale, baseDir) {
132
+ const treeRoot = makeDir(baseDir);
133
+ routes.filter((doc) => !doc.entry.data.sidebar.hidden).map((doc) => [getRoutePathRelativeToCollectionRoot(doc, locale), doc]).sort(([a], [b]) => b.split("/").length - a.split("/").length).forEach(([filePathFromContentDir, doc]) => {
134
+ const parts = getBreadcrumbs(filePathFromContentDir, baseDir);
135
+ let currentNode = treeRoot;
136
+ parts.forEach((part, index) => {
137
+ const isLeaf = index === parts.length - 1;
138
+ if (isLeaf && Object.hasOwn(currentNode, part)) {
139
+ currentNode = currentNode[part];
140
+ part = "index";
141
+ }
142
+ if (!isLeaf) {
143
+ const path = currentNode[SlugKey];
144
+ currentNode[part] ||= makeDir(stripLeadingAndTrailingSlashes(path + "/" + part));
145
+ currentNode = currentNode[part];
146
+ } else currentNode[part] = doc;
147
+ });
148
+ });
149
+ return treeRoot;
150
+ }
151
+ /** Create a link entry for a given content collection entry. */
152
+ function linkFromRoute(route, attrs, autogenerate) {
153
+ return makeSidebarLink({
154
+ href: slugToPathname(route.id),
155
+ label: route.entry.data.sidebar.label || route.entry.data.title,
156
+ badge: route.entry.data.sidebar.badge,
157
+ attrs: {
158
+ ...attrs,
159
+ ...route.entry.data.sidebar.attrs
160
+ },
161
+ autogenerate
162
+ });
163
+ }
164
+ /**
165
+ * Get the sort weight for a given route or directory. Lower numbers rank higher.
166
+ * Directories have the weight of the lowest weighted route they contain.
167
+ */
168
+ function getOrder(routeOrDir) {
169
+ const cachedOrder = orderByEntry.get(routeOrDir);
170
+ if (cachedOrder !== void 0) return cachedOrder;
171
+ const order = isDir(routeOrDir) ? Math.min(...Object.values(routeOrDir).flatMap(getOrder)) : routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE;
172
+ orderByEntry.set(routeOrDir, order);
173
+ return order;
174
+ }
175
+ const orderByEntry = /* @__PURE__ */ new WeakMap();
176
+ /** Sort a directory’s entries by user-specified order or alphabetically if no order specified. */
177
+ function sortDirEntries(dir) {
178
+ return dir.sort(([_keyA, a], [_keyB, b]) => {
179
+ const [aOrder, bOrder] = [getOrder(a), getOrder(b)];
180
+ if (aOrder !== bOrder) return aOrder < bOrder ? -1 : 1;
181
+ return sidebarCollator.compare(isDir(a) ? a[SlugKey] : a.id, isDir(b) ? b[SlugKey] : b.id);
182
+ });
183
+ }
184
+ /** Create a group entry for a given content collection directory. */
185
+ function groupFromDir(dir, context) {
186
+ const { fullPath, dirName, collapsed, autogenerate } = context;
187
+ return {
188
+ type: "group",
189
+ label: dirName,
190
+ entries: sortDirEntries(Object.entries(dir)).map(([key, dirOrRoute]) => dirToItem(dirOrRoute, {
191
+ ...context,
192
+ fullPath: `${fullPath}/${key}`,
193
+ dirName: key
194
+ })),
195
+ collapsed,
196
+ badge: void 0,
197
+ autogenerate
198
+ };
199
+ }
200
+ /** Create a sidebar entry for a directory or content entry. */
201
+ function dirToItem(dirOrRoute, context) {
202
+ const { attrs, autogenerate } = context;
203
+ return isDir(dirOrRoute) ? groupFromDir(dirOrRoute, context) : linkFromRoute(dirOrRoute, attrs, autogenerate);
204
+ }
205
+ /** Create a sidebar entry for a given content directory. */
206
+ function sidebarFromDir(tree, options, autogenerate = rootAutogenerate) {
207
+ return sortDirEntries(Object.entries(tree)).map(([key, dirOrRoute]) => dirToItem(dirOrRoute, {
208
+ ...options,
209
+ fullPath: key,
210
+ dirName: key,
211
+ autogenerate
212
+ }));
213
+ }
214
+ /**
215
+ * Intermediate sidebar represents sidebar entries generated from the user config for a specific
216
+ * locale. These representations are cached per locale to avoid regenerating them for each page.
217
+ * When generating the final sidebar for a page, the current page entry in the sidebar is marked
218
+ * with `isCurrent` and cached. Subsequent runs then reset the previous current entry before marking
219
+ * the new current page.
220
+ *
221
+ * Sidebars, like all route data, are deep cloned before the data is passed to users for mutation,
222
+ * so optimising with a single mutable object per locale is safe.
223
+ *
224
+ * @see getSidebarFromIntermediateSidebar
225
+ */
226
+ const intermediateSidebars = /* @__PURE__ */ new Map();
227
+ const lastCurrentEntryByLocale = /* @__PURE__ */ new Map();
228
+ /** Get the sidebar for the current page using the global config. */
229
+ function getSidebar(pathname, locale) {
230
+ let intermediateSidebar = intermediateSidebars.get(locale);
231
+ if (!intermediateSidebar) {
232
+ intermediateSidebar = getIntermediateSidebarFromConfig(config.sidebar, locale);
233
+ intermediateSidebars.set(locale, intermediateSidebar);
234
+ }
235
+ setIntermediateSidebarCurrentEntry(intermediateSidebar, pathname, locale);
236
+ return intermediateSidebar;
237
+ }
238
+ /** Get the sidebar for the current page using the specified sidebar config. */
239
+ function getSidebarFromConfig(sidebarConfig, pathname, locale) {
240
+ const sidebar = getIntermediateSidebarFromConfig(sidebarConfig, locale);
241
+ const currentEntry = getSidebarCurrentEntry(sidebar, pathname);
242
+ if (currentEntry) currentEntry.isCurrent = true;
243
+ return sidebar;
244
+ }
245
+ /** Get the intermediate sidebar for a locale using the specified sidebar config. */
246
+ function getIntermediateSidebarFromConfig(sidebarConfig, locale) {
247
+ const routes = getLocaleRoutes(locale);
248
+ if (sidebarConfig) return sidebarConfig.flatMap((group) => configItemToEntry(group, locale, routes));
249
+ else return sidebarFromDir(treeify(routes, locale, locale || ""), {
250
+ collapsed: false,
251
+ attrs: void 0
252
+ });
253
+ }
254
+ /** Marks the current page in an intermediate sidebar. */
255
+ function setIntermediateSidebarCurrentEntry(intermediateSidebar, pathname, locale) {
256
+ const lastCurrentEntry = lastCurrentEntryByLocale.get(locale);
257
+ if (lastCurrentEntry) lastCurrentEntry.isCurrent = false;
258
+ const entry = getSidebarCurrentEntry(intermediateSidebar, pathname);
259
+ if (entry) {
260
+ entry.isCurrent = true;
261
+ lastCurrentEntryByLocale.set(locale, entry);
262
+ }
263
+ }
264
+ /** Finds the current page in a sidebar. */
265
+ function getSidebarCurrentEntry(sidebar, pathname) {
266
+ let entriesByPath = sidebarEntriesByPath.get(sidebar);
267
+ if (!entriesByPath) {
268
+ entriesByPath = /* @__PURE__ */ new Map();
269
+ for (const entry of flattenSidebar(sidebar)) {
270
+ const path = neverPathFormatter(encodeURI(entry.href));
271
+ if (!entriesByPath.has(path)) entriesByPath.set(path, entry);
272
+ }
273
+ sidebarEntriesByPath.set(sidebar, entriesByPath);
274
+ }
275
+ return entriesByPath.get(neverPathFormatter(pathname)) ?? null;
276
+ }
277
+ const sidebarEntriesByPath = /* @__PURE__ */ new WeakMap();
278
+ /** Generates a deterministic string based on the content of the passed sidebar. */
279
+ function getSidebarHash(sidebar) {
280
+ let hash = 0;
281
+ const sidebarIdentity = recursivelyBuildSidebarIdentity(sidebar);
282
+ for (let i = 0; i < sidebarIdentity.length; i++) {
283
+ const char = sidebarIdentity.charCodeAt(i);
284
+ hash = (hash << 5) - hash + char;
285
+ }
286
+ return (hash >>> 0).toString(36).padStart(7, "0");
287
+ }
288
+ /** Recurses through a sidebar tree to generate a string concatenating labels and link hrefs. */
289
+ function recursivelyBuildSidebarIdentity(sidebar) {
290
+ return sidebar.flatMap((entry) => entry.type === "group" ? entry.label + recursivelyBuildSidebarIdentity(entry.entries) : entry.label + entry.href).join("");
291
+ }
292
+ /** Turn the nested tree structure of a sidebar into a flat list of all the links. */
293
+ function flattenSidebar(sidebar) {
294
+ const cachedSidebar = flattenedSidebars.get(sidebar);
295
+ if (cachedSidebar) return cachedSidebar;
296
+ const flattenedSidebar = sidebar.flatMap((entry) => entry.type === "group" ? flattenSidebar(entry.entries) : entry);
297
+ flattenedSidebars.set(sidebar, flattenedSidebar);
298
+ return flattenedSidebar;
299
+ }
300
+ const flattenedSidebars = /* @__PURE__ */ new WeakMap();
301
+ /** Get previous/next pages in the sidebar or the ones from the frontmatter if any. */
302
+ function getPrevNextLinks(sidebar, paginationEnabled, config) {
303
+ const entries = flattenSidebar(sidebar);
304
+ const currentIndex = entries.findIndex((entry) => entry.isCurrent);
305
+ return {
306
+ prev: applyPrevNextLinkConfig(entries[currentIndex - 1], paginationEnabled, config.prev),
307
+ next: applyPrevNextLinkConfig(currentIndex > -1 ? entries[currentIndex + 1] : void 0, paginationEnabled, config.next)
308
+ };
309
+ }
310
+ /** Apply a prev/next link config to a navigation link. */
311
+ function applyPrevNextLinkConfig(link, paginationEnabled, config) {
312
+ if (config === false) return void 0;
313
+ else if (config === true) return link;
314
+ else if (typeof config === "string" && link) return {
315
+ ...link,
316
+ label: config
317
+ };
318
+ else if (typeof config === "object") {
319
+ if (link) return {
320
+ ...link,
321
+ label: config.label ?? link.label,
322
+ href: config.link ?? link.href,
323
+ attrs: {}
324
+ };
325
+ else if (config.link && config.label) return makeLink({
326
+ href: config.link,
327
+ label: config.label
328
+ });
329
+ }
330
+ return paginationEnabled ? link : void 0;
331
+ }
332
+ /** Get a sidebar badge for a given item. */
333
+ function getSidebarBadge(config, locale, itemLabel) {
334
+ if (!config) return;
335
+ if (typeof config === "string") return {
336
+ variant: "default",
337
+ text: config
338
+ };
339
+ return {
340
+ ...config,
341
+ text: getSidebarBadgeText(config.text, locale, itemLabel)
342
+ };
343
+ }
344
+ /** Get the badge text for a sidebar item. */
345
+ function getSidebarBadgeText(text, locale, itemLabel) {
346
+ if (typeof text === "string") return text;
347
+ const defaultLang = config.defaultLocale?.lang || config.defaultLocale?.locale || BuiltInDefaultLocale.lang;
348
+ const defaultText = text[defaultLang];
349
+ if (!defaultText) throw new AstroError(`The badge text for "${itemLabel}" must have a key for the default language "${defaultLang}".`, "Update the Starlight config to include a badge text for the default language.\nLearn more about sidebar badges internationalization at https://starlight.astro.build/guides/sidebar/#internationalization-with-badges");
350
+ return pickLang(text, localeToLang(locale)) || defaultText;
351
+ }
352
+ //#endregion
353
+ export { flattenSidebar, getPrevNextLinks, getSidebar, getSidebarFromConfig, getSidebarHash };
@@ -0,0 +1,21 @@
1
+ //#region src/utils/path.d.ts
2
+ /** Ensure the passed path starts with a leading slash. */
3
+ declare function ensureLeadingSlash(href: string): string;
4
+ /** Ensure the passed path ends with a trailing slash. */
5
+ declare function ensureTrailingSlash(href: string): string;
6
+ /** Ensure the passed path starts and ends with slashes. */
7
+ declare function ensureLeadingAndTrailingSlashes(href: string): string;
8
+ /** Ensure the passed path does not start with a leading slash. */
9
+ declare function stripLeadingSlash(href: string): string;
10
+ /** Ensure the passed path does not end with a trailing slash. */
11
+ declare function stripTrailingSlash(href: string): string;
12
+ /** Ensure the passed path does not start and end with slashes. */
13
+ declare function stripLeadingAndTrailingSlashes(href: string): string;
14
+ /** Remove the extension from a path. */
15
+ declare function stripHtmlExtension(path: string): string;
16
+ /** Add '.html' extension to a path. */
17
+ declare function ensureHtmlExtension(path: string): string;
18
+ /** Remove the extension from a path. */
19
+ declare function stripExtension(path: string): string;
20
+ //#endregion
21
+ export { ensureHtmlExtension, ensureLeadingAndTrailingSlashes, ensureLeadingSlash, ensureTrailingSlash, stripExtension, stripHtmlExtension, stripLeadingAndTrailingSlashes, stripLeadingSlash, stripTrailingSlash };
@@ -0,0 +1,51 @@
1
+ //#region src/utils/path.ts
2
+ /** Ensure the passed path starts with a leading slash. */
3
+ function ensureLeadingSlash(href) {
4
+ if (href[0] !== "/") href = "/" + href;
5
+ return href;
6
+ }
7
+ /** Ensure the passed path ends with a trailing slash. */
8
+ function ensureTrailingSlash(href) {
9
+ if (href[href.length - 1] !== "/") href += "/";
10
+ return href;
11
+ }
12
+ /** Ensure the passed path starts and ends with slashes. */
13
+ function ensureLeadingAndTrailingSlashes(href) {
14
+ href = ensureLeadingSlash(href);
15
+ href = ensureTrailingSlash(href);
16
+ return href;
17
+ }
18
+ /** Ensure the passed path does not start with a leading slash. */
19
+ function stripLeadingSlash(href) {
20
+ if (href[0] === "/") href = href.slice(1);
21
+ return href;
22
+ }
23
+ /** Ensure the passed path does not end with a trailing slash. */
24
+ function stripTrailingSlash(href) {
25
+ if (href[href.length - 1] === "/") href = href.slice(0, -1);
26
+ return href;
27
+ }
28
+ /** Ensure the passed path does not start and end with slashes. */
29
+ function stripLeadingAndTrailingSlashes(href) {
30
+ href = stripLeadingSlash(href);
31
+ href = stripTrailingSlash(href);
32
+ return href;
33
+ }
34
+ /** Remove the extension from a path. */
35
+ function stripHtmlExtension(path) {
36
+ const pathWithoutTrailingSlash = stripTrailingSlash(path);
37
+ return pathWithoutTrailingSlash.endsWith(".html") ? pathWithoutTrailingSlash.slice(0, -5) : path;
38
+ }
39
+ /** Add '.html' extension to a path. */
40
+ function ensureHtmlExtension(path) {
41
+ path = stripLeadingAndTrailingSlashes(path);
42
+ if (!path.endsWith(".html")) path = path ? path + ".html" : "/index.html";
43
+ return ensureLeadingSlash(path);
44
+ }
45
+ /** Remove the extension from a path. */
46
+ function stripExtension(path) {
47
+ const periodIndex = path.lastIndexOf(".");
48
+ return path.slice(0, periodIndex > -1 ? periodIndex : void 0);
49
+ }
50
+ //#endregion
51
+ export { ensureHtmlExtension, ensureLeadingAndTrailingSlashes, ensureLeadingSlash, ensureTrailingSlash, stripExtension, stripHtmlExtension, stripLeadingAndTrailingSlashes, stripLeadingSlash, stripTrailingSlash };