livemark 0.25.0 → 0.26.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 (397) hide show
  1. package/README.md +3 -2
  2. package/build/actions/config/define.d.ts +6 -0
  3. package/build/actions/config/define.unit.js +8 -1
  4. package/build/actions/escape/copy.d.ts +11 -0
  5. package/build/actions/escape/copy.js +29 -0
  6. package/build/actions/escape/copy.unit.d.ts +1 -0
  7. package/build/actions/escape/copy.unit.js +37 -0
  8. package/build/actions/escape/list.d.ts +12 -0
  9. package/build/actions/escape/list.js +27 -0
  10. package/build/actions/escape/list.unit.d.ts +1 -0
  11. package/build/actions/escape/list.unit.js +36 -0
  12. package/build/actions/target/build.d.ts +9 -26
  13. package/build/actions/target/build.js +50 -71
  14. package/build/actions/target/build.unit.d.ts +1 -0
  15. package/build/actions/target/build.unit.js +76 -0
  16. package/build/actions/target/clear.d.ts +4 -0
  17. package/build/actions/target/clear.js +14 -0
  18. package/build/actions/target/clear.unit.d.ts +1 -0
  19. package/build/actions/target/clear.unit.js +23 -0
  20. package/build/commands/build.js +1 -2
  21. package/build/commands/clear.d.ts +5 -0
  22. package/build/commands/clear.js +15 -0
  23. package/build/commands/escape.d.ts +4 -3
  24. package/build/commands/escape.js +45 -48
  25. package/build/commands/preview.js +1 -2
  26. package/build/commands/start.js +1 -2
  27. package/build/components/Abbr.d.ts +1 -1
  28. package/build/components/Abbr.js +2 -4
  29. package/build/components/AnsiCode.d.ts +1 -1
  30. package/build/components/AnsiCode.js +2 -2
  31. package/build/components/Article.d.ts +2 -1
  32. package/build/components/Article.js +7 -14
  33. package/build/components/BackToTop.d.ts +1 -1
  34. package/build/components/Banner.d.ts +2 -2
  35. package/build/components/Banner.js +7 -3
  36. package/build/components/BlogIndex.d.ts +1 -1
  37. package/build/components/BlogIndex.js +2 -11
  38. package/build/components/Breadcrumbs.d.ts +1 -1
  39. package/build/components/Breadcrumbs.js +2 -3
  40. package/build/components/Callout.d.ts +1 -1
  41. package/build/components/Callout.js +5 -9
  42. package/build/components/Card.d.ts +1 -1
  43. package/build/components/Card.js +2 -3
  44. package/build/components/Cards.d.ts +1 -1
  45. package/build/components/ChangelogIndex.d.ts +1 -1
  46. package/build/components/ChangelogIndex.js +2 -11
  47. package/build/components/ChoiceList.d.ts +15 -0
  48. package/build/components/ChoiceList.js +13 -0
  49. package/build/components/CodeBlock.d.ts +1 -1
  50. package/build/components/CodeBlock.js +3 -16
  51. package/build/components/CodeTabs.d.ts +1 -1
  52. package/build/components/CodeTabs.js +2 -3
  53. package/build/components/Column.d.ts +1 -1
  54. package/build/components/Columns.d.ts +1 -1
  55. package/build/components/Content.d.ts +1 -1
  56. package/build/components/ContentTab.d.ts +1 -1
  57. package/build/components/ContentTabs.d.ts +1 -1
  58. package/build/components/ContentTabs.js +2 -3
  59. package/build/components/DefaultCatchBoundary.d.ts +1 -1
  60. package/build/components/DefaultCatchBoundary.js +5 -7
  61. package/build/components/DefinitionList.d.ts +3 -3
  62. package/build/components/Details.d.ts +1 -1
  63. package/build/components/Details.js +2 -5
  64. package/build/components/FileTree.d.ts +1 -1
  65. package/build/components/FileTree.js +3 -5
  66. package/build/components/Footer.d.ts +1 -1
  67. package/build/components/Footer.js +2 -5
  68. package/build/components/FootnoteRef.d.ts +1 -1
  69. package/build/components/FootnoteRef.js +2 -4
  70. package/build/components/Header.d.ts +6 -0
  71. package/build/components/Header.js +26 -0
  72. package/build/components/HeaderMenu.d.ts +2 -0
  73. package/build/components/HeaderMenu.js +27 -0
  74. package/build/components/HeaderNav.d.ts +6 -0
  75. package/build/components/HeaderNav.js +74 -0
  76. package/build/components/HeaderSearch.d.ts +4 -0
  77. package/build/components/HeaderSearch.js +33 -0
  78. package/build/components/Heading.d.ts +6 -6
  79. package/build/components/InlineBadge.d.ts +2 -2
  80. package/build/components/InlineBadge.js +1 -1
  81. package/build/components/InlineIcon.d.ts +1 -1
  82. package/build/components/InlineToc.d.ts +1 -1
  83. package/build/components/InlineToc.js +2 -4
  84. package/build/components/Layout.d.ts +2 -1
  85. package/build/components/Layout.js +5 -58
  86. package/build/components/LinkButton.d.ts +2 -2
  87. package/build/components/LinkButton.js +1 -1
  88. package/build/components/MenuSheet.d.ts +22 -0
  89. package/build/components/MenuSheet.js +27 -0
  90. package/build/components/Mermaid.d.ts +1 -1
  91. package/build/components/MermaidRenderer.d.ts +1 -1
  92. package/build/components/MermaidRenderer.js +20 -8
  93. package/build/components/NotFound.d.ts +1 -1
  94. package/build/components/NotFound.js +3 -6
  95. package/build/components/PackageTabs.d.ts +1 -1
  96. package/build/components/PackageTabs.js +3 -7
  97. package/build/components/PageToolbar.d.ts +1 -1
  98. package/build/components/PageToolbar.js +2 -10
  99. package/build/components/PrevNext.d.ts +1 -1
  100. package/build/components/PrevNext.js +2 -10
  101. package/build/components/Root.d.ts +4 -0
  102. package/build/components/Root.js +8 -0
  103. package/build/components/Search.d.ts +5 -2
  104. package/build/components/Search.js +11 -9
  105. package/build/components/SearchDialog.d.ts +1 -1
  106. package/build/components/SearchDialog.js +10 -133
  107. package/build/components/Section.d.ts +1 -1
  108. package/build/components/SectionHeader.d.ts +1 -1
  109. package/build/components/SheetPanel.d.ts +12 -0
  110. package/build/components/SheetPanel.js +19 -0
  111. package/build/components/Sidebar.d.ts +1 -1
  112. package/build/components/Sidebar.js +12 -14
  113. package/build/components/SidebarArticles.d.ts +4 -1
  114. package/build/components/SidebarArticles.js +5 -9
  115. package/build/components/SidebarLinks.d.ts +4 -1
  116. package/build/components/SidebarLinks.js +6 -9
  117. package/build/components/SidebarPosts.d.ts +4 -1
  118. package/build/components/SidebarPosts.js +7 -23
  119. package/build/components/SidebarReleases.d.ts +4 -1
  120. package/build/components/SidebarReleases.js +5 -15
  121. package/build/components/SidebarSectionPicker.d.ts +8 -0
  122. package/build/components/SidebarSectionPicker.js +31 -0
  123. package/build/components/SidebarSections.d.ts +1 -1
  124. package/build/components/SidebarSections.js +5 -9
  125. package/build/components/SiteLink.d.ts +1 -1
  126. package/build/components/SiteTitle.d.ts +1 -1
  127. package/build/components/SiteTitle.js +2 -6
  128. package/build/components/SortableTable.d.ts +1 -1
  129. package/build/components/SoundCloud.d.ts +1 -1
  130. package/build/components/SoundCloud.js +2 -2
  131. package/build/components/TagIndex.d.ts +1 -1
  132. package/build/components/TagIndex.js +2 -11
  133. package/build/components/Theme.d.ts +2 -1
  134. package/build/components/Theme.js +35 -15
  135. package/build/components/Toc.d.ts +5 -4
  136. package/build/components/Toc.js +35 -35
  137. package/build/components/YouTube.d.ts +1 -1
  138. package/build/components/YouTube.js +2 -2
  139. package/build/components/ZoomImage.d.ts +1 -1
  140. package/build/content-collections.js +5 -1
  141. package/build/elements/accordion.d.ts +4 -4
  142. package/build/elements/accordion.js +2 -3
  143. package/build/elements/alert-dialog.d.ts +12 -12
  144. package/build/elements/alert-dialog.js +2 -4
  145. package/build/elements/alert.d.ts +4 -4
  146. package/build/elements/alert.js +2 -2
  147. package/build/elements/aspect-ratio.d.ts +1 -1
  148. package/build/elements/avatar.d.ts +6 -6
  149. package/build/elements/badge.d.ts +1 -1
  150. package/build/elements/badge.js +3 -1
  151. package/build/elements/breadcrumb.d.ts +6 -6
  152. package/build/elements/breadcrumb.js +2 -4
  153. package/build/elements/button-group.d.ts +2 -2
  154. package/build/elements/button-group.js +5 -5
  155. package/build/elements/button.d.ts +2 -2
  156. package/build/elements/button.js +9 -7
  157. package/build/elements/calendar.d.ts +2 -2
  158. package/build/elements/calendar.js +2 -2
  159. package/build/elements/card.d.ts +7 -7
  160. package/build/elements/card.js +4 -4
  161. package/build/elements/carousel.d.ts +5 -5
  162. package/build/elements/carousel.js +3 -7
  163. package/build/elements/chart.d.ts +6 -6
  164. package/build/elements/chart.js +5 -11
  165. package/build/elements/checkbox.d.ts +1 -1
  166. package/build/elements/collapsible.d.ts +3 -3
  167. package/build/elements/command.d.ts +9 -9
  168. package/build/elements/command.js +5 -11
  169. package/build/elements/context-menu.d.ts +15 -15
  170. package/build/elements/context-menu.js +6 -9
  171. package/build/elements/dialog.d.ts +10 -10
  172. package/build/elements/dialog.js +2 -6
  173. package/build/elements/drawer.d.ts +14 -12
  174. package/build/elements/drawer.js +14 -15
  175. package/build/elements/dropdown-menu.d.ts +15 -15
  176. package/build/elements/dropdown-menu.js +7 -10
  177. package/build/elements/empty.d.ts +6 -6
  178. package/build/elements/empty.js +2 -2
  179. package/build/elements/field.d.ts +10 -10
  180. package/build/elements/field.js +3 -4
  181. package/build/elements/hover-card.d.ts +3 -3
  182. package/build/elements/hover-card.js +2 -2
  183. package/build/elements/input-group.d.ts +7 -7
  184. package/build/elements/input-group.js +5 -5
  185. package/build/elements/input-otp.d.ts +4 -4
  186. package/build/elements/input.d.ts +1 -1
  187. package/build/elements/input.js +2 -2
  188. package/build/elements/item.d.ts +9 -9
  189. package/build/elements/item.js +2 -2
  190. package/build/elements/kbd.d.ts +2 -2
  191. package/build/elements/label.d.ts +1 -1
  192. package/build/elements/menubar.d.ts +16 -16
  193. package/build/elements/menubar.js +9 -11
  194. package/build/elements/native-select.d.ts +3 -3
  195. package/build/elements/native-select.js +2 -4
  196. package/build/elements/navigation-menu.d.ts +8 -8
  197. package/build/elements/navigation-menu.js +3 -5
  198. package/build/elements/pagination.d.ts +7 -7
  199. package/build/elements/pagination.js +4 -10
  200. package/build/elements/popover.d.ts +6 -6
  201. package/build/elements/popover.js +2 -2
  202. package/build/elements/progress.d.ts +5 -5
  203. package/build/elements/progress.js +2 -3
  204. package/build/elements/radio-group.d.ts +2 -2
  205. package/build/elements/resizable.d.ts +3 -3
  206. package/build/elements/scroll-area.d.ts +2 -2
  207. package/build/elements/scroll-area.js +2 -4
  208. package/build/elements/select.d.ts +9 -9
  209. package/build/elements/select.js +4 -9
  210. package/build/elements/separator.d.ts +1 -1
  211. package/build/elements/sheet.d.ts +8 -8
  212. package/build/elements/sheet.js +2 -6
  213. package/build/elements/sidebar.d.ts +19 -19
  214. package/build/elements/sidebar.js +15 -37
  215. package/build/elements/skeleton.d.ts +1 -1
  216. package/build/elements/slider.d.ts +2 -1
  217. package/build/elements/slider.js +2 -3
  218. package/build/elements/sonner.d.ts +1 -1
  219. package/build/elements/spinner.d.ts +1 -1
  220. package/build/elements/switch.d.ts +1 -1
  221. package/build/elements/table.d.ts +8 -8
  222. package/build/elements/tabs.d.ts +4 -4
  223. package/build/elements/tabs.js +3 -3
  224. package/build/elements/textarea.d.ts +1 -1
  225. package/build/elements/textarea.js +2 -2
  226. package/build/elements/toggle-group.d.ts +3 -2
  227. package/build/elements/toggle-group.js +3 -3
  228. package/build/elements/toggle.d.ts +1 -1
  229. package/build/elements/toggle.js +2 -2
  230. package/build/elements/tooltip.d.ts +4 -4
  231. package/build/elements/tooltip.js +2 -3
  232. package/build/head.d.ts +4 -0
  233. package/build/head.js +6 -0
  234. package/build/helpers/article-search.d.ts +19 -0
  235. package/build/helpers/article-search.js +134 -0
  236. package/build/helpers/dependency-dir.d.ts +5 -0
  237. package/build/helpers/dependency-dir.js +20 -0
  238. package/build/helpers/dependency-dir.unit.d.ts +1 -0
  239. package/build/helpers/dependency-dir.unit.js +25 -0
  240. package/build/helpers/dynamic-icon-resolver.d.ts +1 -1
  241. package/build/helpers/dynamic-icon.d.ts +1 -1
  242. package/build/helpers/head.d.ts +53 -0
  243. package/build/helpers/head.js +69 -0
  244. package/build/helpers/head.unit.d.ts +1 -0
  245. package/build/helpers/head.unit.js +108 -0
  246. package/build/helpers/nav-items.d.ts +11 -0
  247. package/build/helpers/nav-items.js +65 -0
  248. package/build/helpers/render-inline-markdown.d.ts +1 -0
  249. package/build/helpers/render-inline-markdown.js +34 -0
  250. package/build/helpers/render-inline-markdown.unit.d.ts +1 -0
  251. package/build/helpers/render-inline-markdown.unit.js +20 -0
  252. package/build/helpers/search-highlight.d.ts +8 -0
  253. package/build/helpers/search-highlight.js +59 -0
  254. package/build/helpers/search-highlight.unit.d.ts +1 -0
  255. package/build/helpers/search-highlight.unit.js +36 -0
  256. package/build/helpers/target-export.d.ts +9 -0
  257. package/build/helpers/target-export.js +24 -0
  258. package/build/helpers/target-export.unit.d.ts +1 -0
  259. package/build/helpers/target-export.unit.js +25 -0
  260. package/build/helpers/theme.d.ts +6 -2
  261. package/build/helpers/theme.js +40 -7
  262. package/build/helpers/theme.unit.d.ts +1 -0
  263. package/build/helpers/theme.unit.js +30 -0
  264. package/build/hooks/hydrated.d.ts +2 -0
  265. package/build/hooks/hydrated.js +15 -0
  266. package/build/index.d.ts +1 -0
  267. package/build/index.js +1 -1
  268. package/build/models/config.d.ts +32 -6
  269. package/build/models/config.js +10 -1
  270. package/build/models/section.d.ts +4 -2
  271. package/build/models/section.js +1 -1
  272. package/build/plugins/vite-livemark.d.ts +4 -5
  273. package/build/plugins/vite-livemark.js +56 -90
  274. package/build/program.js +4 -2
  275. package/build/routes/$.d.ts +4 -1
  276. package/build/routes/$.js +20 -9
  277. package/build/routes/__root.js +29 -63
  278. package/build/settings.js +2 -1
  279. package/package.json +68 -66
  280. package/{.agents/skills → skills}/livemark-authoring/SKILL.md +2 -2
  281. package/{.agents/skills → skills}/livemark-configuration/SKILL.md +12 -5
  282. package/skills/livemark-customization/SKILL.md +145 -0
  283. package/source/actions/config/define.unit.ts +9 -0
  284. package/source/actions/escape/copy.ts +35 -0
  285. package/source/actions/escape/copy.unit.ts +51 -0
  286. package/source/actions/escape/list.ts +30 -0
  287. package/source/actions/escape/list.unit.ts +42 -0
  288. package/source/actions/target/build.ts +49 -69
  289. package/source/actions/target/build.unit.ts +95 -0
  290. package/source/actions/target/clear.ts +14 -0
  291. package/source/actions/target/clear.unit.ts +25 -0
  292. package/source/commands/build.ts +0 -1
  293. package/source/commands/clear.ts +15 -0
  294. package/source/commands/escape.ts +42 -59
  295. package/source/commands/preview.ts +0 -1
  296. package/source/commands/start.ts +0 -1
  297. package/source/components/AnsiCode.tsx +1 -1
  298. package/source/components/Article.tsx +8 -4
  299. package/source/components/Banner.tsx +12 -2
  300. package/source/components/BlogIndex.tsx +1 -1
  301. package/source/components/Callout.tsx +4 -6
  302. package/source/components/ChangelogIndex.tsx +1 -1
  303. package/source/components/ChoiceList.tsx +69 -0
  304. package/source/components/CodeBlock.tsx +6 -6
  305. package/source/components/CodeTabs.tsx +1 -1
  306. package/source/components/ContentTabs.tsx +1 -1
  307. package/source/components/DefaultCatchBoundary.tsx +4 -6
  308. package/source/components/Details.tsx +1 -1
  309. package/source/components/FileTree.tsx +1 -1
  310. package/source/components/Header.tsx +52 -0
  311. package/source/components/HeaderMenu.tsx +41 -0
  312. package/source/components/HeaderNav.tsx +145 -0
  313. package/source/components/HeaderSearch.tsx +77 -0
  314. package/source/components/InlineBadge.tsx +1 -1
  315. package/source/components/InlineToc.tsx +1 -1
  316. package/source/components/Layout.tsx +16 -160
  317. package/source/components/LinkButton.tsx +9 -1
  318. package/source/components/MenuSheet.tsx +92 -0
  319. package/source/components/MermaidRenderer.tsx +19 -8
  320. package/source/components/NotFound.tsx +3 -5
  321. package/source/components/PackageTabs.tsx +2 -2
  322. package/source/components/PageToolbar.tsx +11 -3
  323. package/source/components/PrevNext.tsx +2 -2
  324. package/source/components/Root.tsx +13 -0
  325. package/source/components/Search.tsx +28 -8
  326. package/source/components/SearchDialog.tsx +15 -189
  327. package/source/components/SheetPanel.tsx +69 -0
  328. package/source/components/Sidebar.tsx +27 -14
  329. package/source/components/SidebarArticles.tsx +4 -3
  330. package/source/components/SidebarLinks.tsx +3 -2
  331. package/source/components/SidebarPosts.tsx +3 -2
  332. package/source/components/SidebarReleases.tsx +3 -2
  333. package/source/components/SidebarSectionPicker.tsx +70 -0
  334. package/source/components/SiteTitle.tsx +5 -5
  335. package/source/components/SoundCloud.tsx +1 -1
  336. package/source/components/TagIndex.tsx +1 -1
  337. package/source/components/Theme.tsx +55 -29
  338. package/source/components/Toc.tsx +76 -55
  339. package/source/components/YouTube.tsx +1 -1
  340. package/source/content-collections.ts +4 -0
  341. package/source/elements/alert-dialog.tsx +1 -1
  342. package/source/elements/alert.tsx +1 -1
  343. package/source/elements/badge.tsx +4 -0
  344. package/source/elements/button-group.tsx +4 -4
  345. package/source/elements/button.tsx +10 -6
  346. package/source/elements/calendar.tsx +1 -1
  347. package/source/elements/card.tsx +3 -3
  348. package/source/elements/command.tsx +7 -4
  349. package/source/elements/context-menu.tsx +5 -5
  350. package/source/elements/dialog.tsx +1 -1
  351. package/source/elements/drawer.tsx +59 -43
  352. package/source/elements/dropdown-menu.tsx +6 -6
  353. package/source/elements/empty.tsx +1 -1
  354. package/source/elements/field.tsx +1 -1
  355. package/source/elements/hover-card.tsx +1 -1
  356. package/source/elements/input-group.tsx +4 -4
  357. package/source/elements/input.tsx +1 -1
  358. package/source/elements/item.tsx +1 -1
  359. package/source/elements/menubar.tsx +8 -8
  360. package/source/elements/native-select.tsx +1 -1
  361. package/source/elements/popover.tsx +1 -1
  362. package/source/elements/select.tsx +3 -3
  363. package/source/elements/sidebar.tsx +8 -21
  364. package/source/elements/tabs.tsx +2 -2
  365. package/source/elements/textarea.tsx +1 -1
  366. package/source/elements/toggle-group.tsx +2 -2
  367. package/source/elements/toggle.tsx +1 -1
  368. package/source/env.d.ts +1 -0
  369. package/source/head.ts +7 -0
  370. package/source/helpers/article-search.tsx +192 -0
  371. package/source/helpers/dependency-dir.ts +20 -0
  372. package/source/helpers/dependency-dir.unit.ts +39 -0
  373. package/source/helpers/head.ts +94 -0
  374. package/source/helpers/head.unit.ts +116 -0
  375. package/source/helpers/nav-items.tsx +102 -0
  376. package/source/helpers/render-inline-markdown.ts +44 -0
  377. package/source/helpers/render-inline-markdown.unit.ts +30 -0
  378. package/source/helpers/search-highlight.ts +73 -0
  379. package/source/helpers/search-highlight.unit.ts +42 -0
  380. package/source/helpers/target-export.ts +28 -0
  381. package/source/helpers/target-export.unit.ts +37 -0
  382. package/source/helpers/theme.ts +40 -6
  383. package/source/helpers/theme.unit.ts +32 -0
  384. package/source/hooks/hydrated.ts +18 -0
  385. package/source/index.ts +1 -0
  386. package/source/models/config.ts +13 -0
  387. package/source/models/section.ts +3 -0
  388. package/source/plugins/vite-livemark.ts +54 -95
  389. package/source/program.ts +2 -0
  390. package/source/routes/$.tsx +27 -9
  391. package/source/routes/__root.tsx +51 -71
  392. package/source/settings.ts +1 -0
  393. package/source/styles/general.css +59 -11
  394. package/source/styles/markdown.css +13 -7
  395. package/source/styles/shape.css +14 -0
  396. package/.agents/skills/change-review/SKILL.md +0 -47
  397. package/.agents/skills/livemark-customization/SKILL.md +0 -118
@@ -0,0 +1,69 @@
1
+ import { faviconType } from "./favicon.js";
2
+ import { prefixUrl } from "./prefix-url.js";
3
+ import { buildThemeScript } from "./theme.js";
4
+ export function buildRootHead(props) {
5
+ const config = props.config;
6
+ const favicon = prefixUrl(config.favicon ?? config.logo ?? props.defaultFavicon, config.base);
7
+ const feedLinks = config.site
8
+ ? (config.sections ?? [])
9
+ .filter(s => s.type === "blog")
10
+ .map(s => ({
11
+ rel: "alternate",
12
+ type: "application/rss+xml",
13
+ title: `${s.siteTitle ?? s.title} RSS Feed`,
14
+ href: prefixUrl(`${s.prefix}rss.xml`, config.base),
15
+ }))
16
+ : [];
17
+ return {
18
+ meta: [
19
+ { charSet: "utf-8" },
20
+ { title: config.title },
21
+ { name: "description", content: config.description },
22
+ { property: "og:title", content: config.title },
23
+ { property: "og:description", content: config.description },
24
+ { property: "og:site_name", content: config.title },
25
+ { property: "og:type", content: "website" },
26
+ { name: "viewport", content: "width=device-width, initial-scale=1" },
27
+ ...(config.head?.meta ?? []),
28
+ ],
29
+ links: [
30
+ { rel: "icon", href: favicon, type: faviconType(favicon) },
31
+ { rel: "shortcut icon", href: favicon, type: faviconType(favicon) },
32
+ ...props.stylesheets.map(href => ({ rel: "stylesheet", href })),
33
+ ...feedLinks,
34
+ ...(config.head?.links ?? []),
35
+ ],
36
+ scripts: [{ children: buildThemeScript() }, ...(config.head?.scripts ?? [])],
37
+ };
38
+ }
39
+ export function buildPageHead(props) {
40
+ const site = props.config.site?.replace(/\/+$/, "");
41
+ const url = site ? buildAbsoluteUrl(site, props.config.base, props.path) : undefined;
42
+ const image = site && props.image
43
+ ? buildAbsoluteUrl(site, props.config.base, props.image)
44
+ : undefined;
45
+ return {
46
+ meta: [
47
+ ...(props.title
48
+ ? [{ title: props.title }, { property: "og:title", content: props.title }]
49
+ : []),
50
+ ...(props.description
51
+ ? [
52
+ { name: "description", content: props.description },
53
+ { property: "og:description", content: props.description },
54
+ ]
55
+ : []),
56
+ ...(props.isArticle ? [{ property: "og:type", content: "article" }] : []),
57
+ ...(url ? [{ property: "og:url", content: url }] : []),
58
+ ...(image ? [{ property: "og:image", content: image }] : []),
59
+ ],
60
+ links: url ? [{ rel: "canonical", href: url }] : [],
61
+ };
62
+ }
63
+ function buildAbsoluteUrl(site, base, url) {
64
+ const prefixed = prefixUrl(url, base);
65
+ if (!prefixed.startsWith("/") || prefixed.startsWith("//"))
66
+ return prefixed;
67
+ return `${site}${prefixed}`;
68
+ }
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL2hlYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUMxQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDM0MsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFBO0FBUzdDLE1BQU0sVUFBVSxhQUFhLENBQUMsS0FJN0I7SUFDQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFBO0lBQzNCLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FDdkIsTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxjQUFjLEVBQ3JELE1BQU0sQ0FBQyxJQUFJLENBQ1osQ0FBQTtJQUNELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJO1FBQzNCLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO2FBQ3BCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDO2FBQzlCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDVCxHQUFHLEVBQUUsV0FBVztZQUNoQixJQUFJLEVBQUUscUJBQXFCO1lBQzNCLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLEtBQUssV0FBVztZQUMzQyxJQUFJLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sU0FBUyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUM7U0FDbkQsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUNOLE9BQU87UUFDTCxJQUFJLEVBQUU7WUFDSixFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUU7WUFD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QUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN6RSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3RELEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDN0Q7UUFDRCxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtLQUNwRCxDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQUMsSUFBWSxFQUFFLElBQXdCLEVBQUUsR0FBVztJQUMzRSxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFBO0lBQ3JDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQUUsT0FBTyxRQUFRLENBQUE7SUFDM0UsT0FBTyxHQUFHLElBQUksR0FBRyxRQUFRLEVBQUUsQ0FBQTtBQUM3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBSZWFjdCBmcm9tIFwicmVhY3RcIlxuaW1wb3J0IHR5cGUgeyBXZWJzaXRlQ29uZmlnIH0gZnJvbSBcIi4uL21vZGVscy9jb25maWcudHNcIlxuaW1wb3J0IHsgZmF2aWNvblR5cGUgfSBmcm9tIFwiLi9mYXZpY29uLnRzXCJcbmltcG9ydCB7IHByZWZpeFVybCB9IGZyb20gXCIuL3ByZWZpeC11cmwudHNcIlxuaW1wb3J0IHsgYnVpbGRUaGVtZVNjcmlwdCB9IGZyb20gXCIuL3RoZW1lLnRzXCJcblxuLyoqIFNpdGUtd2lkZSBgPGhlYWQ+YCB0YWdzIHRoZSByb290IHJvdXRlIHJlbmRlcnMgb24gZXZlcnkgcGFnZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUm9vdEhlYWQge1xuICBtZXRhOiBBcnJheTxSZWFjdC5KU1guSW50cmluc2ljRWxlbWVudHNbXCJtZXRhXCJdPlxuICBsaW5rczogQXJyYXk8UmVhY3QuSlNYLkludHJpbnNpY0VsZW1lbnRzW1wibGlua1wiXT5cbiAgc2NyaXB0czogQXJyYXk8UmVhY3QuSlNYLkludHJpbnNpY0VsZW1lbnRzW1wic2NyaXB0XCJdPlxufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRSb290SGVhZChwcm9wczoge1xuICBjb25maWc6IFdlYnNpdGVDb25maWdcbiAgZGVmYXVsdEZhdmljb246IHN0cmluZ1xuICBzdHlsZXNoZWV0czogc3RyaW5nW11cbn0pIHtcbiAgY29uc3QgY29uZmlnID0gcHJvcHMuY29uZmlnXG4gIGNvbnN0IGZhdmljb24gPSBwcmVmaXhVcmwoXG4gICAgY29uZmlnLmZhdmljb24gPz8gY29uZmlnLmxvZ28gPz8gcHJvcHMuZGVmYXVsdEZhdmljb24sXG4gICAgY29uZmlnLmJhc2UsXG4gIClcbiAgY29uc3QgZmVlZExpbmtzID0gY29uZmlnLnNpdGVcbiAgICA/IChjb25maWcuc2VjdGlvbnMgPz8gW10pXG4gICAgICAgIC5maWx0ZXIocyA9PiBzLnR5cGUgPT09IFwiYmxvZ1wiKVxuICAgICAgICAubWFwKHMgPT4gKHtcbiAgICAgICAgICByZWw6IFwiYWx0ZXJuYXRlXCIsXG4gICAgICAgICAgdHlwZTogXCJhcHBsaWNhdGlvbi9yc3MreG1sXCIsXG4gICAgICAgICAgdGl0bGU6IGAke3Muc2l0ZVRpdGxlID8/IHMudGl0bGV9IFJTUyBGZWVkYCxcbiAgICAgICAgICBocmVmOiBwcmVmaXhVcmwoYCR7cy5wcmVmaXh9cnNzLnhtbGAsIGNvbmZpZy5iYXNlKSxcbiAgICAgICAgfSkpXG4gICAgOiBbXVxuICByZXR1cm4ge1xuICAgIG1ldGE6IFtcbiAgICAgIHsgY2hhclNldDogXCJ1dGYtOFwiIH0sXG4gICAgICB7IHRpdGxlOiBjb25maWcudGl0bGUgfSxcbiAgICAgIHsgbmFtZTogXCJkZXNjcmlwdGlvblwiLCBjb250ZW50OiBjb25maWcuZGVzY3JpcHRpb24gfSxcbiAgICAgIHsgcHJvcGVydHk6IFwib2c6dGl0bGVcIiwgY29udGVudDogY29uZmlnLnRpdGxlIH0sXG4gICAgICB7IHByb3BlcnR5OiBcIm9nOmRlc2NyaXB0aW9uXCIsIGNvbnRlbnQ6IGNvbmZpZy5kZXNjcmlwdGlvbiB9LFxuICAgICAgeyBwcm9wZXJ0eTogXCJvZzpzaXRlX25hbWVcIiwgY29udGVudDogY29uZmlnLnRpdGxlIH0sXG4gICAgICB7IHByb3BlcnR5OiBcIm9nOnR5cGVcIiwgY29udGVudDogXCJ3ZWJzaXRlXCIgfSxcbiAgICAgIHsgbmFtZTogXCJ2aWV3cG9ydFwiLCBjb250ZW50OiBcIndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xXCIgfSxcbiAgICAgIC4uLihjb25maWcuaGVhZD8ubWV0YSA/PyBbXSksXG4gICAgXSxcbiAgICBsaW5rczogW1xuICAgICAgeyByZWw6IFwiaWNvblwiLCBocmVmOiBmYXZpY29uLCB0eXBlOiBmYXZpY29uVHlwZShmYXZpY29uKSB9LFxuICAgICAgeyByZWw6IFwic2hvcnRjdXQgaWNvblwiLCBocmVmOiBmYXZpY29uLCB0eXBlOiBmYXZpY29uVHlwZShmYXZpY29uKSB9LFxuICAgICAgLi4ucHJvcHMuc3R5bGVzaGVldHMubWFwKGhyZWYgPT4gKHsgcmVsOiBcInN0eWxlc2hlZXRcIiwgaHJlZiB9KSksXG4gICAgICAuLi5mZWVkTGlua3MsXG4gICAgICAuLi4oY29uZmlnLmhlYWQ/LmxpbmtzID8/IFtdKSxcbiAgICBdLFxuICAgIHNjcmlwdHM6IFt7IGNoaWxkcmVuOiBidWlsZFRoZW1lU2NyaXB0KCkgfSwgLi4uKGNvbmZpZy5oZWFkPy5zY3JpcHRzID8/IFtdKV0sXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGFnZUhlYWQocHJvcHM6IHtcbiAgY29uZmlnOiBXZWJzaXRlQ29uZmlnXG4gIHBhdGg6IHN0cmluZ1xuICB0aXRsZT86IHN0cmluZ1xuICBkZXNjcmlwdGlvbj86IHN0cmluZ1xuICBpbWFnZT86IHN0cmluZ1xuICBpc0FydGljbGU/OiBib29sZWFuXG59KSB7XG4gIGNvbnN0IHNpdGUgPSBwcm9wcy5jb25maWcuc2l0ZT8ucmVwbGFjZSgvXFwvKyQvLCBcIlwiKVxuICBjb25zdCB1cmwgPSBzaXRlID8gYnVpbGRBYnNvbHV0ZVVybChzaXRlLCBwcm9wcy5jb25maWcuYmFzZSwgcHJvcHMucGF0aCkgOiB1bmRlZmluZWRcbiAgY29uc3QgaW1hZ2UgPVxuICAgIHNpdGUgJiYgcHJvcHMuaW1hZ2VcbiAgICAgID8gYnVpbGRBYnNvbHV0ZVVybChzaXRlLCBwcm9wcy5jb25maWcuYmFzZSwgcHJvcHMuaW1hZ2UpXG4gICAgICA6IHVuZGVmaW5lZFxuICByZXR1cm4ge1xuICAgIG1ldGE6IFtcbiAgICAgIC4uLihwcm9wcy50aXRsZVxuICAgICAgICA/IFt7IHRpdGxlOiBwcm9wcy50aXRsZSB9LCB7IHByb3BlcnR5OiBcIm9nOnRpdGxlXCIsIGNvbnRlbnQ6IHByb3BzLnRpdGxlIH1dXG4gICAgICAgIDogW10pLFxuICAgICAgLi4uKHByb3BzLmRlc2NyaXB0aW9uXG4gICAgICAgID8gW1xuICAgICAgICAgICAgeyBuYW1lOiBcImRlc2NyaXB0aW9uXCIsIGNvbnRlbnQ6IHByb3BzLmRlc2NyaXB0aW9uIH0sXG4gICAgICAgICAgICB7IHByb3BlcnR5OiBcIm9nOmRlc2NyaXB0aW9uXCIsIGNvbnRlbnQ6IHByb3BzLmRlc2NyaXB0aW9uIH0sXG4gICAgICAgICAgXVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLihwcm9wcy5pc0FydGljbGUgPyBbeyBwcm9wZXJ0eTogXCJvZzp0eXBlXCIsIGNvbnRlbnQ6IFwiYXJ0aWNsZVwiIH1dIDogW10pLFxuICAgICAgLi4uKHVybCA/IFt7IHByb3BlcnR5OiBcIm9nOnVybFwiLCBjb250ZW50OiB1cmwgfV0gOiBbXSksXG4gICAgICAuLi4oaW1hZ2UgPyBbeyBwcm9wZXJ0eTogXCJvZzppbWFnZVwiLCBjb250ZW50OiBpbWFnZSB9XSA6IFtdKSxcbiAgICBdLFxuICAgIGxpbmtzOiB1cmwgPyBbeyByZWw6IFwiY2Fub25pY2FsXCIsIGhyZWY6IHVybCB9XSA6IFtdLFxuICB9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWJzb2x1dGVVcmwoc2l0ZTogc3RyaW5nLCBiYXNlOiBzdHJpbmcgfCB1bmRlZmluZWQsIHVybDogc3RyaW5nKSB7XG4gIGNvbnN0IHByZWZpeGVkID0gcHJlZml4VXJsKHVybCwgYmFzZSlcbiAgaWYgKCFwcmVmaXhlZC5zdGFydHNXaXRoKFwiL1wiKSB8fCBwcmVmaXhlZC5zdGFydHNXaXRoKFwiLy9cIikpIHJldHVybiBwcmVmaXhlZFxuICByZXR1cm4gYCR7c2l0ZX0ke3ByZWZpeGVkfWBcbn1cbiJdfQ==
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ import { describe, expect, it } from "vite-plus/test";
2
+ import { buildPageHead, buildRootHead } from "./head.js";
3
+ const config = { title: "Docs", description: "Blurb" };
4
+ describe("buildRootHead", () => {
5
+ it("builds the default site tags", () => {
6
+ const head = buildRootHead({
7
+ config,
8
+ defaultFavicon: "/logo.svg",
9
+ stylesheets: ["/a.css"],
10
+ });
11
+ expect(head.meta).toContainEqual({ property: "og:title", content: "Docs" });
12
+ expect(head.links).toContainEqual({
13
+ rel: "icon",
14
+ href: "/logo.svg",
15
+ type: "image/svg+xml",
16
+ });
17
+ expect(head.links).toContainEqual({ rel: "stylesheet", href: "/a.css" });
18
+ expect(head.scripts).toHaveLength(1);
19
+ });
20
+ it("appends config head tags after the defaults", () => {
21
+ const head = buildRootHead({
22
+ config: {
23
+ ...config,
24
+ head: {
25
+ meta: [{ property: "og:type", content: "book" }],
26
+ links: [{ rel: "me", href: "https://x.com/me" }],
27
+ scripts: [{ src: "https://cdn.example.com/a.js" }],
28
+ },
29
+ },
30
+ defaultFavicon: "/logo.svg",
31
+ stylesheets: [],
32
+ });
33
+ expect(head.meta.at(-1)).toEqual({ property: "og:type", content: "book" });
34
+ expect(head.links.at(-1)).toEqual({ rel: "me", href: "https://x.com/me" });
35
+ expect(head.scripts.at(-1)).toEqual({ src: "https://cdn.example.com/a.js" });
36
+ });
37
+ it("links blog feeds only when site is set", () => {
38
+ const sections = [
39
+ { type: "blog", title: "Blog", prefix: "/blog/", position: "header" },
40
+ ];
41
+ const withoutSite = buildRootHead({
42
+ config: { ...config, sections },
43
+ defaultFavicon: "/logo.svg",
44
+ stylesheets: [],
45
+ });
46
+ const withSite = buildRootHead({
47
+ config: { ...config, sections, site: "https://example.com", base: "/repo" },
48
+ defaultFavicon: "/logo.svg",
49
+ stylesheets: [],
50
+ });
51
+ expect(withoutSite.links.some(l => l.rel === "alternate")).toBe(false);
52
+ expect(withSite.links).toContainEqual({
53
+ rel: "alternate",
54
+ type: "application/rss+xml",
55
+ title: "Blog RSS Feed",
56
+ href: "/repo/blog/rss.xml",
57
+ });
58
+ });
59
+ });
60
+ describe("buildPageHead", () => {
61
+ it("emits title, description and article type", () => {
62
+ const head = buildPageHead({
63
+ config,
64
+ path: "/guide/",
65
+ title: "Guide",
66
+ description: "How to",
67
+ isArticle: true,
68
+ });
69
+ expect(head.meta).toEqual([
70
+ { title: "Guide" },
71
+ { property: "og:title", content: "Guide" },
72
+ { name: "description", content: "How to" },
73
+ { property: "og:description", content: "How to" },
74
+ { property: "og:type", content: "article" },
75
+ ]);
76
+ expect(head.links).toEqual([]);
77
+ });
78
+ it("adds absolute url, canonical and image when site is set", () => {
79
+ const head = buildPageHead({
80
+ config: { ...config, site: "https://example.com/", base: "/repo" },
81
+ path: "/guide/",
82
+ image: "/repo/assets/cover.png",
83
+ });
84
+ expect(head.meta).toEqual([
85
+ { property: "og:url", content: "https://example.com/repo/guide/" },
86
+ { property: "og:image", content: "https://example.com/repo/assets/cover.png" },
87
+ ]);
88
+ expect(head.links).toEqual([
89
+ { rel: "canonical", href: "https://example.com/repo/guide/" },
90
+ ]);
91
+ });
92
+ it("keeps an already absolute image", () => {
93
+ const head = buildPageHead({
94
+ config: { ...config, site: "https://example.com" },
95
+ path: "/",
96
+ image: "https://cdn.example.com/cover.png",
97
+ });
98
+ expect(head.meta).toContainEqual({
99
+ property: "og:image",
100
+ content: "https://cdn.example.com/cover.png",
101
+ });
102
+ });
103
+ it("skips og:image without site", () => {
104
+ const head = buildPageHead({ config, path: "/", image: "/cover.png" });
105
+ expect(head.meta).toEqual([]);
106
+ });
107
+ });
108
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZC51bml0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvaGVhZC51bml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRXJELE9BQU8sRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRXhELE1BQU0sTUFBTSxHQUFrQixFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFBO0FBRXJFLFFBQVEsQ0FBQyxlQUFlLEVBQUUsR0FBRyxFQUFFO0lBQzdCLEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxHQUFHLEVBQUU7UUFDdEMsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDO1lBQ3pCLE1BQU07WUFDTixjQUFjLEVBQUUsV0FBVztZQUMzQixXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUM7U0FDeEIsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxjQUFjLENBQUMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQzNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsY0FBYyxDQUFDO1lBQ2hDLEdBQUcsRUFBRSxNQUFNO1lBQ1gsSUFBSSxFQUFFLFdBQVc7WUFDakIsSUFBSSxFQUFFLGVBQWU7U0FDdEIsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxjQUFjLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFBO1FBQ3hFLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3RDLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtRQUNyRCxNQUFNLElBQUksR0FBRyxhQUFhLENBQUM7WUFDekIsTUFBTSxFQUFFO2dCQUNOLEdBQUcsTUFBTTtnQkFDVCxJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztvQkFDaEQsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRSxDQUFDO29CQUNoRCxPQUFPLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSw4QkFBOEIsRUFBRSxDQUFDO2lCQUNuRDthQUNGO1lBQ0QsY0FBYyxFQUFFLFdBQVc7WUFDM0IsV0FBVyxFQUFFLEVBQUU7U0FDaEIsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQzFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFBO1FBQzFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLDhCQUE4QixFQUFFLENBQUMsQ0FBQTtJQUM5RSxDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyx3Q0FBd0MsRUFBRSxHQUFHLEVBQUU7UUFDaEQsTUFBTSxRQUFRLEdBQThCO1lBQzFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRTtTQUN0RSxDQUFBO1FBQ0QsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDO1lBQ2hDLE1BQU0sRUFBRSxFQUFFLEdBQUcsTUFBTSxFQUFFLFFBQVEsRUFBRTtZQUMvQixjQUFjLEVBQUUsV0FBVztZQUMzQixXQUFXLEVBQUUsRUFBRTtTQUNoQixDQUFDLENBQUE7UUFDRixNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUM7WUFDN0IsTUFBTSxFQUFFLEVBQUUsR0FBRyxNQUFNLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxxQkFBcUIsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO1lBQzNFLGNBQWMsRUFBRSxXQUFXO1lBQzNCLFdBQVcsRUFBRSxFQUFFO1NBQ2hCLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDdEUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxjQUFjLENBQUM7WUFDcEMsR0FBRyxFQUFFLFdBQVc7WUFDaEIsSUFBSSxFQUFFLHFCQUFxQjtZQUMzQixLQUFLLEVBQUUsZUFBZTtZQUN0QixJQUFJLEVBQUUsb0JBQW9CO1NBQzNCLENBQUMsQ0FBQTtJQUNKLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUE7QUFFRixRQUFRLENBQUMsZUFBZSxFQUFFLEdBQUcsRUFBRTtJQUM3QixFQUFFLENBQUMsMkNBQTJDLEVBQUUsR0FBRyxFQUFFO1FBQ25ELE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQztZQUN6QixNQUFNO1lBQ04sSUFBSSxFQUFFLFNBQVM7WUFDZixLQUFLLEVBQUUsT0FBTztZQUNkLFdBQVcsRUFBRSxRQUFRO1lBQ3JCLFNBQVMsRUFBRSxJQUFJO1NBQ2hCLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ3hCLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRTtZQUNsQixFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRTtZQUMxQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRTtZQUMxQyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFO1lBQ2pELEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFO1NBQzVDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ2hDLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEdBQUcsRUFBRTtRQUNqRSxNQUFNLElBQUksR0FBRyxhQUFhLENBQUM7WUFDekIsTUFBTSxFQUFFLEVBQUUsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLHNCQUFzQixFQUFFLElBQUksRUFBRSxPQUFPLEVBQUU7WUFDbEUsSUFBSSxFQUFFLFNBQVM7WUFDZixLQUFLLEVBQUUsd0JBQXdCO1NBQ2hDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ3hCLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsaUNBQWlDLEVBQUU7WUFDbEUsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSwyQ0FBMkMsRUFBRTtTQUMvRSxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQztZQUN6QixFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLGlDQUFpQyxFQUFFO1NBQzlELENBQUMsQ0FBQTtJQUNKLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtRQUN6QyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUM7WUFDekIsTUFBTSxFQUFFLEVBQUUsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFO1lBQ2xELElBQUksRUFBRSxHQUFHO1lBQ1QsS0FBSyxFQUFFLG1DQUFtQztTQUMzQyxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLGNBQWMsQ0FBQztZQUMvQixRQUFRLEVBQUUsVUFBVTtZQUNwQixPQUFPLEVBQUUsbUNBQW1DO1NBQzdDLENBQUMsQ0FBQTtJQUNKLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLDZCQUE2QixFQUFFLEdBQUcsRUFBRTtRQUNyQyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQTtRQUN0RSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUMvQixDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZGVzY3JpYmUsIGV4cGVjdCwgaXQgfSBmcm9tIFwidml0ZS1wbHVzL3Rlc3RcIlxuaW1wb3J0IHR5cGUgeyBXZWJzaXRlQ29uZmlnIH0gZnJvbSBcIi4uL21vZGVscy9jb25maWcudHNcIlxuaW1wb3J0IHsgYnVpbGRQYWdlSGVhZCwgYnVpbGRSb290SGVhZCB9IGZyb20gXCIuL2hlYWQudHNcIlxuXG5jb25zdCBjb25maWc6IFdlYnNpdGVDb25maWcgPSB7IHRpdGxlOiBcIkRvY3NcIiwgZGVzY3JpcHRpb246IFwiQmx1cmJcIiB9XG5cbmRlc2NyaWJlKFwiYnVpbGRSb290SGVhZFwiLCAoKSA9PiB7XG4gIGl0KFwiYnVpbGRzIHRoZSBkZWZhdWx0IHNpdGUgdGFnc1wiLCAoKSA9PiB7XG4gICAgY29uc3QgaGVhZCA9IGJ1aWxkUm9vdEhlYWQoe1xuICAgICAgY29uZmlnLFxuICAgICAgZGVmYXVsdEZhdmljb246IFwiL2xvZ28uc3ZnXCIsXG4gICAgICBzdHlsZXNoZWV0czogW1wiL2EuY3NzXCJdLFxuICAgIH0pXG4gICAgZXhwZWN0KGhlYWQubWV0YSkudG9Db250YWluRXF1YWwoeyBwcm9wZXJ0eTogXCJvZzp0aXRsZVwiLCBjb250ZW50OiBcIkRvY3NcIiB9KVxuICAgIGV4cGVjdChoZWFkLmxpbmtzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICByZWw6IFwiaWNvblwiLFxuICAgICAgaHJlZjogXCIvbG9nby5zdmdcIixcbiAgICAgIHR5cGU6IFwiaW1hZ2Uvc3ZnK3htbFwiLFxuICAgIH0pXG4gICAgZXhwZWN0KGhlYWQubGlua3MpLnRvQ29udGFpbkVxdWFsKHsgcmVsOiBcInN0eWxlc2hlZXRcIiwgaHJlZjogXCIvYS5jc3NcIiB9KVxuICAgIGV4cGVjdChoZWFkLnNjcmlwdHMpLnRvSGF2ZUxlbmd0aCgxKVxuICB9KVxuXG4gIGl0KFwiYXBwZW5kcyBjb25maWcgaGVhZCB0YWdzIGFmdGVyIHRoZSBkZWZhdWx0c1wiLCAoKSA9PiB7XG4gICAgY29uc3QgaGVhZCA9IGJ1aWxkUm9vdEhlYWQoe1xuICAgICAgY29uZmlnOiB7XG4gICAgICAgIC4uLmNvbmZpZyxcbiAgICAgICAgaGVhZDoge1xuICAgICAgICAgIG1ldGE6IFt7IHByb3BlcnR5OiBcIm9nOnR5cGVcIiwgY29udGVudDogXCJib29rXCIgfV0sXG4gICAgICAgICAgbGlua3M6IFt7IHJlbDogXCJtZVwiLCBocmVmOiBcImh0dHBzOi8veC5jb20vbWVcIiB9XSxcbiAgICAgICAgICBzY3JpcHRzOiBbeyBzcmM6IFwiaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vYS5qc1wiIH1dLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGRlZmF1bHRGYXZpY29uOiBcIi9sb2dvLnN2Z1wiLFxuICAgICAgc3R5bGVzaGVldHM6IFtdLFxuICAgIH0pXG4gICAgZXhwZWN0KGhlYWQubWV0YS5hdCgtMSkpLnRvRXF1YWwoeyBwcm9wZXJ0eTogXCJvZzp0eXBlXCIsIGNvbnRlbnQ6IFwiYm9va1wiIH0pXG4gICAgZXhwZWN0KGhlYWQubGlua3MuYXQoLTEpKS50b0VxdWFsKHsgcmVsOiBcIm1lXCIsIGhyZWY6IFwiaHR0cHM6Ly94LmNvbS9tZVwiIH0pXG4gICAgZXhwZWN0KGhlYWQuc2NyaXB0cy5hdCgtMSkpLnRvRXF1YWwoeyBzcmM6IFwiaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vYS5qc1wiIH0pXG4gIH0pXG5cbiAgaXQoXCJsaW5rcyBibG9nIGZlZWRzIG9ubHkgd2hlbiBzaXRlIGlzIHNldFwiLCAoKSA9PiB7XG4gICAgY29uc3Qgc2VjdGlvbnM6IFdlYnNpdGVDb25maWdbXCJzZWN0aW9uc1wiXSA9IFtcbiAgICAgIHsgdHlwZTogXCJibG9nXCIsIHRpdGxlOiBcIkJsb2dcIiwgcHJlZml4OiBcIi9ibG9nL1wiLCBwb3NpdGlvbjogXCJoZWFkZXJcIiB9LFxuICAgIF1cbiAgICBjb25zdCB3aXRob3V0U2l0ZSA9IGJ1aWxkUm9vdEhlYWQoe1xuICAgICAgY29uZmlnOiB7IC4uLmNvbmZpZywgc2VjdGlvbnMgfSxcbiAgICAgIGRlZmF1bHRGYXZpY29uOiBcIi9sb2dvLnN2Z1wiLFxuICAgICAgc3R5bGVzaGVldHM6IFtdLFxuICAgIH0pXG4gICAgY29uc3Qgd2l0aFNpdGUgPSBidWlsZFJvb3RIZWFkKHtcbiAgICAgIGNvbmZpZzogeyAuLi5jb25maWcsIHNlY3Rpb25zLCBzaXRlOiBcImh0dHBzOi8vZXhhbXBsZS5jb21cIiwgYmFzZTogXCIvcmVwb1wiIH0sXG4gICAgICBkZWZhdWx0RmF2aWNvbjogXCIvbG9nby5zdmdcIixcbiAgICAgIHN0eWxlc2hlZXRzOiBbXSxcbiAgICB9KVxuICAgIGV4cGVjdCh3aXRob3V0U2l0ZS5saW5rcy5zb21lKGwgPT4gbC5yZWwgPT09IFwiYWx0ZXJuYXRlXCIpKS50b0JlKGZhbHNlKVxuICAgIGV4cGVjdCh3aXRoU2l0ZS5saW5rcykudG9Db250YWluRXF1YWwoe1xuICAgICAgcmVsOiBcImFsdGVybmF0ZVwiLFxuICAgICAgdHlwZTogXCJhcHBsaWNhdGlvbi9yc3MreG1sXCIsXG4gICAgICB0aXRsZTogXCJCbG9nIFJTUyBGZWVkXCIsXG4gICAgICBocmVmOiBcIi9yZXBvL2Jsb2cvcnNzLnhtbFwiLFxuICAgIH0pXG4gIH0pXG59KVxuXG5kZXNjcmliZShcImJ1aWxkUGFnZUhlYWRcIiwgKCkgPT4ge1xuICBpdChcImVtaXRzIHRpdGxlLCBkZXNjcmlwdGlvbiBhbmQgYXJ0aWNsZSB0eXBlXCIsICgpID0+IHtcbiAgICBjb25zdCBoZWFkID0gYnVpbGRQYWdlSGVhZCh7XG4gICAgICBjb25maWcsXG4gICAgICBwYXRoOiBcIi9ndWlkZS9cIixcbiAgICAgIHRpdGxlOiBcIkd1aWRlXCIsXG4gICAgICBkZXNjcmlwdGlvbjogXCJIb3cgdG9cIixcbiAgICAgIGlzQXJ0aWNsZTogdHJ1ZSxcbiAgICB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEpLnRvRXF1YWwoW1xuICAgICAgeyB0aXRsZTogXCJHdWlkZVwiIH0sXG4gICAgICB7IHByb3BlcnR5OiBcIm9nOnRpdGxlXCIsIGNvbnRlbnQ6IFwiR3VpZGVcIiB9LFxuICAgICAgeyBuYW1lOiBcImRlc2NyaXB0aW9uXCIsIGNvbnRlbnQ6IFwiSG93IHRvXCIgfSxcbiAgICAgIHsgcHJvcGVydHk6IFwib2c6ZGVzY3JpcHRpb25cIiwgY29udGVudDogXCJIb3cgdG9cIiB9LFxuICAgICAgeyBwcm9wZXJ0eTogXCJvZzp0eXBlXCIsIGNvbnRlbnQ6IFwiYXJ0aWNsZVwiIH0sXG4gICAgXSlcbiAgICBleHBlY3QoaGVhZC5saW5rcykudG9FcXVhbChbXSlcbiAgfSlcblxuICBpdChcImFkZHMgYWJzb2x1dGUgdXJsLCBjYW5vbmljYWwgYW5kIGltYWdlIHdoZW4gc2l0ZSBpcyBzZXRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGhlYWQgPSBidWlsZFBhZ2VIZWFkKHtcbiAgICAgIGNvbmZpZzogeyAuLi5jb25maWcsIHNpdGU6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9cIiwgYmFzZTogXCIvcmVwb1wiIH0sXG4gICAgICBwYXRoOiBcIi9ndWlkZS9cIixcbiAgICAgIGltYWdlOiBcIi9yZXBvL2Fzc2V0cy9jb3Zlci5wbmdcIixcbiAgICB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEpLnRvRXF1YWwoW1xuICAgICAgeyBwcm9wZXJ0eTogXCJvZzp1cmxcIiwgY29udGVudDogXCJodHRwczovL2V4YW1wbGUuY29tL3JlcG8vZ3VpZGUvXCIgfSxcbiAgICAgIHsgcHJvcGVydHk6IFwib2c6aW1hZ2VcIiwgY29udGVudDogXCJodHRwczovL2V4YW1wbGUuY29tL3JlcG8vYXNzZXRzL2NvdmVyLnBuZ1wiIH0sXG4gICAgXSlcbiAgICBleHBlY3QoaGVhZC5saW5rcykudG9FcXVhbChbXG4gICAgICB7IHJlbDogXCJjYW5vbmljYWxcIiwgaHJlZjogXCJodHRwczovL2V4YW1wbGUuY29tL3JlcG8vZ3VpZGUvXCIgfSxcbiAgICBdKVxuICB9KVxuXG4gIGl0KFwia2VlcHMgYW4gYWxyZWFkeSBhYnNvbHV0ZSBpbWFnZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgaGVhZCA9IGJ1aWxkUGFnZUhlYWQoe1xuICAgICAgY29uZmlnOiB7IC4uLmNvbmZpZywgc2l0ZTogXCJodHRwczovL2V4YW1wbGUuY29tXCIgfSxcbiAgICAgIHBhdGg6IFwiL1wiLFxuICAgICAgaW1hZ2U6IFwiaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vY292ZXIucG5nXCIsXG4gICAgfSlcbiAgICBleHBlY3QoaGVhZC5tZXRhKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICBwcm9wZXJ0eTogXCJvZzppbWFnZVwiLFxuICAgICAgY29udGVudDogXCJodHRwczovL2Nkbi5leGFtcGxlLmNvbS9jb3Zlci5wbmdcIixcbiAgICB9KVxuICB9KVxuXG4gIGl0KFwic2tpcHMgb2c6aW1hZ2Ugd2l0aG91dCBzaXRlXCIsICgpID0+IHtcbiAgICBjb25zdCBoZWFkID0gYnVpbGRQYWdlSGVhZCh7IGNvbmZpZywgcGF0aDogXCIvXCIsIGltYWdlOiBcIi9jb3Zlci5wbmdcIiB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEpLnRvRXF1YWwoW10pXG4gIH0pXG59KVxuIl19
@@ -0,0 +1,11 @@
1
+ export type NavItem = {
2
+ key: string;
3
+ title: string;
4
+ icon?: string;
5
+ suffix?: string;
6
+ active: boolean;
7
+ href?: string;
8
+ target?: string;
9
+ };
10
+ export declare function useNavItems(activePrefix?: string): NavItem[];
11
+ export declare function renderNavAnchor(item: NavItem, className?: string): import("react").JSX.Element;
@@ -0,0 +1,65 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { config } from "livemark:virtual";
3
+ import { Link, useLocation } from "@tanstack/react-router";
4
+ import { sectionFirstArticle, sectionFlatArticles, sortedArticles, } from "../content/article.js";
5
+ import { DynamicIcon } from "./dynamic-icon.js";
6
+ import { prefixUrl } from "./prefix-url.js";
7
+ import { customSectionActive } from "./section.js";
8
+ export function useNavItems(activePrefix) {
9
+ const pathname = useLocation({ select: l => l.pathname });
10
+ const sections = config.sections ?? [];
11
+ const items = sections
12
+ .filter(section => section.position === "header")
13
+ .map(section => {
14
+ if (section.type === "custom") {
15
+ return {
16
+ key: section.url,
17
+ title: section.title,
18
+ icon: section.icon,
19
+ active: customSectionActive(section.url, pathname),
20
+ href: section.url,
21
+ };
22
+ }
23
+ const suffix = section.type === "changelog" && section.version
24
+ ? sortedArticles.find(a => a.path === sectionFlatArticles.get(section.prefix)?.[0])?.title
25
+ : undefined;
26
+ return {
27
+ key: section.prefix,
28
+ title: section.title,
29
+ icon: section.icon,
30
+ suffix,
31
+ active: activePrefix === section.prefix,
32
+ target: section.type === "blog" || section.type === "changelog"
33
+ ? section.prefix
34
+ : sectionFirstArticle.get(section.prefix),
35
+ };
36
+ });
37
+ if (!sections.length) {
38
+ items.push({ key: "/", title: "Docs", active: true, target: "/" });
39
+ }
40
+ for (const link of config.links ?? []) {
41
+ if (link.position !== "header")
42
+ continue;
43
+ if (link.prefix && link.prefix !== activePrefix)
44
+ continue;
45
+ items.push({
46
+ key: link.url,
47
+ title: link.title,
48
+ icon: link.icon,
49
+ active: false,
50
+ href: link.url,
51
+ });
52
+ }
53
+ return items;
54
+ }
55
+ export function renderNavAnchor(item, className) {
56
+ const children = (_jsxs(_Fragment, { children: [item.icon && _jsx(DynamicIcon, { name: item.icon, className: "size-3.5" }), _jsxs("span", { children: [item.title, item.suffix && _jsxs("span", { className: "opacity-80", children: [" (", item.suffix, ")"] })] })] }));
57
+ if (item.href) {
58
+ return (_jsx("a", { href: prefixUrl(item.href, config.base), className: className, children: children }));
59
+ }
60
+ return (_jsx(Link, { to: item.target === "/" ? "/" : "/$", params: item.target && item.target !== "/" ? splatFor(item.target) : {}, className: className, children: children }));
61
+ }
62
+ function splatFor(pathname) {
63
+ return { _splat: pathname.replace(/^\/|\/$/g, "") };
64
+ }
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2LWl0ZW1zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvbmF2LWl0ZW1zLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDMUQsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixtQkFBbUIsRUFDbkIsY0FBYyxHQUNmLE1BQU0sdUJBQXVCLENBQUE7QUFDOUIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFvQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFZbEQsTUFBTSxVQUFVLFdBQVcsQ0FBQyxZQUFxQjtJQUMvQyxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtJQUN6RCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQTtJQUN0QyxNQUFNLEtBQUssR0FBYyxRQUFRO1NBQzlCLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEtBQUssUUFBUSxDQUFDO1NBQ2hELEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUNiLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM5QixPQUFPO2dCQUNMLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztnQkFDaEIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO2dCQUNwQixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7Z0JBQ2xCLE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxP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QUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUN2RSxTQUFTLEVBQUUsU0FBUyxZQUVuQixRQUFRLEdBQ0osQ0FDUixDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLFFBQWdCO0lBQ2hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQTtBQUNyRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29uZmlnIH0gZnJvbSBcImxpdmVtYXJrOnZpcnR1YWxcIlxuaW1wb3J0IHsgTGluaywgdXNlTG9jYXRpb24gfSBmcm9tIFwiQHRhbnN0YWNrL3JlYWN0LXJvdXRlclwiXG5pbXBvcnQge1xuICBzZWN0aW9uRmlyc3RBcnRpY2xlLFxuICBzZWN0aW9uRmxhdEFydGljbGVzLFxuICBzb3J0ZWRBcnRpY2xlcyxcbn0gZnJvbSBcIi4uL2NvbnRlbnQvYXJ0aWNsZS50c1wiXG5pbXBvcnQgeyBEeW5hbWljSWNvbiB9IGZyb20gXCIuL2R5bmFtaWMtaWNvbi50c3hcIlxuaW1wb3J0IHsgcHJlZml4VXJsIH0gZnJvbSBcIi4vcHJlZml4LXVybC50c1wiXG5pbXBvcnQgeyBjdXN0b21TZWN0aW9uQWN0aXZlIH0gZnJvbSBcIi4vc2VjdGlvbi50c1wiXG5cbmV4cG9ydCB0eXBlIE5hdkl0ZW0gPSB7XG4gIGtleTogc3RyaW5nXG4gIHRpdGxlOiBzdHJpbmdcbiAgaWNvbj86IHN0cmluZ1xuICBzdWZmaXg/OiBzdHJpbmdcbiAgYWN0aXZlOiBib29sZWFuXG4gIGhyZWY/OiBzdHJpbmdcbiAgdGFyZ2V0Pzogc3RyaW5nXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VOYXZJdGVtcyhhY3RpdmVQcmVmaXg/OiBzdHJpbmcpIHtcbiAgY29uc3QgcGF0aG5hbWUgPSB1c2VMb2NhdGlvbih7IHNlbGVjdDogbCA9PiBsLnBhdGhuYW1lIH0pXG4gIGNvbnN0IHNlY3Rpb25zID0gY29uZmlnLnNlY3Rpb25zID8/IFtdXG4gIGNvbnN0IGl0ZW1zOiBOYXZJdGVtW10gPSBzZWN0aW9uc1xuICAgIC5maWx0ZXIoc2VjdGlvbiA9PiBzZWN0aW9uLnBvc2l0aW9uID09PSBcImhlYWRlclwiKVxuICAgIC5tYXAoc2VjdGlvbiA9PiB7XG4gICAgICBpZiAoc2VjdGlvbi50eXBlID09PSBcImN1c3RvbVwiKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAga2V5OiBzZWN0aW9uLnVybCxcbiAgICAgICAgICB0aXRsZTogc2VjdGlvbi50aXRsZSxcbiAgICAgICAgICBpY29uOiBzZWN0aW9uLmljb24sXG4gICAgICAgICAgYWN0aXZlOiBjdXN0b21TZWN0aW9uQWN0aXZlKHNlY3Rpb24udXJsLCBwYXRobmFtZSksXG4gICAgICAgICAgaHJlZjogc2VjdGlvbi51cmwsXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IHN1ZmZpeCA9XG4gICAgICAgIHNlY3Rpb24udHlwZSA9PT0gXCJjaGFuZ2Vsb2dcIiAmJiBzZWN0aW9uLnZlcnNpb25cbiAgICAgICAgICA/IHNvcnRlZEFydGljbGVzLmZpbmQoXG4gICAgICAgICAgICAgIGEgPT4gYS5wYXRoID09PSBzZWN0aW9uRmxhdEFydGljbGVzLmdldChzZWN0aW9uLnByZWZpeCk/LlswXSxcbiAgICAgICAgICAgICk/LnRpdGxlXG4gICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGtleTogc2VjdGlvbi5wcmVmaXgsXG4gICAgICAgIHRpdGxlOiBzZWN0aW9uLnRpdGxlLFxuICAgICAgICBpY29uOiBzZWN0aW9uLmljb24sXG4gICAgICAgIHN1ZmZpeCxcbiAgICAgICAgYWN0aXZlOiBhY3RpdmVQcmVmaXggPT09IHNlY3Rpb24ucHJlZml4LFxuICAgICAgICB0YXJnZXQ6XG4gICAgICAgICAgc2VjdGlvbi50eXBlID09PSBcImJsb2dcIiB8fCBzZWN0aW9uLnR5cGUgPT09IFwiY2hhbmdlbG9nXCJcbiAgICAgICAgICAgID8gc2VjdGlvbi5wcmVmaXhcbiAgICAgICAgICAgIDogc2VjdGlvbkZpcnN0QXJ0aWNsZS5nZXQoc2VjdGlvbi5wcmVmaXgpLFxuICAgICAgfVxuICAgIH0pXG4gIGlmICghc2VjdGlvbnMubGVuZ3RoKSB7XG4gICAgaXRlbXMucHVzaCh7IGtleTogXCIvXCIsIHRpdGxlOiBcIkRvY3NcIiwgYWN0aXZlOiB0cnVlLCB0YXJnZXQ6IFwiL1wiIH0pXG4gIH1cbiAgZm9yIChjb25zdCBsaW5rIG9mIGNvbmZpZy5saW5rcyA/PyBbXSkge1xuICAgIGlmIChsaW5rLnBvc2l0aW9uICE9PSBcImhlYWRlclwiKSBjb250aW51ZVxuICAgIGlmIChsaW5rLnByZWZpeCAmJiBsaW5rLnByZWZpeCAhPT0gYWN0aXZlUHJlZml4KSBjb250aW51ZVxuICAgIGl0ZW1zLnB1c2goe1xuICAgICAga2V5OiBsaW5rLnVybCxcbiAgICAgIHRpdGxlOiBsaW5rLnRpdGxlLFxuICAgICAgaWNvbjogbGluay5pY29uLFxuICAgICAgYWN0aXZlOiBmYWxzZSxcbiAgICAgIGhyZWY6IGxpbmsudXJsLFxuICAgIH0pXG4gIH1cbiAgcmV0dXJuIGl0ZW1zXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJOYXZBbmNob3IoaXRlbTogTmF2SXRlbSwgY2xhc3NOYW1lPzogc3RyaW5nKSB7XG4gIGNvbnN0IGNoaWxkcmVuID0gKFxuICAgIDw+XG4gICAgICB7aXRlbS5pY29uICYmIDxEeW5hbWljSWNvbiBuYW1lPXtpdGVtLmljb259IGNsYXNzTmFtZT1cInNpemUtMy41XCIgLz59XG4gICAgICA8c3Bhbj5cbiAgICAgICAge2l0ZW0udGl0bGV9XG4gICAgICAgIHtpdGVtLnN1ZmZpeCAmJiA8c3BhbiBjbGFzc05hbWU9XCJvcGFjaXR5LTgwXCI+ICh7aXRlbS5zdWZmaXh9KTwvc3Bhbj59XG4gICAgICA8L3NwYW4+XG4gICAgPC8+XG4gIClcbiAgaWYgKGl0ZW0uaHJlZikge1xuICAgIHJldHVybiAoXG4gICAgICA8YSBocmVmPXtwcmVmaXhVcmwoaXRlbS5ocmVmLCBjb25maWcuYmFzZSl9IGNsYXNzTmFtZT17Y2xhc3NOYW1lfT5cbiAgICAgICAge2NoaWxkcmVufVxuICAgICAgPC9hPlxuICAgIClcbiAgfVxuICByZXR1cm4gKFxuICAgIDxMaW5rXG4gICAgICB0bz17aXRlbS50YXJnZXQgPT09IFwiL1wiID8gXCIvXCIgOiBcIi8kXCJ9XG4gICAgICBwYXJhbXM9e2l0ZW0udGFyZ2V0ICYmIGl0ZW0udGFyZ2V0ICE9PSBcIi9cIiA/IHNwbGF0Rm9yKGl0ZW0udGFyZ2V0KSA6IHt9fVxuICAgICAgY2xhc3NOYW1lPXtjbGFzc05hbWV9XG4gICAgPlxuICAgICAge2NoaWxkcmVufVxuICAgIDwvTGluaz5cbiAgKVxufVxuXG5mdW5jdGlvbiBzcGxhdEZvcihwYXRobmFtZTogc3RyaW5nKSB7XG4gIHJldHVybiB7IF9zcGxhdDogcGF0aG5hbWUucmVwbGFjZSgvXlxcL3xcXC8kL2csIFwiXCIpIH1cbn1cbiJdfQ==
@@ -0,0 +1 @@
1
+ export declare function renderInlineMarkdown(markdown: string, base: string | undefined): string;
@@ -0,0 +1,34 @@
1
+ import rehypeStringify from "rehype-stringify";
2
+ import remarkGfm from "remark-gfm";
3
+ import remarkParse from "remark-parse";
4
+ import remarkRehype from "remark-rehype";
5
+ import { unified } from "unified";
6
+ import { visit } from "unist-util-visit";
7
+ import { prefixUrl } from "./prefix-url.js";
8
+ export function renderInlineMarkdown(markdown, base) {
9
+ const html = unified()
10
+ .use(remarkParse)
11
+ .use(remarkGfm)
12
+ .use(remarkRehype)
13
+ .use(() => (tree) => rewriteLinks(tree, base))
14
+ .use(() => unwrapParagraphs)
15
+ .use(rehypeStringify)
16
+ .processSync(markdown);
17
+ return String(html).trim();
18
+ }
19
+ function rewriteLinks(tree, base) {
20
+ visit(tree, "element", (node) => {
21
+ if (node.tagName !== "a" || typeof node.properties?.href !== "string")
22
+ return;
23
+ const href = node.properties.href;
24
+ node.properties.href = prefixUrl(href, base);
25
+ if (/^https?:\/\//.test(href)) {
26
+ node.properties.target = "_blank";
27
+ node.properties.rel = ["noopener", "noreferrer"];
28
+ }
29
+ });
30
+ }
31
+ function unwrapParagraphs(tree) {
32
+ tree.children = (tree.children ?? []).flatMap(child => child.type === "element" && child.tagName === "p" ? (child.children ?? []) : [child]);
33
+ }
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyLWlubGluZS1tYXJrZG93bi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL3JlbmRlci1pbmxpbmUtbWFya2Rvd24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxlQUFlLE1BQU0sa0JBQWtCLENBQUE7QUFDOUMsT0FBTyxTQUFTLE1BQU0sWUFBWSxDQUFBO0FBQ2xDLE9BQU8sV0FBVyxNQUFNLGNBQWMsQ0FBQTtBQUN0QyxPQUFPLFlBQVksTUFBTSxlQUFlLENBQUE7QUFDeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUNqQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDeEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBUzNDLE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxRQUFnQixFQUFFLElBQXdCO0lBQzdFLE1BQU0sSUFBSSxHQUFHLE9BQU8sRUFBRTtTQUNuQixHQUFHLENBQUMsV0FBVyxDQUFDO1NBQ2hCLEdBQUcsQ0FBQyxTQUFTLENBQUM7U0FDZCxHQUFHLENBQUMsWUFBWSxDQUFDO1NBQ2pCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQWMsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN2RCxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7U0FDM0IsR0FBRyxDQUFDLGVBQWUsQ0FBQztTQUNwQixXQUFXLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDeEIsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7QUFDNUIsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLElBQWMsRUFBRSxJQUF3QjtJQUM1RCxLQUFLLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDLElBQWMsRUFBRSxFQUFFO1FBQ3hDLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxHQUFHLElBQUksT0FBTyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksS0FBSyxRQUFRO1lBQUUsT0FBTTtRQUM3RSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQTtRQUNqQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzVDLElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQTtZQUNqQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUNsRCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQsU0FBUyxnQkFBZ0IsQ0FBQyxJQUFjO0lBQ3RDLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUNwRCxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUNyRixDQUFBO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCByZWh5cGVTdHJpbmdpZnkgZnJvbSBcInJlaHlwZS1zdHJpbmdpZnlcIlxuaW1wb3J0IHJlbWFya0dmbSBmcm9tIFwicmVtYXJrLWdmbVwiXG5pbXBvcnQgcmVtYXJrUGFyc2UgZnJvbSBcInJlbWFyay1wYXJzZVwiXG5pbXBvcnQgcmVtYXJrUmVoeXBlIGZyb20gXCJyZW1hcmstcmVoeXBlXCJcbmltcG9ydCB7IHVuaWZpZWQgfSBmcm9tIFwidW5pZmllZFwiXG5pbXBvcnQgeyB2aXNpdCB9IGZyb20gXCJ1bmlzdC11dGlsLXZpc2l0XCJcbmltcG9ydCB7IHByZWZpeFVybCB9IGZyb20gXCIuL3ByZWZpeC11cmwudHNcIlxuXG5pbnRlcmZhY2UgSGFzdE5vZGUge1xuICB0eXBlOiBzdHJpbmdcbiAgdGFnTmFtZT86IHN0cmluZ1xuICBwcm9wZXJ0aWVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgY2hpbGRyZW4/OiBIYXN0Tm9kZVtdXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJJbmxpbmVNYXJrZG93bihtYXJrZG93bjogc3RyaW5nLCBiYXNlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgY29uc3QgaHRtbCA9IHVuaWZpZWQoKVxuICAgIC51c2UocmVtYXJrUGFyc2UpXG4gICAgLnVzZShyZW1hcmtHZm0pXG4gICAgLnVzZShyZW1hcmtSZWh5cGUpXG4gICAgLnVzZSgoKSA9PiAodHJlZTogSGFzdE5vZGUpID0+IHJld3JpdGVMaW5rcyh0cmVlLCBiYXNlKSlcbiAgICAudXNlKCgpID0+IHVud3JhcFBhcmFncmFwaHMpXG4gICAgLnVzZShyZWh5cGVTdHJpbmdpZnkpXG4gICAgLnByb2Nlc3NTeW5jKG1hcmtkb3duKVxuICByZXR1cm4gU3RyaW5nKGh0bWwpLnRyaW0oKVxufVxuXG5mdW5jdGlvbiByZXdyaXRlTGlua3ModHJlZTogSGFzdE5vZGUsIGJhc2U6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICB2aXNpdCh0cmVlLCBcImVsZW1lbnRcIiwgKG5vZGU6IEhhc3ROb2RlKSA9PiB7XG4gICAgaWYgKG5vZGUudGFnTmFtZSAhPT0gXCJhXCIgfHwgdHlwZW9mIG5vZGUucHJvcGVydGllcz8uaHJlZiAhPT0gXCJzdHJpbmdcIikgcmV0dXJuXG4gICAgY29uc3QgaHJlZiA9IG5vZGUucHJvcGVydGllcy5ocmVmXG4gICAgbm9kZS5wcm9wZXJ0aWVzLmhyZWYgPSBwcmVmaXhVcmwoaHJlZiwgYmFzZSlcbiAgICBpZiAoL15odHRwcz86XFwvXFwvLy50ZXN0KGhyZWYpKSB7XG4gICAgICBub2RlLnByb3BlcnRpZXMudGFyZ2V0ID0gXCJfYmxhbmtcIlxuICAgICAgbm9kZS5wcm9wZXJ0aWVzLnJlbCA9IFtcIm5vb3BlbmVyXCIsIFwibm9yZWZlcnJlclwiXVxuICAgIH1cbiAgfSlcbn1cblxuZnVuY3Rpb24gdW53cmFwUGFyYWdyYXBocyh0cmVlOiBIYXN0Tm9kZSkge1xuICB0cmVlLmNoaWxkcmVuID0gKHRyZWUuY2hpbGRyZW4gPz8gW10pLmZsYXRNYXAoY2hpbGQgPT5cbiAgICBjaGlsZC50eXBlID09PSBcImVsZW1lbnRcIiAmJiBjaGlsZC50YWdOYW1lID09PSBcInBcIiA/IChjaGlsZC5jaGlsZHJlbiA/PyBbXSkgOiBbY2hpbGRdLFxuICApXG59XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vite-plus/test";
2
+ import { renderInlineMarkdown } from "./render-inline-markdown.js";
3
+ describe("renderInlineMarkdown", () => {
4
+ it("should render plain text without a paragraph", () => {
5
+ expect(renderInlineMarkdown("Hello world", undefined)).toBe("Hello world");
6
+ });
7
+ it("should render bold, emphasis and code", () => {
8
+ expect(renderInlineMarkdown("**a** _b_ `c`", undefined)).toBe("<strong>a</strong> <em>b</em> <code>c</code>");
9
+ });
10
+ it("should open absolute links in a new tab", () => {
11
+ expect(renderInlineMarkdown("[x](https://example.com)", undefined)).toBe('<a href="https://example.com" target="_blank" rel="noopener noreferrer">x</a>');
12
+ });
13
+ it("should prefix root-relative links with the base", () => {
14
+ expect(renderInlineMarkdown("[x](/blog/)", "/repo")).toBe('<a href="/repo/blog/">x</a>');
15
+ });
16
+ it("should drop raw HTML tags", () => {
17
+ expect(renderInlineMarkdown("a <b onclick=x>c</b>", undefined)).toBe("a c");
18
+ });
19
+ });
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyLWlubGluZS1tYXJrZG93bi51bml0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvcmVuZGVyLWlubGluZS1tYXJrZG93bi51bml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQ3JELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDZCQUE2QixDQUFBO0FBRWxFLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLEVBQUU7SUFDcEMsRUFBRSxDQUFDLDhDQUE4QyxFQUFFLEdBQUcsRUFBRTtRQUN0RCxNQUFNLENBQUMsb0JBQW9CLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFBO0lBQzVFLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLHVDQUF1QyxFQUFFLEdBQUcsRUFBRTtRQUMvQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsZUFBZSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUMzRCw4Q0FBOEMsQ0FDL0MsQ0FBQTtJQUNILENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLHlDQUF5QyxFQUFFLEdBQUcsRUFBRTtRQUNqRCxNQUFNLENBQUMsb0JBQW9CLENBQUMsMEJBQTBCLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ3RFLCtFQUErRSxDQUNoRixDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsaURBQWlELEVBQUUsR0FBRyxFQUFFO1FBQ3pELE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ3ZELDZCQUE2QixDQUM5QixDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsMkJBQTJCLEVBQUUsR0FBRyxFQUFFO1FBQ25DLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxzQkFBc0IsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUM3RSxDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZGVzY3JpYmUsIGV4cGVjdCwgaXQgfSBmcm9tIFwidml0ZS1wbHVzL3Rlc3RcIlxuaW1wb3J0IHsgcmVuZGVySW5saW5lTWFya2Rvd24gfSBmcm9tIFwiLi9yZW5kZXItaW5saW5lLW1hcmtkb3duLnRzXCJcblxuZGVzY3JpYmUoXCJyZW5kZXJJbmxpbmVNYXJrZG93blwiLCAoKSA9PiB7XG4gIGl0KFwic2hvdWxkIHJlbmRlciBwbGFpbiB0ZXh0IHdpdGhvdXQgYSBwYXJhZ3JhcGhcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChyZW5kZXJJbmxpbmVNYXJrZG93bihcIkhlbGxvIHdvcmxkXCIsIHVuZGVmaW5lZCkpLnRvQmUoXCJIZWxsbyB3b3JsZFwiKVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIHJlbmRlciBib2xkLCBlbXBoYXNpcyBhbmQgY29kZVwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHJlbmRlcklubGluZU1hcmtkb3duKFwiKiphKiogX2JfIGBjYFwiLCB1bmRlZmluZWQpKS50b0JlKFxuICAgICAgXCI8c3Ryb25nPmE8L3N0cm9uZz4gPGVtPmI8L2VtPiA8Y29kZT5jPC9jb2RlPlwiLFxuICAgIClcbiAgfSlcblxuICBpdChcInNob3VsZCBvcGVuIGFic29sdXRlIGxpbmtzIGluIGEgbmV3IHRhYlwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHJlbmRlcklubGluZU1hcmtkb3duKFwiW3hdKGh0dHBzOi8vZXhhbXBsZS5jb20pXCIsIHVuZGVmaW5lZCkpLnRvQmUoXG4gICAgICAnPGEgaHJlZj1cImh0dHBzOi8vZXhhbXBsZS5jb21cIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+eDwvYT4nLFxuICAgIClcbiAgfSlcblxuICBpdChcInNob3VsZCBwcmVmaXggcm9vdC1yZWxhdGl2ZSBsaW5rcyB3aXRoIHRoZSBiYXNlXCIsICgpID0+IHtcbiAgICBleHBlY3QocmVuZGVySW5saW5lTWFya2Rvd24oXCJbeF0oL2Jsb2cvKVwiLCBcIi9yZXBvXCIpKS50b0JlKFxuICAgICAgJzxhIGhyZWY9XCIvcmVwby9ibG9nL1wiPng8L2E+JyxcbiAgICApXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgZHJvcCByYXcgSFRNTCB0YWdzXCIsICgpID0+IHtcbiAgICBleHBlY3QocmVuZGVySW5saW5lTWFya2Rvd24oXCJhIDxiIG9uY2xpY2s9eD5jPC9iPlwiLCB1bmRlZmluZWQpKS50b0JlKFwiYSBjXCIpXG4gIH0pXG59KVxuIl19
@@ -0,0 +1,8 @@
1
+ import { type RefObject } from "react";
2
+ /** Build a case-insensitive pattern matching each word of a search query */
3
+ export declare function buildHighlightPattern(query: string): RegExp | undefined;
4
+ /** Find the `[start, end]` offsets of every pattern match in a text */
5
+ export declare function findTextMatches(text: string, pattern: RegExp): (readonly [number, number])[];
6
+ /** Highlight search query matches under `root` and scroll to the first visible one;
7
+ * `page` re-runs it when the same query lands on another page */
8
+ export declare function useSearchHighlight(root: RefObject<HTMLElement | null>, page: string, query?: string): void;
@@ -0,0 +1,59 @@
1
+ import { useEffect } from "react";
2
+ const HIGHLIGHT_NAME = "search-match";
3
+ /** Build a case-insensitive pattern matching each word of a search query */
4
+ export function buildHighlightPattern(query) {
5
+ const words = [...new Set(query.toLowerCase().split(/\s+/))]
6
+ .filter(word => word.length >= 2)
7
+ .sort((a, b) => b.length - a.length)
8
+ .map(word => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
9
+ if (!words.length)
10
+ return undefined;
11
+ return new RegExp(words.join("|"), "gi");
12
+ }
13
+ /** Find the `[start, end]` offsets of every pattern match in a text */
14
+ export function findTextMatches(text, pattern) {
15
+ return [...text.matchAll(pattern)].map(match => [match.index, match.index + match[0].length]);
16
+ }
17
+ /** Highlight search query matches under `root` and scroll to the first visible one;
18
+ * `page` re-runs it when the same query lands on another page */
19
+ export function useSearchHighlight(root, page, query) {
20
+ useEffect(() => {
21
+ const pattern = query ? buildHighlightPattern(query) : undefined;
22
+ if (!pattern || !root.current || typeof CSS === "undefined" || !CSS.highlights)
23
+ return;
24
+ const ranges = collectMatchRanges(root.current, pattern);
25
+ CSS.highlights.set(HIGHLIGHT_NAME, new Highlight(...ranges));
26
+ // An explicit anchor in the URL wins over the first match. The frame delay lets
27
+ // the router's scroll restoration, which resets to the top, run first.
28
+ const frame = window.location.hash
29
+ ? undefined
30
+ : requestAnimationFrame(() => scrollToFirstVisible(ranges));
31
+ return () => {
32
+ if (frame !== undefined)
33
+ cancelAnimationFrame(frame);
34
+ CSS.highlights.delete(HIGHLIGHT_NAME);
35
+ };
36
+ }, [root, page, query]);
37
+ }
38
+ function collectMatchRanges(root, pattern) {
39
+ const ranges = [];
40
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
41
+ acceptNode: node => node.parentElement?.closest("pre, script, style, svg, textarea")
42
+ ? NodeFilter.FILTER_REJECT
43
+ : NodeFilter.FILTER_ACCEPT,
44
+ });
45
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
46
+ for (const [start, end] of findTextMatches(node.textContent ?? "", pattern)) {
47
+ const range = new Range();
48
+ range.setStart(node, start);
49
+ range.setEnd(node, end);
50
+ ranges.push(range);
51
+ }
52
+ }
53
+ return ranges;
54
+ }
55
+ function scrollToFirstVisible(ranges) {
56
+ const first = ranges.find(range => range.startContainer.parentElement?.checkVisibility());
57
+ first?.startContainer.parentElement?.scrollIntoView({ block: "center" });
58
+ }
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLWhpZ2hsaWdodC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL3NlYXJjaC1oaWdobGlnaHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBa0IsTUFBTSxPQUFPLENBQUE7QUFFakQsTUFBTSxjQUFjLEdBQUcsY0FBYyxDQUFBO0FBRXJDLDRFQUE0RTtBQUM1RSxNQUFNLFVBQVUscUJBQXFCLENBQUMsS0FBYTtJQUNqRCxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQ3pELE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO1NBQ2hDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztTQUNuQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7SUFDM0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNO1FBQUUsT0FBTyxTQUFTLENBQUE7SUFDbkMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFBO0FBQzFDLENBQUM7QUFFRCx1RUFBdUU7QUFDdkUsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUFZLEVBQUUsT0FBZTtJQUMzRCxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUNwQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEtB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QUUsY0FBYyxDQUFDLGFBQWEsRUFBRSxjQUFjLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQTtBQUMxRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdXNlRWZmZWN0LCB0eXBlIFJlZk9iamVjdCB9IGZyb20gXCJyZWFjdFwiXG5cbmNvbnN0IEhJR0hMSUdIVF9OQU1FID0gXCJzZWFyY2gtbWF0Y2hcIlxuXG4vKiogQnVpbGQgYSBjYXNlLWluc2Vuc2l0aXZlIHBhdHRlcm4gbWF0Y2hpbmcgZWFjaCB3b3JkIG9mIGEgc2VhcmNoIHF1ZXJ5ICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRIaWdobGlnaHRQYXR0ZXJuKHF1ZXJ5OiBzdHJpbmcpIHtcbiAgY29uc3Qgd29yZHMgPSBbLi4ubmV3IFNldChxdWVyeS50b0xvd2VyQ2FzZSgpLnNwbGl0KC9cXHMrLykpXVxuICAgIC5maWx0ZXIod29yZCA9PiB3b3JkLmxlbmd0aCA+PSAyKVxuICAgIC5zb3J0KChhLCBiKSA9PiBiLmxlbmd0aCAtIGEubGVuZ3RoKVxuICAgIC5tYXAod29yZCA9PiB3b3JkLnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCBcIlxcXFwkJlwiKSlcbiAgaWYgKCF3b3Jkcy5sZW5ndGgpIHJldHVybiB1bmRlZmluZWRcbiAgcmV0dXJuIG5ldyBSZWdFeHAod29yZHMuam9pbihcInxcIiksIFwiZ2lcIilcbn1cblxuLyoqIEZpbmQgdGhlIGBbc3RhcnQsIGVuZF1gIG9mZnNldHMgb2YgZXZlcnkgcGF0dGVybiBtYXRjaCBpbiBhIHRleHQgKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kVGV4dE1hdGNoZXModGV4dDogc3RyaW5nLCBwYXR0ZXJuOiBSZWdFeHApIHtcbiAgcmV0dXJuIFsuLi50ZXh0Lm1hdGNoQWxsKHBhdHRlcm4pXS5tYXAoXG4gICAgbWF0Y2ggPT4gW21hdGNoLmluZGV4LCBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aF0gYXMgY29uc3QsXG4gIClcbn1cblxuLyoqIEhpZ2hsaWdodCBzZWFyY2ggcXVlcnkgbWF0Y2hlcyB1bmRlciBgcm9vdGAgYW5kIHNjcm9sbCB0byB0aGUgZmlyc3QgdmlzaWJsZSBvbmU7XG4gKiAgYHBhZ2VgIHJlLXJ1bnMgaXQgd2hlbiB0aGUgc2FtZSBxdWVyeSBsYW5kcyBvbiBhbm90aGVyIHBhZ2UgKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VTZWFyY2hIaWdobGlnaHQoXG4gIHJvb3Q6IFJlZk9iamVjdDxIVE1MRWxlbWVudCB8IG51bGw+LFxuICBwYWdlOiBzdHJpbmcsXG4gIHF1ZXJ5Pzogc3RyaW5nLFxuKSB7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgcGF0dGVybiA9IHF1ZXJ5ID8gYnVpbGRIaWdobGlnaHRQYXR0ZXJuKHF1ZXJ5KSA6IHVuZGVmaW5lZFxuICAgIGlmICghcGF0dGVybiB8fCAhcm9vdC5jdXJyZW50IHx8IHR5cGVvZiBDU1MgPT09IFwidW5kZWZpbmVkXCIgfHwgIUNTUy5oaWdobGlnaHRzKSByZXR1cm5cblxuICAgIGNvbnN0IHJhbmdlcyA9IGNvbGxlY3RNYXRjaFJhbmdlcyhyb290LmN1cnJlbnQsIHBhdHRlcm4pXG4gICAgQ1NTLmhpZ2hsaWdodHMuc2V0KEhJR0hMSUdIVF9OQU1FLCBuZXcgSGlnaGxpZ2h0KC4uLnJhbmdlcykpXG5cbiAgICAvLyBBbiBleHBsaWNpdCBhbmNob3IgaW4gdGhlIFVSTCB3aW5zIG92ZXIgdGhlIGZpcnN0IG1hdGNoLiBUaGUgZnJhbWUgZGVsYXkgbGV0c1xuICAgIC8vIHRoZSByb3V0ZXIncyBzY3JvbGwgcmVzdG9yYXRpb24sIHdoaWNoIHJlc2V0cyB0byB0aGUgdG9wLCBydW4gZmlyc3QuXG4gICAgY29uc3QgZnJhbWUgPSB3aW5kb3cubG9jYXRpb24uaGFzaFxuICAgICAgPyB1bmRlZmluZWRcbiAgICAgIDogcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHNjcm9sbFRvRmlyc3RWaXNpYmxlKHJhbmdlcykpXG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKGZyYW1lICE9PSB1bmRlZmluZWQpIGNhbmNlbEFuaW1hdGlvbkZyYW1lKGZyYW1lKVxuICAgICAgQ1NTLmhpZ2hsaWdodHMuZGVsZXRlKEhJR0hMSUdIVF9OQU1FKVxuICAgIH1cbiAgfSwgW3Jvb3QsIHBhZ2UsIHF1ZXJ5XSlcbn1cblxuZnVuY3Rpb24gY29sbGVjdE1hdGNoUmFuZ2VzKHJvb3Q6IEhUTUxFbGVtZW50LCBwYXR0ZXJuOiBSZWdFeHApIHtcbiAgY29uc3QgcmFuZ2VzOiBSYW5nZVtdID0gW11cbiAgY29uc3Qgd2Fsa2VyID0gZG9jdW1lbnQuY3JlYXRlVHJlZVdhbGtlcihyb290LCBOb2RlRmlsdGVyLlNIT1dfVEVYVCwge1xuICAgIGFjY2VwdE5vZGU6IG5vZGUgPT5cbiAgICAgIG5vZGUucGFyZW50RWxlbWVudD8uY2xvc2VzdChcInByZSwgc2NyaXB0LCBzdHlsZSwgc3ZnLCB0ZXh0YXJlYVwiKVxuICAgICAgICA/IE5vZGVGaWx0ZXIuRklMVEVSX1JFSkVDVFxuICAgICAgICA6IE5vZGVGaWx0ZXIuRklMVEVSX0FDQ0VQVCxcbiAgfSlcbiAgZm9yIChsZXQgbm9kZSA9IHdhbGtlci5uZXh0Tm9kZSgpOyBub2RlOyBub2RlID0gd2Fsa2VyLm5leHROb2RlKCkpIHtcbiAgICBmb3IgKGNvbnN0IFtzdGFydCwgZW5kXSBvZiBmaW5kVGV4dE1hdGNoZXMobm9kZS50ZXh0Q29udGVudCA/PyBcIlwiLCBwYXR0ZXJuKSkge1xuICAgICAgY29uc3QgcmFuZ2UgPSBuZXcgUmFuZ2UoKVxuICAgICAgcmFuZ2Uuc2V0U3RhcnQobm9kZSwgc3RhcnQpXG4gICAgICByYW5nZS5zZXRFbmQobm9kZSwgZW5kKVxuICAgICAgcmFuZ2VzLnB1c2gocmFuZ2UpXG4gICAgfVxuICB9XG4gIHJldHVybiByYW5nZXNcbn1cblxuZnVuY3Rpb24gc2Nyb2xsVG9GaXJzdFZpc2libGUocmFuZ2VzOiBSYW5nZVtdKSB7XG4gIGNvbnN0IGZpcnN0ID0gcmFuZ2VzLmZpbmQocmFuZ2UgPT5cbiAgICByYW5nZS5zdGFydENvbnRhaW5lci5wYXJlbnRFbGVtZW50Py5jaGVja1Zpc2liaWxpdHkoKSxcbiAgKVxuICBmaXJzdD8uc3RhcnRDb250YWluZXIucGFyZW50RWxlbWVudD8uc2Nyb2xsSW50b1ZpZXcoeyBibG9jazogXCJjZW50ZXJcIiB9KVxufVxuIl19
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from "vite-plus/test";
2
+ import { buildHighlightPattern, findTextMatches } from "./search-highlight.js";
3
+ describe("buildHighlightPattern", () => {
4
+ it("should return undefined for an empty query", () => {
5
+ expect(buildHighlightPattern(" ")).toBeUndefined();
6
+ });
7
+ it("should drop single-character words", () => {
8
+ expect(buildHighlightPattern("a b")).toBeUndefined();
9
+ expect(buildHighlightPattern("a config")?.source).toBe("config");
10
+ });
11
+ it("should put longer words first and dedupe case-insensitively", () => {
12
+ expect(buildHighlightPattern("Side sidebar side")?.source).toBe("sidebar|side");
13
+ });
14
+ it("should escape regex syntax", () => {
15
+ expect(buildHighlightPattern("c++ (x)")?.source).toBe("c\\+\\+|\\(x\\)");
16
+ });
17
+ });
18
+ describe("findTextMatches", () => {
19
+ it("should find every word case-insensitively", () => {
20
+ const pattern = buildHighlightPattern("search config");
21
+ expect(pattern && findTextMatches("Search the Config, search!", pattern)).toEqual([
22
+ [0, 6],
23
+ [11, 17],
24
+ [19, 25],
25
+ ]);
26
+ });
27
+ it("should prefer the longest word at a shared position", () => {
28
+ const pattern = buildHighlightPattern("side sidebar");
29
+ expect(pattern && findTextMatches("the sidebar", pattern)).toEqual([[4, 11]]);
30
+ });
31
+ it("should return no matches when nothing matches", () => {
32
+ const pattern = buildHighlightPattern("orama");
33
+ expect(pattern && findTextMatches("nothing here", pattern)).toEqual([]);
34
+ });
35
+ });
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLWhpZ2hsaWdodC51bml0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvc2VhcmNoLWhpZ2hsaWdodC51bml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQ3JELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUU5RSxRQUFRLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxFQUFFO0lBQ3JDLEVBQUUsQ0FBQyw0Q0FBNEMsRUFBRSxHQUFHLEVBQUU7UUFDcEQsTUFBTSxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUE7SUFDdEQsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsb0NBQW9DLEVBQUUsR0FBRyxFQUFFO1FBQzVDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQ3BELE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDbEUsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsNkRBQTZELEVBQUUsR0FBRyxFQUFFO1FBQ3JFLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQTtJQUNqRixDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxHQUFHLEVBQUU7UUFDcEMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO0lBQzFFLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUE7QUFFRixRQUFRLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFO0lBQy9CLEVBQUUsQ0FBQywyQ0FBMkMsRUFBRSxHQUFHLEVBQUU7UUFDbkQsTUFBTSxPQUFPLEdBQUcscUJBQXFCLENBQUMsZUFBZSxDQUFDLENBQUE7UUFDdEQsTUFBTSxDQUFDLE9BQU8sSUFBSSxlQUFlLENBQUMsNEJBQTRCLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDaEYsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ04sQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO1lBQ1IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO1NBQ1QsQ0FBQyxDQUFBO0lBQ0osQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMscURBQXFELEVBQUUsR0FBRyxFQUFFO1FBQzdELE1BQU0sT0FBTyxHQUFHLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxDQUFBO1FBQ3JELE1BQU0sQ0FBQyxPQUFPLElBQUksZUFBZSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUMvRSxDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQywrQ0FBK0MsRUFBRSxHQUFHLEVBQUU7UUFDdkQsTUFBTSxPQUFPLEdBQUcscUJBQXFCLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDOUMsTUFBTSxDQUFDLE9BQU8sSUFBSSxlQUFlLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ3pFLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBkZXNjcmliZSwgZXhwZWN0LCBpdCB9IGZyb20gXCJ2aXRlLXBsdXMvdGVzdFwiXG5pbXBvcnQgeyBidWlsZEhpZ2hsaWdodFBhdHRlcm4sIGZpbmRUZXh0TWF0Y2hlcyB9IGZyb20gXCIuL3NlYXJjaC1oaWdobGlnaHQudHNcIlxuXG5kZXNjcmliZShcImJ1aWxkSGlnaGxpZ2h0UGF0dGVyblwiLCAoKSA9PiB7XG4gIGl0KFwic2hvdWxkIHJldHVybiB1bmRlZmluZWQgZm9yIGFuIGVtcHR5IHF1ZXJ5XCIsICgpID0+IHtcbiAgICBleHBlY3QoYnVpbGRIaWdobGlnaHRQYXR0ZXJuKFwiICAgXCIpKS50b0JlVW5kZWZpbmVkKClcbiAgfSlcblxuICBpdChcInNob3VsZCBkcm9wIHNpbmdsZS1jaGFyYWN0ZXIgd29yZHNcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChidWlsZEhpZ2hsaWdodFBhdHRlcm4oXCJhIGJcIikpLnRvQmVVbmRlZmluZWQoKVxuICAgIGV4cGVjdChidWlsZEhpZ2hsaWdodFBhdHRlcm4oXCJhIGNvbmZpZ1wiKT8uc291cmNlKS50b0JlKFwiY29uZmlnXCIpXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgcHV0IGxvbmdlciB3b3JkcyBmaXJzdCBhbmQgZGVkdXBlIGNhc2UtaW5zZW5zaXRpdmVseVwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KGJ1aWxkSGlnaGxpZ2h0UGF0dGVybihcIlNpZGUgc2lkZWJhciBzaWRlXCIpPy5zb3VyY2UpLnRvQmUoXCJzaWRlYmFyfHNpZGVcIilcbiAgfSlcblxuICBpdChcInNob3VsZCBlc2NhcGUgcmVnZXggc3ludGF4XCIsICgpID0+IHtcbiAgICBleHBlY3QoYnVpbGRIaWdobGlnaHRQYXR0ZXJuKFwiYysrICh4KVwiKT8uc291cmNlKS50b0JlKFwiY1xcXFwrXFxcXCt8XFxcXCh4XFxcXClcIilcbiAgfSlcbn0pXG5cbmRlc2NyaWJlKFwiZmluZFRleHRNYXRjaGVzXCIsICgpID0+IHtcbiAgaXQoXCJzaG91bGQgZmluZCBldmVyeSB3b3JkIGNhc2UtaW5zZW5zaXRpdmVseVwiLCAoKSA9PiB7XG4gICAgY29uc3QgcGF0dGVybiA9IGJ1aWxkSGlnaGxpZ2h0UGF0dGVybihcInNlYXJjaCBjb25maWdcIilcbiAgICBleHBlY3QocGF0dGVybiAmJiBmaW5kVGV4dE1hdGNoZXMoXCJTZWFyY2ggdGhlIENvbmZpZywgc2VhcmNoIVwiLCBwYXR0ZXJuKSkudG9FcXVhbChbXG4gICAgICBbMCwgNl0sXG4gICAgICBbMTEsIDE3XSxcbiAgICAgIFsxOSwgMjVdLFxuICAgIF0pXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgcHJlZmVyIHRoZSBsb25nZXN0IHdvcmQgYXQgYSBzaGFyZWQgcG9zaXRpb25cIiwgKCkgPT4ge1xuICAgIGNvbnN0IHBhdHRlcm4gPSBidWlsZEhpZ2hsaWdodFBhdHRlcm4oXCJzaWRlIHNpZGViYXJcIilcbiAgICBleHBlY3QocGF0dGVybiAmJiBmaW5kVGV4dE1hdGNoZXMoXCJ0aGUgc2lkZWJhclwiLCBwYXR0ZXJuKSkudG9FcXVhbChbWzQsIDExXV0pXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgcmV0dXJuIG5vIG1hdGNoZXMgd2hlbiBub3RoaW5nIG1hdGNoZXNcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHBhdHRlcm4gPSBidWlsZEhpZ2hsaWdodFBhdHRlcm4oXCJvcmFtYVwiKVxuICAgIGV4cGVjdChwYXR0ZXJuICYmIGZpbmRUZXh0TWF0Y2hlcyhcIm5vdGhpbmcgaGVyZVwiLCBwYXR0ZXJuKSkudG9FcXVhbChbXSlcbiAgfSlcbn0pXG4iXX0=
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Map a `livemark/<subpath>` import onto the target copy its `exports` entry names, so
3
+ * escapes importing Livemark modules reach other escapes, not the package originals.
4
+ */
5
+ export declare function resolveTargetExport(props: {
6
+ id: string;
7
+ targetDir: string;
8
+ exports: Record<string, string>;
9
+ }): string | undefined;
@@ -0,0 +1,24 @@
1
+ import { join } from "node:path";
2
+ /**
3
+ * Map a `livemark/<subpath>` import onto the target copy its `exports` entry names, so
4
+ * escapes importing Livemark modules reach other escapes, not the package originals.
5
+ */
6
+ export function resolveTargetExport(props) {
7
+ const queryIndex = props.id.indexOf("?");
8
+ const specifier = queryIndex === -1 ? props.id : props.id.slice(0, queryIndex);
9
+ const query = queryIndex === -1 ? "" : props.id.slice(queryIndex);
10
+ if (!specifier.startsWith("livemark/"))
11
+ return undefined;
12
+ const subpath = `./${specifier.slice("livemark/".length)}`;
13
+ for (const [key, value] of Object.entries(props.exports)) {
14
+ const [prefix, suffix] = key.split("*");
15
+ if (suffix === undefined || !prefix || !value.startsWith("./source/"))
16
+ continue;
17
+ if (!subpath.startsWith(prefix) || !subpath.endsWith(suffix))
18
+ continue;
19
+ const name = subpath.slice(prefix.length, subpath.length - suffix.length);
20
+ return (join(props.targetDir, value.slice("./source/".length).replace("*", name)) + query);
21
+ }
22
+ return undefined;
23
+ }
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFyZ2V0LWV4cG9ydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL3RhcmdldC1leHBvcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUVoQzs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsS0FJbkM7SUFDQyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUN4QyxNQUFNLFNBQVMsR0FBRyxVQUFVLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQTtJQUM5RSxNQUFNLEtBQUssR0FBRyxVQUFVLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDakUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDO1FBQUUsT0FBTyxTQUFTLENBQUE7SUFFeEQsTUFBTSxPQUFPLEdBQUcsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFBO0lBQzFELEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUN2QyxJQUFJLE1BQU0sS0FBSyxTQUFTLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztZQUFFLFNBQVE7UUFDL0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztZQUFFLFNBQVE7UUFDdEUsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ3pFLE9BQU8sQ0FDTCxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUNsRixDQUFBO0lBQ0gsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFBO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5cbi8qKlxuICogTWFwIGEgYGxpdmVtYXJrLzxzdWJwYXRoPmAgaW1wb3J0IG9udG8gdGhlIHRhcmdldCBjb3B5IGl0cyBgZXhwb3J0c2AgZW50cnkgbmFtZXMsIHNvXG4gKiBlc2NhcGVzIGltcG9ydGluZyBMaXZlbWFyayBtb2R1bGVzIHJlYWNoIG90aGVyIGVzY2FwZXMsIG5vdCB0aGUgcGFja2FnZSBvcmlnaW5hbHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlVGFyZ2V0RXhwb3J0KHByb3BzOiB7XG4gIGlkOiBzdHJpbmdcbiAgdGFyZ2V0RGlyOiBzdHJpbmdcbiAgZXhwb3J0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxufSkge1xuICBjb25zdCBxdWVyeUluZGV4ID0gcHJvcHMuaWQuaW5kZXhPZihcIj9cIilcbiAgY29uc3Qgc3BlY2lmaWVyID0gcXVlcnlJbmRleCA9PT0gLTEgPyBwcm9wcy5pZCA6IHByb3BzLmlkLnNsaWNlKDAsIHF1ZXJ5SW5kZXgpXG4gIGNvbnN0IHF1ZXJ5ID0gcXVlcnlJbmRleCA9PT0gLTEgPyBcIlwiIDogcHJvcHMuaWQuc2xpY2UocXVlcnlJbmRleClcbiAgaWYgKCFzcGVjaWZpZXIuc3RhcnRzV2l0aChcImxpdmVtYXJrL1wiKSkgcmV0dXJuIHVuZGVmaW5lZFxuXG4gIGNvbnN0IHN1YnBhdGggPSBgLi8ke3NwZWNpZmllci5zbGljZShcImxpdmVtYXJrL1wiLmxlbmd0aCl9YFxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhwcm9wcy5leHBvcnRzKSkge1xuICAgIGNvbnN0IFtwcmVmaXgsIHN1ZmZpeF0gPSBrZXkuc3BsaXQoXCIqXCIpXG4gICAgaWYgKHN1ZmZpeCA9PT0gdW5kZWZpbmVkIHx8ICFwcmVmaXggfHwgIXZhbHVlLnN0YXJ0c1dpdGgoXCIuL3NvdXJjZS9cIikpIGNvbnRpbnVlXG4gICAgaWYgKCFzdWJwYXRoLnN0YXJ0c1dpdGgocHJlZml4KSB8fCAhc3VicGF0aC5lbmRzV2l0aChzdWZmaXgpKSBjb250aW51ZVxuICAgIGNvbnN0IG5hbWUgPSBzdWJwYXRoLnNsaWNlKHByZWZpeC5sZW5ndGgsIHN1YnBhdGgubGVuZ3RoIC0gc3VmZml4Lmxlbmd0aClcbiAgICByZXR1cm4gKFxuICAgICAgam9pbihwcm9wcy50YXJnZXREaXIsIHZhbHVlLnNsaWNlKFwiLi9zb3VyY2UvXCIubGVuZ3RoKS5yZXBsYWNlKFwiKlwiLCBuYW1lKSkgKyBxdWVyeVxuICAgIClcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkXG59XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import { join } from "node:path";
2
+ import { describe, expect, it } from "vite-plus/test";
3
+ import packageJson from "../../package.json" with { type: "json" };
4
+ import { resolveTargetExport } from "./target-export.js";
5
+ const targetDir = "/project/.livemark/.target";
6
+ function resolveId(id) {
7
+ return resolveTargetExport({ id, targetDir, exports: packageJson.exports });
8
+ }
9
+ describe("resolveTargetExport", () => {
10
+ it("maps each source subpath export into the target", () => {
11
+ expect(resolveId("livemark/components/Footer")).toBe(join(targetDir, "components/Footer.tsx"));
12
+ expect(resolveId("livemark/elements/button")).toBe(join(targetDir, "elements/button.tsx"));
13
+ expect(resolveId("livemark/hooks/in-view")).toBe(join(targetDir, "hooks/in-view.ts"));
14
+ expect(resolveId("livemark/styles/general")).toBe(join(targetDir, "styles/general.css"));
15
+ });
16
+ it("keeps the query", () => {
17
+ expect(resolveId("livemark/styles/general?url")).toBe(`${join(targetDir, "styles/general.css")}?url`);
18
+ });
19
+ it("leaves other specifiers alone", () => {
20
+ expect(resolveId("livemark")).toBeUndefined();
21
+ expect(resolveId("livemark/unknown/thing")).toBeUndefined();
22
+ expect(resolveId("react")).toBeUndefined();
23
+ });
24
+ });
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFyZ2V0LWV4cG9ydC51bml0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvdGFyZ2V0LWV4cG9ydC51bml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDaEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFDckQsT0FBTyxXQUFXLE1BQU0sb0JBQW9CLENBQUMsT0FBTyxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUE7QUFDbEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFFeEQsTUFBTSxTQUFTLEdBQUcsNEJBQTRCLENBQUE7QUFFOUMsU0FBUyxTQUFTLENBQUMsRUFBVTtJQUMzQixPQUFPLG1CQUFtQixDQUFDLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7QUFDN0UsQ0FBQztBQUVELFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDbkMsRUFBRSxDQUFDLGlEQUFpRCxFQUFFLEdBQUcsRUFBRTtRQUN6RCxNQUFNLENBQUMsU0FBUyxDQUFDLDRCQUE0QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ2xELElBQUksQ0FBQyxTQUFTLEVBQUUsdUJBQXVCLENBQUMsQ0FDekMsQ0FBQTtRQUNELE1BQU0sQ0FBQyxTQUFTLENBQUMsMEJBQTBCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FDaEQsSUFBSSxDQUFDLFNBQVMsRUFBRSxxQkFBcUIsQ0FBQyxDQUN2QyxDQUFBO1FBQ0QsTUFBTSxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFBO1FBQ3JGLE1BQU0sQ0FBQyxTQUFTLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FDL0MsSUFBSSxDQUFDLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxDQUN0QyxDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFO1FBQ3pCLE1BQU0sQ0FBQyxTQUFTLENBQUMsNkJBQTZCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FDbkQsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLG9CQUFvQixDQUFDLE1BQU0sQ0FDL0MsQ0FBQTtJQUNILENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLCtCQUErQixFQUFFLEdBQUcsRUFBRTtRQUN2QyxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDN0MsTUFBTSxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDM0QsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFBO0lBQzVDLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBkZXNjcmliZSwgZXhwZWN0LCBpdCB9IGZyb20gXCJ2aXRlLXBsdXMvdGVzdFwiXG5pbXBvcnQgcGFja2FnZUpzb24gZnJvbSBcIi4uLy4uL3BhY2thZ2UuanNvblwiIHdpdGggeyB0eXBlOiBcImpzb25cIiB9XG5pbXBvcnQgeyByZXNvbHZlVGFyZ2V0RXhwb3J0IH0gZnJvbSBcIi4vdGFyZ2V0LWV4cG9ydC50c1wiXG5cbmNvbnN0IHRhcmdldERpciA9IFwiL3Byb2plY3QvLmxpdmVtYXJrLy50YXJnZXRcIlxuXG5mdW5jdGlvbiByZXNvbHZlSWQoaWQ6IHN0cmluZykge1xuICByZXR1cm4gcmVzb2x2ZVRhcmdldEV4cG9ydCh7IGlkLCB0YXJnZXREaXIsIGV4cG9ydHM6IHBhY2thZ2VKc29uLmV4cG9ydHMgfSlcbn1cblxuZGVzY3JpYmUoXCJyZXNvbHZlVGFyZ2V0RXhwb3J0XCIsICgpID0+IHtcbiAgaXQoXCJtYXBzIGVhY2ggc291cmNlIHN1YnBhdGggZXhwb3J0IGludG8gdGhlIHRhcmdldFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHJlc29sdmVJZChcImxpdmVtYXJrL2NvbXBvbmVudHMvRm9vdGVyXCIpKS50b0JlKFxuICAgICAgam9pbih0YXJnZXREaXIsIFwiY29tcG9uZW50cy9Gb290ZXIudHN4XCIpLFxuICAgIClcbiAgICBleHBlY3QocmVzb2x2ZUlkKFwibGl2ZW1hcmsvZWxlbWVudHMvYnV0dG9uXCIpKS50b0JlKFxuICAgICAgam9pbih0YXJnZXREaXIsIFwiZWxlbWVudHMvYnV0dG9uLnRzeFwiKSxcbiAgICApXG4gICAgZXhwZWN0KHJlc29sdmVJZChcImxpdmVtYXJrL2hvb2tzL2luLXZpZXdcIikpLnRvQmUoam9pbih0YXJnZXREaXIsIFwiaG9va3MvaW4tdmlldy50c1wiKSlcbiAgICBleHBlY3QocmVzb2x2ZUlkKFwibGl2ZW1hcmsvc3R5bGVzL2dlbmVyYWxcIikpLnRvQmUoXG4gICAgICBqb2luKHRhcmdldERpciwgXCJzdHlsZXMvZ2VuZXJhbC5jc3NcIiksXG4gICAgKVxuICB9KVxuXG4gIGl0KFwia2VlcHMgdGhlIHF1ZXJ5XCIsICgpID0+IHtcbiAgICBleHBlY3QocmVzb2x2ZUlkKFwibGl2ZW1hcmsvc3R5bGVzL2dlbmVyYWw/dXJsXCIpKS50b0JlKFxuICAgICAgYCR7am9pbih0YXJnZXREaXIsIFwic3R5bGVzL2dlbmVyYWwuY3NzXCIpfT91cmxgLFxuICAgIClcbiAgfSlcblxuICBpdChcImxlYXZlcyBvdGhlciBzcGVjaWZpZXJzIGFsb25lXCIsICgpID0+IHtcbiAgICBleHBlY3QocmVzb2x2ZUlkKFwibGl2ZW1hcmtcIikpLnRvQmVVbmRlZmluZWQoKVxuICAgIGV4cGVjdChyZXNvbHZlSWQoXCJsaXZlbWFyay91bmtub3duL3RoaW5nXCIpKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzb2x2ZUlkKFwicmVhY3RcIikpLnRvQmVVbmRlZmluZWQoKVxuICB9KVxufSlcbiJdfQ==
@@ -1,5 +1,9 @@
1
1
  export type Theme = "light" | "dark";
2
- export declare function detectClientTheme(): Theme;
2
+ export type ThemePref = Theme | "system";
3
+ export declare function resolveTheme(pref: ThemePref, prefersDark: boolean): Theme;
3
4
  export declare function activateTheme(theme: Theme): void;
4
5
  export declare function getCurrentTheme(): Theme;
5
- export declare function setTheme(theme: Theme): void;
6
+ export declare function getThemePref(): ThemePref;
7
+ export declare function setTheme(pref: ThemePref): void;
8
+ export declare function startTheme(): () => void;
9
+ export declare function buildThemeScript(): string;