livemark 0.25.0 → 0.27.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 (427) hide show
  1. package/README.md +3 -2
  2. package/build/actions/config/define.d.ts +12 -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/article.js +4 -11
  141. package/build/content-collections.js +6 -4
  142. package/build/elements/accordion.d.ts +4 -4
  143. package/build/elements/accordion.js +2 -3
  144. package/build/elements/alert-dialog.d.ts +12 -12
  145. package/build/elements/alert-dialog.js +2 -4
  146. package/build/elements/alert.d.ts +4 -4
  147. package/build/elements/alert.js +2 -2
  148. package/build/elements/aspect-ratio.d.ts +1 -1
  149. package/build/elements/avatar.d.ts +6 -6
  150. package/build/elements/badge.d.ts +1 -1
  151. package/build/elements/badge.js +3 -1
  152. package/build/elements/breadcrumb.d.ts +6 -6
  153. package/build/elements/breadcrumb.js +2 -4
  154. package/build/elements/button-group.d.ts +2 -2
  155. package/build/elements/button-group.js +5 -5
  156. package/build/elements/button.d.ts +2 -2
  157. package/build/elements/button.js +9 -7
  158. package/build/elements/calendar.d.ts +2 -2
  159. package/build/elements/calendar.js +2 -2
  160. package/build/elements/card.d.ts +7 -7
  161. package/build/elements/card.js +4 -4
  162. package/build/elements/carousel.d.ts +5 -5
  163. package/build/elements/carousel.js +3 -7
  164. package/build/elements/chart.d.ts +6 -6
  165. package/build/elements/chart.js +5 -11
  166. package/build/elements/checkbox.d.ts +1 -1
  167. package/build/elements/collapsible.d.ts +3 -3
  168. package/build/elements/command.d.ts +9 -9
  169. package/build/elements/command.js +5 -11
  170. package/build/elements/context-menu.d.ts +15 -15
  171. package/build/elements/context-menu.js +6 -9
  172. package/build/elements/dialog.d.ts +10 -10
  173. package/build/elements/dialog.js +2 -6
  174. package/build/elements/drawer.d.ts +14 -12
  175. package/build/elements/drawer.js +14 -15
  176. package/build/elements/dropdown-menu.d.ts +15 -15
  177. package/build/elements/dropdown-menu.js +7 -10
  178. package/build/elements/empty.d.ts +6 -6
  179. package/build/elements/empty.js +2 -2
  180. package/build/elements/field.d.ts +10 -10
  181. package/build/elements/field.js +3 -4
  182. package/build/elements/hover-card.d.ts +3 -3
  183. package/build/elements/hover-card.js +2 -2
  184. package/build/elements/input-group.d.ts +7 -7
  185. package/build/elements/input-group.js +5 -5
  186. package/build/elements/input-otp.d.ts +4 -4
  187. package/build/elements/input.d.ts +1 -1
  188. package/build/elements/input.js +2 -2
  189. package/build/elements/item.d.ts +9 -9
  190. package/build/elements/item.js +2 -2
  191. package/build/elements/kbd.d.ts +2 -2
  192. package/build/elements/label.d.ts +1 -1
  193. package/build/elements/menubar.d.ts +16 -16
  194. package/build/elements/menubar.js +9 -11
  195. package/build/elements/native-select.d.ts +3 -3
  196. package/build/elements/native-select.js +2 -4
  197. package/build/elements/navigation-menu.d.ts +8 -8
  198. package/build/elements/navigation-menu.js +3 -5
  199. package/build/elements/pagination.d.ts +7 -7
  200. package/build/elements/pagination.js +4 -10
  201. package/build/elements/popover.d.ts +6 -6
  202. package/build/elements/popover.js +2 -2
  203. package/build/elements/progress.d.ts +5 -5
  204. package/build/elements/progress.js +2 -3
  205. package/build/elements/radio-group.d.ts +2 -2
  206. package/build/elements/resizable.d.ts +3 -3
  207. package/build/elements/scroll-area.d.ts +2 -2
  208. package/build/elements/scroll-area.js +2 -4
  209. package/build/elements/select.d.ts +9 -9
  210. package/build/elements/select.js +4 -9
  211. package/build/elements/separator.d.ts +1 -1
  212. package/build/elements/sheet.d.ts +8 -8
  213. package/build/elements/sheet.js +2 -6
  214. package/build/elements/sidebar.d.ts +19 -19
  215. package/build/elements/sidebar.js +15 -37
  216. package/build/elements/skeleton.d.ts +1 -1
  217. package/build/elements/slider.d.ts +2 -1
  218. package/build/elements/slider.js +2 -3
  219. package/build/elements/sonner.d.ts +1 -1
  220. package/build/elements/spinner.d.ts +1 -1
  221. package/build/elements/switch.d.ts +1 -1
  222. package/build/elements/table.d.ts +8 -8
  223. package/build/elements/tabs.d.ts +4 -4
  224. package/build/elements/tabs.js +3 -3
  225. package/build/elements/textarea.d.ts +1 -1
  226. package/build/elements/textarea.js +2 -2
  227. package/build/elements/toggle-group.d.ts +3 -2
  228. package/build/elements/toggle-group.js +3 -3
  229. package/build/elements/toggle.d.ts +1 -1
  230. package/build/elements/toggle.js +2 -2
  231. package/build/elements/tooltip.d.ts +4 -4
  232. package/build/elements/tooltip.js +2 -3
  233. package/build/head.d.ts +4 -0
  234. package/build/head.js +6 -0
  235. package/build/helpers/agent-skills.d.ts +22 -0
  236. package/build/helpers/agent-skills.js +46 -0
  237. package/build/helpers/agent-skills.unit.d.ts +1 -0
  238. package/build/helpers/agent-skills.unit.js +49 -0
  239. package/build/helpers/article-search.d.ts +19 -0
  240. package/build/helpers/article-search.js +134 -0
  241. package/build/helpers/article.d.ts +13 -0
  242. package/build/helpers/article.js +17 -1
  243. package/build/helpers/dependency-dir.d.ts +5 -0
  244. package/build/helpers/dependency-dir.js +20 -0
  245. package/build/helpers/dependency-dir.unit.d.ts +1 -0
  246. package/build/helpers/dependency-dir.unit.js +25 -0
  247. package/build/helpers/dynamic-icon-resolver.d.ts +1 -1
  248. package/build/helpers/dynamic-icon.d.ts +1 -1
  249. package/build/helpers/head.d.ts +58 -0
  250. package/build/helpers/head.js +80 -0
  251. package/build/helpers/head.unit.d.ts +1 -0
  252. package/build/helpers/head.unit.js +110 -0
  253. package/build/helpers/llms.d.ts +33 -0
  254. package/build/helpers/llms.js +72 -0
  255. package/build/helpers/llms.unit.d.ts +1 -0
  256. package/build/helpers/llms.unit.js +98 -0
  257. package/build/helpers/nav-items.d.ts +11 -0
  258. package/build/helpers/nav-items.js +65 -0
  259. package/build/helpers/render-inline-markdown.d.ts +1 -0
  260. package/build/helpers/render-inline-markdown.js +34 -0
  261. package/build/helpers/render-inline-markdown.unit.d.ts +1 -0
  262. package/build/helpers/render-inline-markdown.unit.js +20 -0
  263. package/build/helpers/search-highlight.d.ts +8 -0
  264. package/build/helpers/search-highlight.js +59 -0
  265. package/build/helpers/search-highlight.unit.d.ts +1 -0
  266. package/build/helpers/search-highlight.unit.js +36 -0
  267. package/build/helpers/target-export.d.ts +9 -0
  268. package/build/helpers/target-export.js +24 -0
  269. package/build/helpers/target-export.unit.d.ts +1 -0
  270. package/build/helpers/target-export.unit.js +25 -0
  271. package/build/helpers/theme.d.ts +6 -2
  272. package/build/helpers/theme.js +40 -7
  273. package/build/helpers/theme.unit.d.ts +1 -0
  274. package/build/helpers/theme.unit.js +30 -0
  275. package/build/hooks/hydrated.d.ts +2 -0
  276. package/build/hooks/hydrated.js +15 -0
  277. package/build/index.d.ts +1 -0
  278. package/build/index.js +1 -1
  279. package/build/models/config.d.ts +52 -6
  280. package/build/models/config.js +17 -1
  281. package/build/models/section.d.ts +4 -2
  282. package/build/models/section.js +1 -1
  283. package/build/plugins/vite-agents.d.ts +17 -0
  284. package/build/plugins/vite-agents.js +109 -0
  285. package/build/plugins/vite-agents.unit.d.ts +1 -0
  286. package/build/plugins/vite-agents.unit.js +20 -0
  287. package/build/plugins/vite-livemark.d.ts +4 -5
  288. package/build/plugins/vite-livemark.js +56 -90
  289. package/build/plugins/vite-robots.d.ts +4 -2
  290. package/build/plugins/vite-robots.js +15 -2
  291. package/build/plugins/vite-robots.unit.js +5 -1
  292. package/build/program.js +4 -2
  293. package/build/routes/$.d.ts +4 -1
  294. package/build/routes/$.js +20 -9
  295. package/build/routes/__root.js +29 -63
  296. package/build/settings.js +2 -1
  297. package/build/vite.config.js +3 -1
  298. package/package.json +69 -66
  299. package/{.agents/skills → skills}/livemark-authoring/SKILL.md +2 -2
  300. package/{.agents/skills → skills}/livemark-configuration/SKILL.md +16 -5
  301. package/skills/livemark-customization/SKILL.md +146 -0
  302. package/source/actions/config/define.unit.ts +9 -0
  303. package/source/actions/escape/copy.ts +35 -0
  304. package/source/actions/escape/copy.unit.ts +51 -0
  305. package/source/actions/escape/list.ts +30 -0
  306. package/source/actions/escape/list.unit.ts +42 -0
  307. package/source/actions/target/build.ts +49 -69
  308. package/source/actions/target/build.unit.ts +95 -0
  309. package/source/actions/target/clear.ts +14 -0
  310. package/source/actions/target/clear.unit.ts +25 -0
  311. package/source/commands/build.ts +0 -1
  312. package/source/commands/clear.ts +15 -0
  313. package/source/commands/escape.ts +42 -59
  314. package/source/commands/preview.ts +0 -1
  315. package/source/commands/start.ts +0 -1
  316. package/source/components/AnsiCode.tsx +1 -1
  317. package/source/components/Article.tsx +8 -4
  318. package/source/components/Banner.tsx +12 -2
  319. package/source/components/BlogIndex.tsx +1 -1
  320. package/source/components/Callout.tsx +4 -6
  321. package/source/components/ChangelogIndex.tsx +1 -1
  322. package/source/components/ChoiceList.tsx +69 -0
  323. package/source/components/CodeBlock.tsx +6 -6
  324. package/source/components/CodeTabs.tsx +1 -1
  325. package/source/components/ContentTabs.tsx +1 -1
  326. package/source/components/DefaultCatchBoundary.tsx +4 -6
  327. package/source/components/Details.tsx +1 -1
  328. package/source/components/FileTree.tsx +1 -1
  329. package/source/components/Header.tsx +52 -0
  330. package/source/components/HeaderMenu.tsx +41 -0
  331. package/source/components/HeaderNav.tsx +145 -0
  332. package/source/components/HeaderSearch.tsx +77 -0
  333. package/source/components/InlineBadge.tsx +1 -1
  334. package/source/components/InlineToc.tsx +1 -1
  335. package/source/components/Layout.tsx +16 -160
  336. package/source/components/LinkButton.tsx +9 -1
  337. package/source/components/MenuSheet.tsx +92 -0
  338. package/source/components/MermaidRenderer.tsx +19 -8
  339. package/source/components/NotFound.tsx +3 -5
  340. package/source/components/PackageTabs.tsx +2 -2
  341. package/source/components/PageToolbar.tsx +11 -3
  342. package/source/components/PrevNext.tsx +2 -2
  343. package/source/components/Root.tsx +13 -0
  344. package/source/components/Search.tsx +28 -8
  345. package/source/components/SearchDialog.tsx +15 -189
  346. package/source/components/SheetPanel.tsx +69 -0
  347. package/source/components/Sidebar.tsx +27 -14
  348. package/source/components/SidebarArticles.tsx +4 -3
  349. package/source/components/SidebarLinks.tsx +3 -2
  350. package/source/components/SidebarPosts.tsx +3 -2
  351. package/source/components/SidebarReleases.tsx +3 -2
  352. package/source/components/SidebarSectionPicker.tsx +70 -0
  353. package/source/components/SiteTitle.tsx +5 -5
  354. package/source/components/SoundCloud.tsx +1 -1
  355. package/source/components/TagIndex.tsx +1 -1
  356. package/source/components/Theme.tsx +55 -29
  357. package/source/components/Toc.tsx +76 -55
  358. package/source/components/YouTube.tsx +1 -1
  359. package/source/content/article.ts +8 -13
  360. package/source/content-collections.ts +5 -4
  361. package/source/elements/alert-dialog.tsx +1 -1
  362. package/source/elements/alert.tsx +1 -1
  363. package/source/elements/badge.tsx +4 -0
  364. package/source/elements/button-group.tsx +4 -4
  365. package/source/elements/button.tsx +10 -6
  366. package/source/elements/calendar.tsx +1 -1
  367. package/source/elements/card.tsx +3 -3
  368. package/source/elements/command.tsx +7 -4
  369. package/source/elements/context-menu.tsx +5 -5
  370. package/source/elements/dialog.tsx +1 -1
  371. package/source/elements/drawer.tsx +59 -43
  372. package/source/elements/dropdown-menu.tsx +6 -6
  373. package/source/elements/empty.tsx +1 -1
  374. package/source/elements/field.tsx +1 -1
  375. package/source/elements/hover-card.tsx +1 -1
  376. package/source/elements/input-group.tsx +4 -4
  377. package/source/elements/input.tsx +1 -1
  378. package/source/elements/item.tsx +1 -1
  379. package/source/elements/menubar.tsx +8 -8
  380. package/source/elements/native-select.tsx +1 -1
  381. package/source/elements/popover.tsx +1 -1
  382. package/source/elements/select.tsx +3 -3
  383. package/source/elements/sidebar.tsx +8 -21
  384. package/source/elements/tabs.tsx +2 -2
  385. package/source/elements/textarea.tsx +1 -1
  386. package/source/elements/toggle-group.tsx +2 -2
  387. package/source/elements/toggle.tsx +1 -1
  388. package/source/env.d.ts +1 -0
  389. package/source/head.ts +7 -0
  390. package/source/helpers/agent-skills.ts +59 -0
  391. package/source/helpers/agent-skills.unit.ts +56 -0
  392. package/source/helpers/article-search.tsx +192 -0
  393. package/source/helpers/article.ts +17 -0
  394. package/source/helpers/dependency-dir.ts +20 -0
  395. package/source/helpers/dependency-dir.unit.ts +39 -0
  396. package/source/helpers/head.ts +105 -0
  397. package/source/helpers/head.unit.ts +118 -0
  398. package/source/helpers/llms.ts +109 -0
  399. package/source/helpers/llms.unit.ts +115 -0
  400. package/source/helpers/nav-items.tsx +102 -0
  401. package/source/helpers/render-inline-markdown.ts +44 -0
  402. package/source/helpers/render-inline-markdown.unit.ts +30 -0
  403. package/source/helpers/search-highlight.ts +73 -0
  404. package/source/helpers/search-highlight.unit.ts +42 -0
  405. package/source/helpers/target-export.ts +28 -0
  406. package/source/helpers/target-export.unit.ts +37 -0
  407. package/source/helpers/theme.ts +40 -6
  408. package/source/helpers/theme.unit.ts +32 -0
  409. package/source/hooks/hydrated.ts +18 -0
  410. package/source/index.ts +1 -0
  411. package/source/models/config.ts +24 -0
  412. package/source/models/section.ts +3 -0
  413. package/source/plugins/vite-agents.ts +135 -0
  414. package/source/plugins/vite-agents.unit.ts +26 -0
  415. package/source/plugins/vite-livemark.ts +54 -95
  416. package/source/plugins/vite-robots.ts +18 -3
  417. package/source/plugins/vite-robots.unit.ts +7 -0
  418. package/source/program.ts +2 -0
  419. package/source/routes/$.tsx +27 -9
  420. package/source/routes/__root.tsx +51 -71
  421. package/source/settings.ts +1 -0
  422. package/source/styles/general.css +59 -11
  423. package/source/styles/markdown.css +13 -7
  424. package/source/styles/shape.css +14 -0
  425. package/source/vite.config.ts +2 -0
  426. package/.agents/skills/change-review/SKILL.md +0 -47
  427. package/.agents/skills/livemark-customization/SKILL.md +0 -118
@@ -0,0 +1,25 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { mkdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { temporaryDirectoryTask } from "tempy";
5
+ import { describe, expect, it } from "vite-plus/test";
6
+ import { resolveDependencyDir } from "./dependency-dir.js";
7
+ describe("resolveDependencyDir", () => {
8
+ it("uses the store dir beside an isolated install", () => temporaryDirectoryTask(async (root) => {
9
+ const store = join(root, ".pnpm/livemark@1.0.0/node_modules");
10
+ await mkdir(join(store, "livemark/source"), { recursive: true });
11
+ await mkdir(join(store, "livemark/node_modules/.bin"), { recursive: true });
12
+ expect(resolveDependencyDir(join(store, "livemark/source"))).toBe(realpathSync(store));
13
+ }));
14
+ it("uses the package's own node_modules when it has one", () => temporaryDirectoryTask(async (root) => {
15
+ const packageDir = join(root, "node_modules/livemark");
16
+ await mkdir(join(packageDir, "source"), { recursive: true });
17
+ await mkdir(join(packageDir, "node_modules/zod"), { recursive: true });
18
+ expect(resolveDependencyDir(join(packageDir, "source"))).toBe(join(realpathSync(packageDir), "node_modules"));
19
+ }));
20
+ it("uses the checkout's node_modules outside an install", () => temporaryDirectoryTask(async (root) => {
21
+ await mkdir(join(root, "livemark/source"), { recursive: true });
22
+ expect(resolveDependencyDir(join(root, "livemark/source"))).toBe(join(realpathSync(root), "livemark/node_modules"));
23
+ }));
24
+ });
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS1kaXIudW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL2RlcGVuZGVuY3ktZGlyLnVuaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDeEMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNoQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxPQUFPLENBQUE7QUFDOUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFDckQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFFMUQsUUFBUSxDQUFDLHNCQUFzQixFQUFFLEdBQUcsRUFBRTtJQUNwQyxFQUFFLENBQUMsK0NBQStDLEVBQUUsR0FBRyxFQUFFLENBQ3ZELHNCQUFzQixDQUFDLEtBQUssRUFBQyxJQUFJLEVBQUMsRUFBRTtRQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLG1DQUFtQyxDQUFDLENBQUE7UUFDN0QsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7UUFDaEUsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSw0QkFBNEIsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7UUFFM0UsTUFBTSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUMvRCxZQUFZLENBQUMsS0FBSyxDQUFDLENBQ3BCLENBQUE7SUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBRUwsRUFBRSxDQUFDLHFEQUFxRCxFQUFFLEdBQUcsRUFBRSxDQUM3RCxzQkFBc0IsQ0FBQyxLQUFLLEVBQUMsSUFBSSxFQUFDLEVBQUU7UUFDbEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSx1QkFBdUIsQ0FBQyxDQUFBO1FBQ3RELE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUM1RCxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLGtCQUFrQixDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUV0RSxNQUFNLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUMzRCxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxDQUMvQyxDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUVMLEVBQUUsQ0FBQyxxREFBcUQsRUFBRSxHQUFHLEVBQUUsQ0FDN0Qsc0JBQXNCLENBQUMsS0FBSyxFQUFDLElBQUksRUFBQyxFQUFFO1FBQ2xDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO1FBRS9ELE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FDOUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSx1QkFBdUIsQ0FBQyxDQUNsRCxDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUNQLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVhbHBhdGhTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIlxuaW1wb3J0IHsgbWtkaXIgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiXG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyB0ZW1wb3JhcnlEaXJlY3RvcnlUYXNrIH0gZnJvbSBcInRlbXB5XCJcbmltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGUtcGx1cy90ZXN0XCJcbmltcG9ydCB7IHJlc29sdmVEZXBlbmRlbmN5RGlyIH0gZnJvbSBcIi4vZGVwZW5kZW5jeS1kaXIudHNcIlxuXG5kZXNjcmliZShcInJlc29sdmVEZXBlbmRlbmN5RGlyXCIsICgpID0+IHtcbiAgaXQoXCJ1c2VzIHRoZSBzdG9yZSBkaXIgYmVzaWRlIGFuIGlzb2xhdGVkIGluc3RhbGxcIiwgKCkgPT5cbiAgICB0ZW1wb3JhcnlEaXJlY3RvcnlUYXNrKGFzeW5jIHJvb3QgPT4ge1xuICAgICAgY29uc3Qgc3RvcmUgPSBqb2luKHJvb3QsIFwiLnBucG0vbGl2ZW1hcmtAMS4wLjAvbm9kZV9tb2R1bGVzXCIpXG4gICAgICBhd2FpdCBta2Rpcihqb2luKHN0b3JlLCBcImxpdmVtYXJrL3NvdXJjZVwiKSwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgICAgIGF3YWl0IG1rZGlyKGpvaW4oc3RvcmUsIFwibGl2ZW1hcmsvbm9kZV9tb2R1bGVzLy5iaW5cIiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cbiAgICAgIGV4cGVjdChyZXNvbHZlRGVwZW5kZW5jeURpcihqb2luKHN0b3JlLCBcImxpdmVtYXJrL3NvdXJjZVwiKSkpLnRvQmUoXG4gICAgICAgIHJlYWxwYXRoU3luYyhzdG9yZSksXG4gICAgICApXG4gICAgfSkpXG5cbiAgaXQoXCJ1c2VzIHRoZSBwYWNrYWdlJ3Mgb3duIG5vZGVfbW9kdWxlcyB3aGVuIGl0IGhhcyBvbmVcIiwgKCkgPT5cbiAgICB0ZW1wb3JhcnlEaXJlY3RvcnlUYXNrKGFzeW5jIHJvb3QgPT4ge1xuICAgICAgY29uc3QgcGFja2FnZURpciA9IGpvaW4ocm9vdCwgXCJub2RlX21vZHVsZXMvbGl2ZW1hcmtcIilcbiAgICAgIGF3YWl0IG1rZGlyKGpvaW4ocGFja2FnZURpciwgXCJzb3VyY2VcIiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgICBhd2FpdCBta2Rpcihqb2luKHBhY2thZ2VEaXIsIFwibm9kZV9tb2R1bGVzL3pvZFwiKSwgeyByZWN1cnNpdmU6IHRydWUgfSlcblxuICAgICAgZXhwZWN0KHJlc29sdmVEZXBlbmRlbmN5RGlyKGpvaW4ocGFja2FnZURpciwgXCJzb3VyY2VcIikpKS50b0JlKFxuICAgICAgICBqb2luKHJlYWxwYXRoU3luYyhwYWNrYWdlRGlyKSwgXCJub2RlX21vZHVsZXNcIiksXG4gICAgICApXG4gICAgfSkpXG5cbiAgaXQoXCJ1c2VzIHRoZSBjaGVja291dCdzIG5vZGVfbW9kdWxlcyBvdXRzaWRlIGFuIGluc3RhbGxcIiwgKCkgPT5cbiAgICB0ZW1wb3JhcnlEaXJlY3RvcnlUYXNrKGFzeW5jIHJvb3QgPT4ge1xuICAgICAgYXdhaXQgbWtkaXIoam9pbihyb290LCBcImxpdmVtYXJrL3NvdXJjZVwiKSwgeyByZWN1cnNpdmU6IHRydWUgfSlcblxuICAgICAgZXhwZWN0KHJlc29sdmVEZXBlbmRlbmN5RGlyKGpvaW4ocm9vdCwgXCJsaXZlbWFyay9zb3VyY2VcIikpKS50b0JlKFxuICAgICAgICBqb2luKHJlYWxwYXRoU3luYyhyb290KSwgXCJsaXZlbWFyay9ub2RlX21vZHVsZXNcIiksXG4gICAgICApXG4gICAgfSkpXG59KVxuIl19
@@ -2,4 +2,4 @@
2
2
  export default function DynamicIconResolver(props: {
3
3
  name: string;
4
4
  className?: string;
5
- }): import("react/jsx-runtime").JSX.Element | null;
5
+ }): import("react").JSX.Element | null;
@@ -2,4 +2,4 @@
2
2
  export declare function DynamicIcon(props: {
3
3
  name: string;
4
4
  className?: string;
5
- }): import("react/jsx-runtime").JSX.Element;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,58 @@
1
+ import type * as React from "react";
2
+ import type { WebsiteConfig } from "../models/config.ts";
3
+ /** Site-wide `<head>` tags the root route renders on every page. */
4
+ export interface RootHead {
5
+ meta: Array<React.JSX.IntrinsicElements["meta"]>;
6
+ links: Array<React.JSX.IntrinsicElements["link"]>;
7
+ scripts: Array<React.JSX.IntrinsicElements["script"]>;
8
+ }
9
+ export declare function buildRootHead(props: {
10
+ config: WebsiteConfig;
11
+ defaultFavicon: string;
12
+ stylesheets: string[];
13
+ }): {
14
+ meta: Record<string, string>[];
15
+ links: (Record<string, string> | {
16
+ rel: string;
17
+ href: string;
18
+ type: string | undefined;
19
+ } | {
20
+ rel: string;
21
+ href: string;
22
+ })[];
23
+ scripts: Record<string, string>[];
24
+ };
25
+ export declare function buildPageHead(props: {
26
+ config: WebsiteConfig;
27
+ path: string;
28
+ title?: string;
29
+ description?: string;
30
+ image?: string;
31
+ isArticle?: boolean;
32
+ }): {
33
+ meta: ({
34
+ title: string;
35
+ property?: undefined;
36
+ name?: undefined;
37
+ content?: undefined;
38
+ } | {
39
+ title?: undefined;
40
+ property: string;
41
+ content: string;
42
+ name?: undefined;
43
+ } | {
44
+ title?: undefined;
45
+ property?: undefined;
46
+ name: string;
47
+ content: string;
48
+ })[];
49
+ links: ({
50
+ rel: string;
51
+ href: string;
52
+ type?: undefined;
53
+ } | {
54
+ rel: string;
55
+ type: string;
56
+ href: string;
57
+ })[];
58
+ };
@@ -0,0 +1,80 @@
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: [
61
+ ...(url ? [{ rel: "canonical", href: url }] : []),
62
+ ...(props.isArticle
63
+ ? [
64
+ {
65
+ rel: "alternate",
66
+ type: "text/markdown",
67
+ href: prefixUrl(`${props.path}index.md`, props.config.base),
68
+ },
69
+ ]
70
+ : []),
71
+ ],
72
+ };
73
+ }
74
+ function buildAbsoluteUrl(site, base, url) {
75
+ const prefixed = prefixUrl(url, base);
76
+ if (!prefixed.startsWith("/") || prefixed.startsWith("//"))
77
+ return prefixed;
78
+ return `${site}${prefixed}`;
79
+ }
80
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL2hlYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUMxQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDM0MsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFBO0FBUzdDLE1BQU0sVUFBVSxhQUFhLENBQUMsS0FJN0I7SUFDQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFBO0lBQzNCLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FDdkIsTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxjQUFjLEVBQ3JELE1BQU0sQ0FBQyxJQUFJLENBQ1osQ0FBQTtJQUNELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJO1FBQzNCLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO2FBQ3BCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDO2FBQzlCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDVCxHQUFHLEVBQUUsV0FBVztZQUNoQixJQUFJLEVBQUUscUJBQXFCO1lBQzNCLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLEtBQUssV0FBVztZQUMzQyxJQUFJLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sU0FBUyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUM7U0FDbkQsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUNOLE9BQU87UUFDTCxJQUFJLEVBQUU7WUFDSixFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUU7WUFDcEIsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRTtZQUN2QixFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUU7WUFDcEQsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFO1lBQy9DLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFO1lBQzNELEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRTtZQUNuRCxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRTtZQUMzQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLHFDQUFxQyxFQUFFO1lBQ3BFLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUM7U0FDN0I7UUFDRCxLQUFLLEVBQUU7WUFDTCxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQzFELEVBQUUsR0FBRyxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDbkUsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDL0QsR0FBRyxTQUFTO1lBQ1osR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQztTQUM5QjtRQUNELE9BQU8sRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLElBQUksRUFBRSxDQUFDLENBQUM7S0FDN0UsQ0FBQTtBQUNILENBQUM7QUFFRCxNQUFNLFVBQVUsYUFBYSxDQUFDLEtBTzdCO0lBQ0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUNuRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQTtJQUNwRixNQUFNLEtBQUssR0FDVCxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUs7UUFDakIsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3hELENBQUMsQ0FBQyxTQUFTLENBQUE7SUFDZixPQUFPO1FBQ0wsSUFBSSxFQUFFO1lBQ0osR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLO2dCQUNiLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDMUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVztnQkFDbkIsQ0FBQyxDQUFDO29CQUNFLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLFdBQVcsRUFBRTtvQkFDbkQsRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUU7aUJBQzNEO2dCQUNILENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDUCxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN6RSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3RELEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDN0Q7UUFDRCxLQUFLLEVBQUU7WUFDTCxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2pELEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUztnQkFDakIsQ0FBQyxDQUFDO29CQUNFO3dCQUNFLEdBQUcsRUFBRSxXQUFXO3dCQUNoQixJQUFJLEVBQUUsZUFBZTt3QkFDckIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLFVBQVUsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztxQkFDNUQ7aUJBQ0Y7Z0JBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUNSO0tBQ0YsQ0FBQTtBQUNILENBQUM7QUFFRCxTQUFTLGdCQUFnQixDQUFDLElBQVksRUFBRSxJQUF3QixFQUFFLEdBQVc7SUFDM0UsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUNyQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztRQUFFLE9BQU8sUUFBUSxDQUFBO0lBQzNFLE9BQU8sR0FBRyxJQUFJLEdBQUcsUUFBUSxFQUFFLENBQUE7QUFDN0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlICogYXMgUmVhY3QgZnJvbSBcInJlYWN0XCJcbmltcG9ydCB0eXBlIHsgV2Vic2l0ZUNvbmZpZyB9IGZyb20gXCIuLi9tb2RlbHMvY29uZmlnLnRzXCJcbmltcG9ydCB7IGZhdmljb25UeXBlIH0gZnJvbSBcIi4vZmF2aWNvbi50c1wiXG5pbXBvcnQgeyBwcmVmaXhVcmwgfSBmcm9tIFwiLi9wcmVmaXgtdXJsLnRzXCJcbmltcG9ydCB7IGJ1aWxkVGhlbWVTY3JpcHQgfSBmcm9tIFwiLi90aGVtZS50c1wiXG5cbi8qKiBTaXRlLXdpZGUgYDxoZWFkPmAgdGFncyB0aGUgcm9vdCByb3V0ZSByZW5kZXJzIG9uIGV2ZXJ5IHBhZ2UuICovXG5leHBvcnQgaW50ZXJmYWNlIFJvb3RIZWFkIHtcbiAgbWV0YTogQXJyYXk8UmVhY3QuSlNYLkludHJpbnNpY0VsZW1lbnRzW1wibWV0YVwiXT5cbiAgbGlua3M6IEFycmF5PFJlYWN0LkpTWC5JbnRyaW5zaWNFbGVtZW50c1tcImxpbmtcIl0+XG4gIHNjcmlwdHM6IEFycmF5PFJlYWN0LkpTWC5JbnRyaW5zaWNFbGVtZW50c1tcInNjcmlwdFwiXT5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUm9vdEhlYWQocHJvcHM6IHtcbiAgY29uZmlnOiBXZWJzaXRlQ29uZmlnXG4gIGRlZmF1bHRGYXZpY29uOiBzdHJpbmdcbiAgc3R5bGVzaGVldHM6IHN0cmluZ1tdXG59KSB7XG4gIGNvbnN0IGNvbmZpZyA9IHByb3BzLmNvbmZpZ1xuICBjb25zdCBmYXZpY29uID0gcHJlZml4VXJsKFxuICAgIGNvbmZpZy5mYXZpY29uID8/IGNvbmZpZy5sb2dvID8/IHByb3BzLmRlZmF1bHRGYXZpY29uLFxuICAgIGNvbmZpZy5iYXNlLFxuICApXG4gIGNvbnN0IGZlZWRMaW5rcyA9IGNvbmZpZy5zaXRlXG4gICAgPyAoY29uZmlnLnNlY3Rpb25zID8/IFtdKVxuICAgICAgICAuZmlsdGVyKHMgPT4gcy50eXBlID09PSBcImJsb2dcIilcbiAgICAgICAgLm1hcChzID0+ICh7XG4gICAgICAgICAgcmVsOiBcImFsdGVybmF0ZVwiLFxuICAgICAgICAgIHR5cGU6IFwiYXBwbGljYXRpb24vcnNzK3htbFwiLFxuICAgICAgICAgIHRpdGxlOiBgJHtzLnNpdGVUaXRsZSA/PyBzLnRpdGxlfSBSU1MgRmVlZGAsXG4gICAgICAgICAgaHJlZjogcHJlZml4VXJsKGAke3MucHJlZml4fXJzcy54bWxgLCBjb25maWcuYmFzZSksXG4gICAgICAgIH0pKVxuICAgIDogW11cbiAgcmV0dXJuIHtcbiAgICBtZXRhOiBbXG4gICAgICB7IGNoYXJTZXQ6IFwidXRmLThcIiB9LFxuICAgICAgeyB0aXRsZTogY29uZmlnLnRpdGxlIH0sXG4gICAgICB7IG5hbWU6IFwiZGVzY3JpcHRpb25cIiwgY29udGVudDogY29uZmlnLmRlc2NyaXB0aW9uIH0sXG4gICAgICB7IHByb3BlcnR5OiBcIm9nOnRpdGxlXCIsIGNvbnRlbnQ6IGNvbmZpZy50aXRsZSB9LFxuICAgICAgeyBwcm9wZXJ0eTogXCJvZzpkZXNjcmlwdGlvblwiLCBjb250ZW50OiBjb25maWcuZGVzY3JpcHRpb24gfSxcbiAgICAgIHsgcHJvcGVydHk6IFwib2c6c2l0ZV9uYW1lXCIsIGNvbnRlbnQ6IGNvbmZpZy50aXRsZSB9LFxuICAgICAgeyBwcm9wZXJ0eTogXCJvZzp0eXBlXCIsIGNvbnRlbnQ6IFwid2Vic2l0ZVwiIH0sXG4gICAgICB7IG5hbWU6IFwidmlld3BvcnRcIiwgY29udGVudDogXCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MVwiIH0sXG4gICAgICAuLi4oY29uZmlnLmhlYWQ/Lm1ldGEgPz8gW10pLFxuICAgIF0sXG4gICAgbGlua3M6IFtcbiAgICAgIHsgcmVsOiBcImljb25cIiwgaHJlZjogZmF2aWNvbiwgdHlwZTogZmF2aWNvblR5cGUoZmF2aWNvbikgfSxcbiAgICAgIHsgcmVsOiBcInNob3J0Y3V0IGljb25cIiwgaHJlZjogZmF2aWNvbiwgdHlwZTogZmF2aWNvblR5cGUoZmF2aWNvbikgfSxcbiAgICAgIC4uLnByb3BzLnN0eWxlc2hlZXRzLm1hcChocmVmID0+ICh7IHJlbDogXCJzdHlsZXNoZWV0XCIsIGhyZWYgfSkpLFxuICAgICAgLi4uZmVlZExpbmtzLFxuICAgICAgLi4uKGNvbmZpZy5oZWFkPy5saW5rcyA/PyBbXSksXG4gICAgXSxcbiAgICBzY3JpcHRzOiBbeyBjaGlsZHJlbjogYnVpbGRUaGVtZVNjcmlwdCgpIH0sIC4uLihjb25maWcuaGVhZD8uc2NyaXB0cyA/PyBbXSldLFxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFBhZ2VIZWFkKHByb3BzOiB7XG4gIGNvbmZpZzogV2Vic2l0ZUNvbmZpZ1xuICBwYXRoOiBzdHJpbmdcbiAgdGl0bGU/OiBzdHJpbmdcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgaW1hZ2U/OiBzdHJpbmdcbiAgaXNBcnRpY2xlPzogYm9vbGVhblxufSkge1xuICBjb25zdCBzaXRlID0gcHJvcHMuY29uZmlnLnNpdGU/LnJlcGxhY2UoL1xcLyskLywgXCJcIilcbiAgY29uc3QgdXJsID0gc2l0ZSA/IGJ1aWxkQWJzb2x1dGVVcmwoc2l0ZSwgcHJvcHMuY29uZmlnLmJhc2UsIHByb3BzLnBhdGgpIDogdW5kZWZpbmVkXG4gIGNvbnN0IGltYWdlID1cbiAgICBzaXRlICYmIHByb3BzLmltYWdlXG4gICAgICA/IGJ1aWxkQWJzb2x1dGVVcmwoc2l0ZSwgcHJvcHMuY29uZmlnLmJhc2UsIHByb3BzLmltYWdlKVxuICAgICAgOiB1bmRlZmluZWRcbiAgcmV0dXJuIHtcbiAgICBtZXRhOiBbXG4gICAgICAuLi4ocHJvcHMudGl0bGVcbiAgICAgICAgPyBbeyB0aXRsZTogcHJvcHMudGl0bGUgfSwgeyBwcm9wZXJ0eTogXCJvZzp0aXRsZVwiLCBjb250ZW50OiBwcm9wcy50aXRsZSB9XVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLihwcm9wcy5kZXNjcmlwdGlvblxuICAgICAgICA/IFtcbiAgICAgICAgICAgIHsgbmFtZTogXCJkZXNjcmlwdGlvblwiLCBjb250ZW50OiBwcm9wcy5kZXNjcmlwdGlvbiB9LFxuICAgICAgICAgICAgeyBwcm9wZXJ0eTogXCJvZzpkZXNjcmlwdGlvblwiLCBjb250ZW50OiBwcm9wcy5kZXNjcmlwdGlvbiB9LFxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXSksXG4gICAgICAuLi4ocHJvcHMuaXNBcnRpY2xlID8gW3sgcHJvcGVydHk6IFwib2c6dHlwZVwiLCBjb250ZW50OiBcImFydGljbGVcIiB9XSA6IFtdKSxcbiAgICAgIC4uLih1cmwgPyBbeyBwcm9wZXJ0eTogXCJvZzp1cmxcIiwgY29udGVudDogdXJsIH1dIDogW10pLFxuICAgICAgLi4uKGltYWdlID8gW3sgcHJvcGVydHk6IFwib2c6aW1hZ2VcIiwgY29udGVudDogaW1hZ2UgfV0gOiBbXSksXG4gICAgXSxcbiAgICBsaW5rczogW1xuICAgICAgLi4uKHVybCA/IFt7IHJlbDogXCJjYW5vbmljYWxcIiwgaHJlZjogdXJsIH1dIDogW10pLFxuICAgICAgLi4uKHByb3BzLmlzQXJ0aWNsZVxuICAgICAgICA/IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcmVsOiBcImFsdGVybmF0ZVwiLFxuICAgICAgICAgICAgICB0eXBlOiBcInRleHQvbWFya2Rvd25cIixcbiAgICAgICAgICAgICAgaHJlZjogcHJlZml4VXJsKGAke3Byb3BzLnBhdGh9aW5kZXgubWRgLCBwcm9wcy5jb25maWcuYmFzZSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXSksXG4gICAgXSxcbiAgfVxufVxuXG5mdW5jdGlvbiBidWlsZEFic29sdXRlVXJsKHNpdGU6IHN0cmluZywgYmFzZTogc3RyaW5nIHwgdW5kZWZpbmVkLCB1cmw6IHN0cmluZykge1xuICBjb25zdCBwcmVmaXhlZCA9IHByZWZpeFVybCh1cmwsIGJhc2UpXG4gIGlmICghcHJlZml4ZWQuc3RhcnRzV2l0aChcIi9cIikgfHwgcHJlZml4ZWQuc3RhcnRzV2l0aChcIi8vXCIpKSByZXR1cm4gcHJlZml4ZWRcbiAgcmV0dXJuIGAke3NpdGV9JHtwcmVmaXhlZH1gXG59XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,110 @@
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
+ { rel: "alternate", type: "text/markdown", href: "/guide/index.md" },
78
+ ]);
79
+ });
80
+ it("adds absolute url, canonical and image when site is set", () => {
81
+ const head = buildPageHead({
82
+ config: { ...config, site: "https://example.com/", base: "/repo" },
83
+ path: "/guide/",
84
+ image: "/repo/assets/cover.png",
85
+ });
86
+ expect(head.meta).toEqual([
87
+ { property: "og:url", content: "https://example.com/repo/guide/" },
88
+ { property: "og:image", content: "https://example.com/repo/assets/cover.png" },
89
+ ]);
90
+ expect(head.links).toEqual([
91
+ { rel: "canonical", href: "https://example.com/repo/guide/" },
92
+ ]);
93
+ });
94
+ it("keeps an already absolute image", () => {
95
+ const head = buildPageHead({
96
+ config: { ...config, site: "https://example.com" },
97
+ path: "/",
98
+ image: "https://cdn.example.com/cover.png",
99
+ });
100
+ expect(head.meta).toContainEqual({
101
+ property: "og:image",
102
+ content: "https://cdn.example.com/cover.png",
103
+ });
104
+ });
105
+ it("skips og:image without site", () => {
106
+ const head = buildPageHead({ config, path: "/", image: "/cover.png" });
107
+ expect(head.meta).toEqual([]);
108
+ });
109
+ });
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZC51bml0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvaGVhZC51bml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRXJELE9BQU8sRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRXhELE1BQU0sTUFBTSxHQUFrQixFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFBO0FBRXJFLFFBQVEsQ0FBQyxlQUFlLEVBQUUsR0FBRyxFQUFFO0lBQzdCLEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxHQUFHLEVBQUU7UUFDdEMsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDO1lBQ3pCLE1BQU07WUFDTixjQUFjLEVBQUUsV0FBVztZQUMzQixXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUM7U0FDeEIsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxjQUFjLENBQUMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQzNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsY0FBYyxDQUFDO1lBQ2hDLEdBQUcsRUFBRSxNQUFNO1lBQ1gsSUFBSSxFQUFFLFdBQVc7WUFDakIsSUFBSSxFQUFFLGVBQWU7U0FDdEIsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxjQUFjLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFBO1FBQ3hFLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3RD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QUFPLENBQUM7WUFDekIsRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxpQ0FBaUMsRUFBRTtTQUM5RCxDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRSxHQUFHLEVBQUU7UUFDekMsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDO1lBQ3pCLE1BQU0sRUFBRSxFQUFFLEdBQUcsTUFBTSxFQUFFLElBQUksRUFBRSxxQkFBcUIsRUFBRTtZQUNsRCxJQUFJLEVBQUUsR0FBRztZQUNULEtBQUssRUFBRSxtQ0FBbUM7U0FDM0MsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxjQUFjLENBQUM7WUFDL0IsUUFBUSxFQUFFLFVBQVU7WUFDcEIsT0FBTyxFQUFFLG1DQUFtQztTQUM3QyxDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUU7UUFDckMsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUE7UUFDdEUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDL0IsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGUtcGx1cy90ZXN0XCJcbmltcG9ydCB0eXBlIHsgV2Vic2l0ZUNvbmZpZyB9IGZyb20gXCIuLi9tb2RlbHMvY29uZmlnLnRzXCJcbmltcG9ydCB7IGJ1aWxkUGFnZUhlYWQsIGJ1aWxkUm9vdEhlYWQgfSBmcm9tIFwiLi9oZWFkLnRzXCJcblxuY29uc3QgY29uZmlnOiBXZWJzaXRlQ29uZmlnID0geyB0aXRsZTogXCJEb2NzXCIsIGRlc2NyaXB0aW9uOiBcIkJsdXJiXCIgfVxuXG5kZXNjcmliZShcImJ1aWxkUm9vdEhlYWRcIiwgKCkgPT4ge1xuICBpdChcImJ1aWxkcyB0aGUgZGVmYXVsdCBzaXRlIHRhZ3NcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGhlYWQgPSBidWlsZFJvb3RIZWFkKHtcbiAgICAgIGNvbmZpZyxcbiAgICAgIGRlZmF1bHRGYXZpY29uOiBcIi9sb2dvLnN2Z1wiLFxuICAgICAgc3R5bGVzaGVldHM6IFtcIi9hLmNzc1wiXSxcbiAgICB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEpLnRvQ29udGFpbkVxdWFsKHsgcHJvcGVydHk6IFwib2c6dGl0bGVcIiwgY29udGVudDogXCJEb2NzXCIgfSlcbiAgICBleHBlY3QoaGVhZC5saW5rcykudG9Db250YWluRXF1YWwoe1xuICAgICAgcmVsOiBcImljb25cIixcbiAgICAgIGhyZWY6IFwiL2xvZ28uc3ZnXCIsXG4gICAgICB0eXBlOiBcImltYWdlL3N2Zyt4bWxcIixcbiAgICB9KVxuICAgIGV4cGVjdChoZWFkLmxpbmtzKS50b0NvbnRhaW5FcXVhbCh7IHJlbDogXCJzdHlsZXNoZWV0XCIsIGhyZWY6IFwiL2EuY3NzXCIgfSlcbiAgICBleHBlY3QoaGVhZC5zY3JpcHRzKS50b0hhdmVMZW5ndGgoMSlcbiAgfSlcblxuICBpdChcImFwcGVuZHMgY29uZmlnIGhlYWQgdGFncyBhZnRlciB0aGUgZGVmYXVsdHNcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGhlYWQgPSBidWlsZFJvb3RIZWFkKHtcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICAuLi5jb25maWcsXG4gICAgICAgIGhlYWQ6IHtcbiAgICAgICAgICBtZXRhOiBbeyBwcm9wZXJ0eTogXCJvZzp0eXBlXCIsIGNvbnRlbnQ6IFwiYm9va1wiIH1dLFxuICAgICAgICAgIGxpbmtzOiBbeyByZWw6IFwibWVcIiwgaHJlZjogXCJodHRwczovL3guY29tL21lXCIgfV0sXG4gICAgICAgICAgc2NyaXB0czogW3sgc3JjOiBcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tL2EuanNcIiB9XSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBkZWZhdWx0RmF2aWNvbjogXCIvbG9nby5zdmdcIixcbiAgICAgIHN0eWxlc2hlZXRzOiBbXSxcbiAgICB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEuYXQoLTEpKS50b0VxdWFsKHsgcHJvcGVydHk6IFwib2c6dHlwZVwiLCBjb250ZW50OiBcImJvb2tcIiB9KVxuICAgIGV4cGVjdChoZWFkLmxpbmtzLmF0KC0xKSkudG9FcXVhbCh7IHJlbDogXCJtZVwiLCBocmVmOiBcImh0dHBzOi8veC5jb20vbWVcIiB9KVxuICAgIGV4cGVjdChoZWFkLnNjcmlwdHMuYXQoLTEpKS50b0VxdWFsKHsgc3JjOiBcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tL2EuanNcIiB9KVxuICB9KVxuXG4gIGl0KFwibGlua3MgYmxvZyBmZWVkcyBvbmx5IHdoZW4gc2l0ZSBpcyBzZXRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHNlY3Rpb25zOiBXZWJzaXRlQ29uZmlnW1wic2VjdGlvbnNcIl0gPSBbXG4gICAgICB7IHR5cGU6IFwiYmxvZ1wiLCB0aXRsZTogXCJCbG9nXCIsIHByZWZpeDogXCIvYmxvZy9cIiwgcG9zaXRpb246IFwiaGVhZGVyXCIgfSxcbiAgICBdXG4gICAgY29uc3Qgd2l0aG91dFNpdGUgPSBidWlsZFJvb3RIZWFkKHtcbiAgICAgIGNvbmZpZzogeyAuLi5jb25maWcsIHNlY3Rpb25zIH0sXG4gICAgICBkZWZhdWx0RmF2aWNvbjogXCIvbG9nby5zdmdcIixcbiAgICAgIHN0eWxlc2hlZXRzOiBbXSxcbiAgICB9KVxuICAgIGNvbnN0IHdpdGhTaXRlID0gYnVpbGRSb290SGVhZCh7XG4gICAgICBjb25maWc6IHsgLi4uY29uZmlnLCBzZWN0aW9ucywgc2l0ZTogXCJodHRwczovL2V4YW1wbGUuY29tXCIsIGJhc2U6IFwiL3JlcG9cIiB9LFxuICAgICAgZGVmYXVsdEZhdmljb246IFwiL2xvZ28uc3ZnXCIsXG4gICAgICBzdHlsZXNoZWV0czogW10sXG4gICAgfSlcbiAgICBleHBlY3Qod2l0aG91dFNpdGUubGlua3Muc29tZShsID0+IGwucmVsID09PSBcImFsdGVybmF0ZVwiKSkudG9CZShmYWxzZSlcbiAgICBleHBlY3Qod2l0aFNpdGUubGlua3MpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgIHJlbDogXCJhbHRlcm5hdGVcIixcbiAgICAgIHR5cGU6IFwiYXBwbGljYXRpb24vcnNzK3htbFwiLFxuICAgICAgdGl0bGU6IFwiQmxvZyBSU1MgRmVlZFwiLFxuICAgICAgaHJlZjogXCIvcmVwby9ibG9nL3Jzcy54bWxcIixcbiAgICB9KVxuICB9KVxufSlcblxuZGVzY3JpYmUoXCJidWlsZFBhZ2VIZWFkXCIsICgpID0+IHtcbiAgaXQoXCJlbWl0cyB0aXRsZSwgZGVzY3JpcHRpb24gYW5kIGFydGljbGUgdHlwZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgaGVhZCA9IGJ1aWxkUGFnZUhlYWQoe1xuICAgICAgY29uZmlnLFxuICAgICAgcGF0aDogXCIvZ3VpZGUvXCIsXG4gICAgICB0aXRsZTogXCJHdWlkZVwiLFxuICAgICAgZGVzY3JpcHRpb246IFwiSG93IHRvXCIsXG4gICAgICBpc0FydGljbGU6IHRydWUsXG4gICAgfSlcbiAgICBleHBlY3QoaGVhZC5tZXRhKS50b0VxdWFsKFtcbiAgICAgIHsgdGl0bGU6IFwiR3VpZGVcIiB9LFxuICAgICAgeyBwcm9wZXJ0eTogXCJvZzp0aXRsZVwiLCBjb250ZW50OiBcIkd1aWRlXCIgfSxcbiAgICAgIHsgbmFtZTogXCJkZXNjcmlwdGlvblwiLCBjb250ZW50OiBcIkhvdyB0b1wiIH0sXG4gICAgICB7IHByb3BlcnR5OiBcIm9nOmRlc2NyaXB0aW9uXCIsIGNvbnRlbnQ6IFwiSG93IHRvXCIgfSxcbiAgICAgIHsgcHJvcGVydHk6IFwib2c6dHlwZVwiLCBjb250ZW50OiBcImFydGljbGVcIiB9LFxuICAgIF0pXG4gICAgZXhwZWN0KGhlYWQubGlua3MpLnRvRXF1YWwoW1xuICAgICAgeyByZWw6IFwiYWx0ZXJuYXRlXCIsIHR5cGU6IFwidGV4dC9tYXJrZG93blwiLCBocmVmOiBcIi9ndWlkZS9pbmRleC5tZFwiIH0sXG4gICAgXSlcbiAgfSlcblxuICBpdChcImFkZHMgYWJzb2x1dGUgdXJsLCBjYW5vbmljYWwgYW5kIGltYWdlIHdoZW4gc2l0ZSBpcyBzZXRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGhlYWQgPSBidWlsZFBhZ2VIZWFkKHtcbiAgICAgIGNvbmZpZzogeyAuLi5jb25maWcsIHNpdGU6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9cIiwgYmFzZTogXCIvcmVwb1wiIH0sXG4gICAgICBwYXRoOiBcIi9ndWlkZS9cIixcbiAgICAgIGltYWdlOiBcIi9yZXBvL2Fzc2V0cy9jb3Zlci5wbmdcIixcbiAgICB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEpLnRvRXF1YWwoW1xuICAgICAgeyBwcm9wZXJ0eTogXCJvZzp1cmxcIiwgY29udGVudDogXCJodHRwczovL2V4YW1wbGUuY29tL3JlcG8vZ3VpZGUvXCIgfSxcbiAgICAgIHsgcHJvcGVydHk6IFwib2c6aW1hZ2VcIiwgY29udGVudDogXCJodHRwczovL2V4YW1wbGUuY29tL3JlcG8vYXNzZXRzL2NvdmVyLnBuZ1wiIH0sXG4gICAgXSlcbiAgICBleHBlY3QoaGVhZC5saW5rcykudG9FcXVhbChbXG4gICAgICB7IHJlbDogXCJjYW5vbmljYWxcIiwgaHJlZjogXCJodHRwczovL2V4YW1wbGUuY29tL3JlcG8vZ3VpZGUvXCIgfSxcbiAgICBdKVxuICB9KVxuXG4gIGl0KFwia2VlcHMgYW4gYWxyZWFkeSBhYnNvbHV0ZSBpbWFnZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgaGVhZCA9IGJ1aWxkUGFnZUhlYWQoe1xuICAgICAgY29uZmlnOiB7IC4uLmNvbmZpZywgc2l0ZTogXCJodHRwczovL2V4YW1wbGUuY29tXCIgfSxcbiAgICAgIHBhdGg6IFwiL1wiLFxuICAgICAgaW1hZ2U6IFwiaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vY292ZXIucG5nXCIsXG4gICAgfSlcbiAgICBleHBlY3QoaGVhZC5tZXRhKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICBwcm9wZXJ0eTogXCJvZzppbWFnZVwiLFxuICAgICAgY29udGVudDogXCJodHRwczovL2Nkbi5leGFtcGxlLmNvbS9jb3Zlci5wbmdcIixcbiAgICB9KVxuICB9KVxuXG4gIGl0KFwic2tpcHMgb2c6aW1hZ2Ugd2l0aG91dCBzaXRlXCIsICgpID0+IHtcbiAgICBjb25zdCBoZWFkID0gYnVpbGRQYWdlSGVhZCh7IGNvbmZpZywgcGF0aDogXCIvXCIsIGltYWdlOiBcIi9jb3Zlci5wbmdcIiB9KVxuICAgIGV4cGVjdChoZWFkLm1ldGEpLnRvRXF1YWwoW10pXG4gIH0pXG59KVxuIl19
@@ -0,0 +1,33 @@
1
+ import type { Config } from "../models/config.ts";
2
+ import type { RoutedSection } from "../models/section.ts";
3
+ /** The slice of a built article that agent-facing files are rendered from. */
4
+ export interface LlmsArticle {
5
+ path: string;
6
+ title: string;
7
+ description?: string;
8
+ order?: number;
9
+ date?: string;
10
+ }
11
+ /** Render `llms.txt`: the site title and description, then one Markdown link
12
+ * per article twin, grouped under each routed section in sidebar order. */
13
+ export declare function renderLlmsText(props: {
14
+ config: Pick<Config, "title" | "description" | "site" | "base" | "sections">;
15
+ articles: LlmsArticle[];
16
+ }): string;
17
+ /** Render the Markdown twin of a section's index page (a blog or changelog
18
+ * listing), which has no article of its own: links to the section's articles. */
19
+ export declare function renderSectionIndex(props: {
20
+ config: Pick<Config, "site" | "base" | "sections">;
21
+ section: RoutedSection;
22
+ articles: LlmsArticle[];
23
+ }): string;
24
+ /** Render the Markdown twin of an article: its title and description as the
25
+ * rendered page shows them, then the body without its own leading h1. */
26
+ export declare function renderMarkdownTwin(props: {
27
+ article: LlmsArticle;
28
+ content: string;
29
+ }): string;
30
+ /** Path of an article's Markdown twin inside the build output (no base). */
31
+ export declare function buildTwinFileName(path: string): string;
32
+ /** Drop a leading h1 so a title set by frontmatter or a patch is not shown twice */
33
+ export declare function stripLeadingH1(content: string): string;
@@ -0,0 +1,72 @@
1
+ import { buildArticleTree, compareArticleDate, compareArticleOrder, flattenArticleTree, } from "./article.js";
2
+ import { partitionBySection } from "./section.js";
3
+ /** Render `llms.txt`: the site title and description, then one Markdown link
4
+ * per article twin, grouped under each routed section in sidebar order. */
5
+ export function renderLlmsText(props) {
6
+ const lines = [`# ${props.config.title}`, "", `> ${props.config.description}`];
7
+ for (const group of groupArticles(props)) {
8
+ lines.push("", `## ${group.title}`, "", ...renderLinks(props.config, group.articles));
9
+ }
10
+ return `${lines.join("\n")}\n`;
11
+ }
12
+ /** Render the Markdown twin of a section's index page (a blog or changelog
13
+ * listing), which has no article of its own: links to the section's articles. */
14
+ export function renderSectionIndex(props) {
15
+ const group = groupArticles(props).find(g => g.prefix === props.section.prefix);
16
+ const lines = [
17
+ `# ${props.section.title}`,
18
+ "",
19
+ ...renderLinks(props.config, group?.articles ?? []),
20
+ ];
21
+ return `${lines.join("\n")}\n`;
22
+ }
23
+ /** Render the Markdown twin of an article: its title and description as the
24
+ * rendered page shows them, then the body without its own leading h1. */
25
+ export function renderMarkdownTwin(props) {
26
+ const article = props.article;
27
+ const parts = [`# ${article.title}`];
28
+ if (article.description)
29
+ parts.push(`> ${article.description}`);
30
+ parts.push(stripLeadingH1(props.content).trim());
31
+ return `${parts.join("\n\n")}\n`;
32
+ }
33
+ /** Path of an article's Markdown twin inside the build output (no base). */
34
+ export function buildTwinFileName(path) {
35
+ return `${path.replace(/^\//, "")}index.md`;
36
+ }
37
+ /** Drop a leading h1 so a title set by frontmatter or a patch is not shown twice */
38
+ export function stripLeadingH1(content) {
39
+ return content.replace(/^[ \t]*#\s+[^\n]*\n+/, "");
40
+ }
41
+ function buildTwinUrl(config, path) {
42
+ const host = config.site?.replace(/\/+$/, "") ?? "";
43
+ return `${host}${config.base ?? ""}${path}index.md`;
44
+ }
45
+ function groupArticles(props) {
46
+ const sections = props.config.sections?.filter((s) => s.type !== "custom") ?? [];
47
+ const buckets = partitionBySection([...props.articles].sort(compareArticleOrder), sections);
48
+ const groups = [
49
+ ...sections.map(s => ({
50
+ prefix: s.prefix,
51
+ title: s.title,
52
+ dated: s.type !== "article",
53
+ })),
54
+ { prefix: "__default__", title: sections.length ? "Other" : "Pages", dated: false },
55
+ ];
56
+ return groups.flatMap(group => {
57
+ const bucket = buckets.get(group.prefix);
58
+ if (!bucket?.length)
59
+ return [];
60
+ const articles = group.dated
61
+ ? [...bucket].sort(compareArticleDate)
62
+ : flattenArticleTree(buildArticleTree(bucket)).flatMap(path => bucket.find(a => a.path === path) ?? []);
63
+ return [{ prefix: group.prefix, title: group.title, articles }];
64
+ });
65
+ }
66
+ function renderLinks(config, articles) {
67
+ return articles.map(article => {
68
+ const link = `[${article.title}](${buildTwinUrl(config, article.path)})`;
69
+ return article.description ? `- ${link}: ${article.description}` : `- ${link}`;
70
+ });
71
+ }
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGxtcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9oZWxwZXJzL2xsbXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixrQkFBa0IsRUFDbEIsbUJBQW1CLEVBQ25CLGtCQUFrQixHQUNuQixNQUFNLGNBQWMsQ0FBQTtBQUNyQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFXakQ7NEVBQzRFO0FBQzVFLE1BQU0sVUFBVSxjQUFjLENBQUMsS0FHOUI7SUFDQyxNQUFNLEtBQUssR0FBRyxDQUFDLEtBQUssS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUE7SUFDOUUsS0FBSyxNQUFNLEtBQUssSUFBSSxhQUFhLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxNQUFNLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQTtJQUN2RixDQUFDO0lBQ0QsT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQTtBQUNoQyxDQUFDO0FBRUQ7a0ZBQ2tGO0FBQ2xGLE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxLQUlsQztJQUNDLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDL0UsTUFBTSxLQUFLLEdBQUc7UUFDWixLQUFLLEtBQUssQ0FBQyxPQUFPLENB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QUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUM7WUFDdEMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUNsRCxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FDaEQsQ0FBQTtRQUNMLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDakUsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsTUFBcUMsRUFBRSxRQUF1QjtJQUNqRixPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDNUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUE7UUFDeEUsT0FBTyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksS0FBSyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUE7SUFDaEYsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBDb25maWcgfSBmcm9tIFwiLi4vbW9kZWxzL2NvbmZpZy50c1wiXG5pbXBvcnQgdHlwZSB7IFJvdXRlZFNlY3Rpb24gfSBmcm9tIFwiLi4vbW9kZWxzL3NlY3Rpb24udHNcIlxuaW1wb3J0IHtcbiAgYnVpbGRBcnRpY2xlVHJlZSxcbiAgY29tcGFyZUFydGljbGVEYXRlLFxuICBjb21wYXJlQXJ0aWNsZU9yZGVyLFxuICBmbGF0dGVuQXJ0aWNsZVRyZWUsXG59IGZyb20gXCIuL2FydGljbGUudHNcIlxuaW1wb3J0IHsgcGFydGl0aW9uQnlTZWN0aW9uIH0gZnJvbSBcIi4vc2VjdGlvbi50c1wiXG5cbi8qKiBUaGUgc2xpY2Ugb2YgYSBidWlsdCBhcnRpY2xlIHRoYXQgYWdlbnQtZmFjaW5nIGZpbGVzIGFyZSByZW5kZXJlZCBmcm9tLiAqL1xuZXhwb3J0IGludGVyZmFjZSBMbG1zQXJ0aWNsZSB7XG4gIHBhdGg6IHN0cmluZ1xuICB0aXRsZTogc3RyaW5nXG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nXG4gIG9yZGVyPzogbnVtYmVyXG4gIGRhdGU/OiBzdHJpbmdcbn1cblxuLyoqIFJlbmRlciBgbGxtcy50eHRgOiB0aGUgc2l0ZSB0aXRsZSBhbmQgZGVzY3JpcHRpb24sIHRoZW4gb25lIE1hcmtkb3duIGxpbmtcbiAqICBwZXIgYXJ0aWNsZSB0d2luLCBncm91cGVkIHVuZGVyIGVhY2ggcm91dGVkIHNlY3Rpb24gaW4gc2lkZWJhciBvcmRlci4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJMbG1zVGV4dChwcm9wczoge1xuICBjb25maWc6IFBpY2s8Q29uZmlnLCBcInRpdGxlXCIgfCBcImRlc2NyaXB0aW9uXCIgfCBcInNpdGVcIiB8IFwiYmFzZVwiIHwgXCJzZWN0aW9uc1wiPlxuICBhcnRpY2xlczogTGxtc0FydGljbGVbXVxufSkge1xuICBjb25zdCBsaW5lcyA9IFtgIyAke3Byb3BzLmNvbmZpZy50aXRsZX1gLCBcIlwiLCBgPiAke3Byb3BzLmNvbmZpZy5kZXNjcmlwdGlvbn1gXVxuICBmb3IgKGNvbnN0IGdyb3VwIG9mIGdyb3VwQXJ0aWNsZXMocHJvcHMpKSB7XG4gICAgbGluZXMucHVzaChcIlwiLCBgIyMgJHtncm91cC50aXRsZX1gLCBcIlwiLCAuLi5yZW5kZXJMaW5rcyhwcm9wcy5jb25maWcsIGdyb3VwLmFydGljbGVzKSlcbiAgfVxuICByZXR1cm4gYCR7bGluZXMuam9pbihcIlxcblwiKX1cXG5gXG59XG5cbi8qKiBSZW5kZXIgdGhlIE1hcmtkb3duIHR3aW4gb2YgYSBzZWN0aW9uJ3MgaW5kZXggcGFnZSAoYSBibG9nIG9yIGNoYW5nZWxvZ1xuICogIGxpc3RpbmcpLCB3aGljaCBoYXMgbm8gYXJ0aWNsZSBvZiBpdHMgb3duOiBsaW5rcyB0byB0aGUgc2VjdGlvbidzIGFydGljbGVzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclNlY3Rpb25JbmRleChwcm9wczoge1xuICBjb25maWc6IFBpY2s8Q29uZmlnLCBcInNpdGVcIiB8IFwiYmFzZVwiIHwgXCJzZWN0aW9uc1wiPlxuICBzZWN0aW9uOiBSb3V0ZWRTZWN0aW9uXG4gIGFydGljbGVzOiBMbG1zQXJ0aWNsZVtdXG59KSB7XG4gIGNvbnN0IGdyb3VwID0gZ3JvdXBBcnRpY2xlcyhwcm9wcykuZmluZChnID0+IGcucHJlZml4ID09PSBwcm9wcy5zZWN0aW9uLnByZWZpeClcbiAgY29uc3QgbGluZXMgPSBbXG4gICAgYCMgJHtwcm9wcy5zZWN0aW9uLnRpdGxlfWAsXG4gICAgXCJcIixcbiAgICAuLi5yZW5kZXJMaW5rcyhwcm9wcy5jb25maWcsIGdyb3VwPy5hcnRpY2xlcyA/PyBbXSksXG4gIF1cbiAgcmV0dXJuIGAke2xpbmVzLmpvaW4oXCJcXG5cIil9XFxuYFxufVxuXG4vKiogUmVuZGVyIHRoZSBNYXJrZG93biB0d2luIG9mIGFuIGFydGljbGU6IGl0cyB0aXRsZSBhbmQgZGVzY3JpcHRpb24gYXMgdGhlXG4gKiAgcmVuZGVyZWQgcGFnZSBzaG93cyB0aGVtLCB0aGVuIHRoZSBib2R5IHdpdGhvdXQgaXRzIG93biBsZWFkaW5nIGgxLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlck1hcmtkb3duVHdpbihwcm9wczogeyBhcnRpY2xlOiBMbG1zQXJ0aWNsZTsgY29udGVudDogc3RyaW5nIH0pIHtcbiAgY29uc3QgYXJ0aWNsZSA9IHByb3BzLmFydGljbGVcbiAgY29uc3QgcGFydHMgPSBbYCMgJHthcnRpY2xlLnRpdGxlfWBdXG4gIGlmIChhcnRpY2xlLmRlc2NyaXB0aW9uKSBwYXJ0cy5wdXNoKGA+ICR7YXJ0aWNsZS5kZXNjcmlwdGlvbn1gKVxuICBwYXJ0cy5wdXNoKHN0cmlwTGVhZGluZ0gxKHByb3BzLmNvbnRlbnQpLnRyaW0oKSlcbiAgcmV0dXJuIGAke3BhcnRzLmpvaW4oXCJcXG5cXG5cIil9XFxuYFxufVxuXG4vKiogUGF0aCBvZiBhbiBhcnRpY2xlJ3MgTWFya2Rvd24gdHdpbiBpbnNpZGUgdGhlIGJ1aWxkIG91dHB1dCAobm8gYmFzZSkuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRUd2luRmlsZU5hbWUocGF0aDogc3RyaW5nKSB7XG4gIHJldHVybiBgJHtwYXRoLnJlcGxhY2UoL15cXC8vLCBcIlwiKX1pbmRleC5tZGBcbn1cblxuLyoqIERyb3AgYSBsZWFkaW5nIGgxIHNvIGEgdGl0bGUgc2V0IGJ5IGZyb250bWF0dGVyIG9yIGEgcGF0Y2ggaXMgbm90IHNob3duIHR3aWNlICovXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBMZWFkaW5nSDEoY29udGVudDogc3RyaW5nKSB7XG4gIHJldHVybiBjb250ZW50LnJlcGxhY2UoL15bIFxcdF0qI1xccytbXlxcbl0qXFxuKy8sIFwiXCIpXG59XG5cbmZ1bmN0aW9uIGJ1aWxkVHdpblVybChjb25maWc6IFBpY2s8Q29uZmlnLCBcInNpdGVcIiB8IFwiYmFzZVwiPiwgcGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IGhvc3QgPSBjb25maWcuc2l0ZT8ucmVwbGFjZSgvXFwvKyQvLCBcIlwiKSA/PyBcIlwiXG4gIHJldHVybiBgJHtob3N0fSR7Y29uZmlnLmJhc2UgPz8gXCJcIn0ke3BhdGh9aW5kZXgubWRgXG59XG5cbmZ1bmN0aW9uIGdyb3VwQXJ0aWNsZXMocHJvcHM6IHtcbiAgY29uZmlnOiBQaWNrPENvbmZpZywgXCJzZWN0aW9uc1wiPlxuICBhcnRpY2xlczogTGxtc0FydGljbGVbXVxufSkge1xuICBjb25zdCBzZWN0aW9ucyA9XG4gICAgcHJvcHMuY29uZmlnLnNlY3Rpb25zPy5maWx0ZXIoKHMpOiBzIGlzIFJvdXRlZFNlY3Rpb24gPT4gcy50eXBlICE9PSBcImN1c3RvbVwiKSA/PyBbXVxuICBjb25zdCBidWNrZXRzID0gcGFydGl0aW9uQnlTZWN0aW9uKFxuICAgIFsuLi5wcm9wcy5hcnRpY2xlc10uc29ydChjb21wYXJlQXJ0aWNsZU9yZGVyKSxcbiAgICBzZWN0aW9ucyxcbiAgKVxuICBjb25zdCBncm91cHMgPSBbXG4gICAgLi4uc2VjdGlvbnMubWFwKHMgPT4gKHtcbiAgICAgIHByZWZpeDogcy5wcmVmaXgsXG4gICAgICB0aXRsZTogcy50aXRsZSxcbiAgICAgIGRhdGVkOiBzLnR5cGUgIT09IFwiYXJ0aWNsZVwiLFxuICAgIH0pKSxcbiAgICB7IHByZWZpeDogXCJfX2RlZmF1bHRfX1wiLCB0aXRsZTogc2VjdGlvbnMubGVuZ3RoID8gXCJPdGhlclwiIDogXCJQYWdlc1wiLCBkYXRlZDogZmFsc2UgfSxcbiAgXVxuICByZXR1cm4gZ3JvdXBzLmZsYXRNYXAoZ3JvdXAgPT4ge1xuICAgIGNvbnN0IGJ1Y2tldCA9IGJ1Y2tldHMuZ2V0KGdyb3VwLnByZWZpeClcbiAgICBpZiAoIWJ1Y2tldD8ubGVuZ3RoKSByZXR1cm4gW11cbiAgICBjb25zdCBhcnRpY2xlcyA9IGdyb3VwLmRhdGVkXG4gICAgICA/IFsuLi5idWNrZXRdLnNvcnQoY29tcGFyZUFydGljbGVEYXRlKVxuICAgICAgOiBmbGF0dGVuQXJ0aWNsZVRyZWUoYnVpbGRBcnRpY2xlVHJlZShidWNrZXQpKS5mbGF0TWFwKFxuICAgICAgICAgIHBhdGggPT4gYnVja2V0LmZpbmQoYSA9PiBhLnBhdGggPT09IHBhdGgpID8/IFtdLFxuICAgICAgICApXG4gICAgcmV0dXJuIFt7IHByZWZpeDogZ3JvdXAucHJlZml4LCB0aXRsZTogZ3JvdXAudGl0bGUsIGFydGljbGVzIH1dXG4gIH0pXG59XG5cbmZ1bmN0aW9uIHJlbmRlckxpbmtzKGNvbmZpZzogUGljazxDb25maWcsIFwic2l0ZVwiIHwgXCJiYXNlXCI+LCBhcnRpY2xlczogTGxtc0FydGljbGVbXSkge1xuICByZXR1cm4gYXJ0aWNsZXMubWFwKGFydGljbGUgPT4ge1xuICAgIGNvbnN0IGxpbmsgPSBgWyR7YXJ0aWNsZS50aXRsZX1dKCR7YnVpbGRUd2luVXJsKGNvbmZpZywgYXJ0aWNsZS5wYXRoKX0pYFxuICAgIHJldHVybiBhcnRpY2xlLmRlc2NyaXB0aW9uID8gYC0gJHtsaW5rfTogJHthcnRpY2xlLmRlc2NyaXB0aW9ufWAgOiBgLSAke2xpbmt9YFxuICB9KVxufVxuIl19
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,98 @@
1
+ import { describe, expect, it } from "vite-plus/test";
2
+ import { buildTwinFileName, renderLlmsText, renderMarkdownTwin, renderSectionIndex, } from "./llms.js";
3
+ const config = { title: "Docs", description: "Blurb" };
4
+ describe("renderLlmsText", () => {
5
+ it("lists articles in sidebar order under a single heading without sections", () => {
6
+ const text = renderLlmsText({
7
+ config,
8
+ articles: [
9
+ { path: "/guide/", title: "Guide", order: 2 },
10
+ { path: "/intro/", title: "Intro", description: "Start here", order: 1 },
11
+ { path: "/guide/deep/", title: "Deep" },
12
+ ],
13
+ });
14
+ expect(text).toBe([
15
+ "# Docs",
16
+ "",
17
+ "> Blurb",
18
+ "",
19
+ "## Pages",
20
+ "",
21
+ "- [Intro](/intro/index.md): Start here",
22
+ "- [Guide](/guide/index.md)",
23
+ "- [Deep](/guide/deep/index.md)",
24
+ "",
25
+ ].join("\n"));
26
+ });
27
+ it("groups by routed section, newest first in a blog, with absolute urls", () => {
28
+ const text = renderLlmsText({
29
+ config: {
30
+ ...config,
31
+ site: "https://example.com/",
32
+ base: "/repo",
33
+ sections: [
34
+ { title: "Docs", prefix: "/", type: "article", position: "header" },
35
+ { title: "Blog", prefix: "/blog/", type: "blog", position: "header" },
36
+ {
37
+ title: "GitHub",
38
+ url: "https://github.com",
39
+ type: "custom",
40
+ position: "header",
41
+ },
42
+ ],
43
+ },
44
+ articles: [
45
+ { path: "/blog/old/", title: "Old", date: "2026-01-01" },
46
+ { path: "/intro/", title: "Intro" },
47
+ { path: "/blog/new/", title: "New", date: "2026-02-01" },
48
+ ],
49
+ });
50
+ expect(text).toContain([
51
+ "## Docs",
52
+ "",
53
+ "- [Intro](https://example.com/repo/intro/index.md)",
54
+ "",
55
+ "## Blog",
56
+ "",
57
+ "- [New](https://example.com/repo/blog/new/index.md)",
58
+ "- [Old](https://example.com/repo/blog/old/index.md)",
59
+ ].join("\n"));
60
+ expect(text).not.toContain("GitHub");
61
+ });
62
+ });
63
+ describe("renderSectionIndex", () => {
64
+ it("lists only the section's articles, newest first", () => {
65
+ const blog = {
66
+ title: "Blog",
67
+ prefix: "/blog/",
68
+ type: "blog",
69
+ position: "header",
70
+ };
71
+ const text = renderSectionIndex({
72
+ config: { sections: [blog] },
73
+ section: blog,
74
+ articles: [
75
+ { path: "/intro/", title: "Intro" },
76
+ { path: "/blog/old/", title: "Old", date: "2026-01-01" },
77
+ { path: "/blog/new/", title: "New", date: "2026-02-01", description: "Fresh" },
78
+ ],
79
+ });
80
+ expect(text).toBe("# Blog\n\n- [New](/blog/new/index.md): Fresh\n- [Old](/blog/old/index.md)\n");
81
+ });
82
+ });
83
+ describe("renderMarkdownTwin", () => {
84
+ it("leads with the title and description instead of the body's own h1", () => {
85
+ const twin = renderMarkdownTwin({
86
+ article: { path: "/intro/", title: "Introduction", description: "Start here" },
87
+ content: "# Livemark\n\nBody text\n",
88
+ });
89
+ expect(twin).toBe("# Introduction\n\n> Start here\n\nBody text\n");
90
+ });
91
+ });
92
+ describe("buildTwinFileName", () => {
93
+ it("places the twin beside the page's index.html", () => {
94
+ expect(buildTwinFileName("/")).toBe("index.md");
95
+ expect(buildTwinFileName("/guide/deep/")).toBe("guide/deep/index.md");
96
+ });
97
+ });
98
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGxtcy51bml0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2hlbHBlcnMvbGxtcy51bml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRXJELE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsY0FBYyxFQUNkLGtCQUFrQixFQUNsQixrQkFBa0IsR0FDbkIsTUFBTSxXQUFXLENBQUE7QUFFbEIsTUFBTSxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsQ0FBQTtBQUV0RCxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxFQUFFO0lBQzlCLEVBQUUsQ0FBQyx5RUFBeUUsRUFBRSxHQUFHLEVBQUU7UUFDakYsTUFBTSxJQUFJLEdBQUcsY0FBYyxDQUFDO1lBQzFCLE1BQU07WUFDTixRQUFRLEVBQUU7Z0JBQ1IsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtnQkFDN0MsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFO2dCQUN4RSxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRTthQUN4QztTQUNGLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQ2Y7WUFDRSxRQUFRO1lBQ1IsRUFBRTtZQUNGLFNBQVM7WUFDVCxFQUFFO1lBQ0YsVUFBVTtZQUNWLEVBQUU7WUFDRix3Q0FBd0M7WUFDeEMsNEJBQTRCO1lBQzVCLGdDQUFnQztZQUNoQyxFQUFFO1NBQ0gsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQTtJQUNILENB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QVksRUFBRTtZQUM5RSxPQUFPLEVBQUUsMkJBQTJCO1NBQ3JDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsK0NBQStDLENBQUMsQ0FBQTtJQUNwRSxDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBO0FBRUYsUUFBUSxDQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRTtJQUNqQyxFQUFFLENBQUMsOENBQThDLEVBQUUsR0FBRyxFQUFFO1FBQ3RELE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUMvQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQTtJQUN2RSxDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZGVzY3JpYmUsIGV4cGVjdCwgaXQgfSBmcm9tIFwidml0ZS1wbHVzL3Rlc3RcIlxuaW1wb3J0IHR5cGUgeyBSb3V0ZWRTZWN0aW9uIH0gZnJvbSBcIi4uL21vZGVscy9zZWN0aW9uLnRzXCJcbmltcG9ydCB7XG4gIGJ1aWxkVHdpbkZpbGVOYW1lLFxuICByZW5kZXJMbG1zVGV4dCxcbiAgcmVuZGVyTWFya2Rvd25Ud2luLFxuICByZW5kZXJTZWN0aW9uSW5kZXgsXG59IGZyb20gXCIuL2xsbXMudHNcIlxuXG5jb25zdCBjb25maWcgPSB7IHRpdGxlOiBcIkRvY3NcIiwgZGVzY3JpcHRpb246IFwiQmx1cmJcIiB9XG5cbmRlc2NyaWJlKFwicmVuZGVyTGxtc1RleHRcIiwgKCkgPT4ge1xuICBpdChcImxpc3RzIGFydGljbGVzIGluIHNpZGViYXIgb3JkZXIgdW5kZXIgYSBzaW5nbGUgaGVhZGluZyB3aXRob3V0IHNlY3Rpb25zXCIsICgpID0+IHtcbiAgICBjb25zdCB0ZXh0ID0gcmVuZGVyTGxtc1RleHQoe1xuICAgICAgY29uZmlnLFxuICAgICAgYXJ0aWNsZXM6IFtcbiAgICAgICAgeyBwYXRoOiBcIi9ndWlkZS9cIiwgdGl0bGU6IFwiR3VpZGVcIiwgb3JkZXI6IDIgfSxcbiAgICAgICAgeyBwYXRoOiBcIi9pbnRyby9cIiwgdGl0bGU6IFwiSW50cm9cIiwgZGVzY3JpcHRpb246IFwiU3RhcnQgaGVyZVwiLCBvcmRlcjogMSB9LFxuICAgICAgICB7IHBhdGg6IFwiL2d1aWRlL2RlZXAvXCIsIHRpdGxlOiBcIkRlZXBcIiB9LFxuICAgICAgXSxcbiAgICB9KVxuICAgIGV4cGVjdCh0ZXh0KS50b0JlKFxuICAgICAgW1xuICAgICAgICBcIiMgRG9jc1wiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIj4gQmx1cmJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCIjIyBQYWdlc1wiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIi0gW0ludHJvXSgvaW50cm8vaW5kZXgubWQpOiBTdGFydCBoZXJlXCIsXG4gICAgICAgIFwiLSBbR3VpZGVdKC9ndWlkZS9pbmRleC5tZClcIixcbiAgICAgICAgXCItIFtEZWVwXSgvZ3VpZGUvZGVlcC9pbmRleC5tZClcIixcbiAgICAgICAgXCJcIixcbiAgICAgIF0uam9pbihcIlxcblwiKSxcbiAgICApXG4gIH0pXG5cbiAgaXQoXCJncm91cHMgYnkgcm91dGVkIHNlY3Rpb24sIG5ld2VzdCBmaXJzdCBpbiBhIGJsb2csIHdpdGggYWJzb2x1dGUgdXJsc1wiLCAoKSA9PiB7XG4gICAgY29uc3QgdGV4dCA9IHJlbmRlckxsbXNUZXh0KHtcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICAuLi5jb25maWcsXG4gICAgICAgIHNpdGU6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9cIixcbiAgICAgICAgYmFzZTogXCIvcmVwb1wiLFxuICAgICAgICBzZWN0aW9uczogW1xuICAgICAgICAgIHsgdGl0bGU6IFwiRG9jc1wiLCBwcmVmaXg6IFwiL1wiLCB0eXBlOiBcImFydGljbGVcIiwgcG9zaXRpb246IFwiaGVhZGVyXCIgfSxcbiAgICAgICAgICB7IHRpdGxlOiBcIkJsb2dcIiwgcHJlZml4OiBcIi9ibG9nL1wiLCB0eXBlOiBcImJsb2dcIiwgcG9zaXRpb246IFwiaGVhZGVyXCIgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0aXRsZTogXCJHaXRIdWJcIixcbiAgICAgICAgICAgIHVybDogXCJodHRwczovL2dpdGh1Yi5jb21cIixcbiAgICAgICAgICAgIHR5cGU6IFwiY3VzdG9tXCIsXG4gICAgICAgICAgICBwb3NpdGlvbjogXCJoZWFkZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIGFydGljbGVzOiBbXG4gICAgICAgIHsgcGF0aDogXCIvYmxvZy9vbGQvXCIsIHRpdGxlOiBcIk9sZFwiLCBkYXRlOiBcIjIwMjYtMDEtMDFcIiB9LFxuICAgICAgICB7IHBhdGg6IFwiL2ludHJvL1wiLCB0aXRsZTogXCJJbnRyb1wiIH0sXG4gICAgICAgIHsgcGF0aDogXCIvYmxvZy9uZXcvXCIsIHRpdGxlOiBcIk5ld1wiLCBkYXRlOiBcIjIwMjYtMDItMDFcIiB9LFxuICAgICAgXSxcbiAgICB9KVxuICAgIGV4cGVjdCh0ZXh0KS50b0NvbnRhaW4oXG4gICAgICBbXG4gICAgICAgIFwiIyMgRG9jc1wiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIi0gW0ludHJvXShodHRwczovL2V4YW1wbGUuY29tL3JlcG8vaW50cm8vaW5kZXgubWQpXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiIyMgQmxvZ1wiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIi0gW05ld10oaHR0cHM6Ly9leGFtcGxlLmNvbS9yZXBvL2Jsb2cvbmV3L2luZGV4Lm1kKVwiLFxuICAgICAgICBcIi0gW09sZF0oaHR0cHM6Ly9leGFtcGxlLmNvbS9yZXBvL2Jsb2cvb2xkL2luZGV4Lm1kKVwiLFxuICAgICAgXS5qb2luKFwiXFxuXCIpLFxuICAgIClcbiAgICBleHBlY3QodGV4dCkubm90LnRvQ29udGFpbihcIkdpdEh1YlwiKVxuICB9KVxufSlcblxuZGVzY3JpYmUoXCJyZW5kZXJTZWN0aW9uSW5kZXhcIiwgKCkgPT4ge1xuICBpdChcImxpc3RzIG9ubHkgdGhlIHNlY3Rpb24ncyBhcnRpY2xlcywgbmV3ZXN0IGZpcnN0XCIsICgpID0+IHtcbiAgICBjb25zdCBibG9nOiBSb3V0ZWRTZWN0aW9uID0ge1xuICAgICAgdGl0bGU6IFwiQmxvZ1wiLFxuICAgICAgcHJlZml4OiBcIi9ibG9nL1wiLFxuICAgICAgdHlwZTogXCJibG9nXCIsXG4gICAgICBwb3NpdGlvbjogXCJoZWFkZXJcIixcbiAgICB9XG4gICAgY29uc3QgdGV4dCA9IHJlbmRlclNlY3Rpb25JbmRleCh7XG4gICAgICBjb25maWc6IHsgc2VjdGlvbnM6IFtibG9nXSB9LFxuICAgICAgc2VjdGlvbjogYmxvZyxcbiAgICAgIGFydGljbGVzOiBbXG4gICAgICAgIHsgcGF0aDogXCIvaW50cm8vXCIsIHRpdGxlOiBcIkludHJvXCIgfSxcbiAgICAgICAgeyBwYXRoOiBcIi9ibG9nL29sZC9cIiwgdGl0bGU6IFwiT2xkXCIsIGRhdGU6IFwiMjAyNi0wMS0wMVwiIH0sXG4gICAgICAgIHsgcGF0aDogXCIvYmxvZy9uZXcvXCIsIHRpdGxlOiBcIk5ld1wiLCBkYXRlOiBcIjIwMjYtMDItMDFcIiwgZGVzY3JpcHRpb246IFwiRnJlc2hcIiB9LFxuICAgICAgXSxcbiAgICB9KVxuICAgIGV4cGVjdCh0ZXh0KS50b0JlKFxuICAgICAgXCIjIEJsb2dcXG5cXG4tIFtOZXddKC9ibG9nL25ldy9pbmRleC5tZCk6IEZyZXNoXFxuLSBbT2xkXSgvYmxvZy9vbGQvaW5kZXgubWQpXFxuXCIsXG4gICAgKVxuICB9KVxufSlcblxuZGVzY3JpYmUoXCJyZW5kZXJNYXJrZG93blR3aW5cIiwgKCkgPT4ge1xuICBpdChcImxlYWRzIHdpdGggdGhlIHRpdGxlIGFuZCBkZXNjcmlwdGlvbiBpbnN0ZWFkIG9mIHRoZSBib2R5J3Mgb3duIGgxXCIsICgpID0+IHtcbiAgICBjb25zdCB0d2luID0gcmVuZGVyTWFya2Rvd25Ud2luKHtcbiAgICAgIGFydGljbGU6IHsgcGF0aDogXCIvaW50cm8vXCIsIHRpdGxlOiBcIkludHJvZHVjdGlvblwiLCBkZXNjcmlwdGlvbjogXCJTdGFydCBoZXJlXCIgfSxcbiAgICAgIGNvbnRlbnQ6IFwiIyBMaXZlbWFya1xcblxcbkJvZHkgdGV4dFxcblwiLFxuICAgIH0pXG4gICAgZXhwZWN0KHR3aW4pLnRvQmUoXCIjIEludHJvZHVjdGlvblxcblxcbj4gU3RhcnQgaGVyZVxcblxcbkJvZHkgdGV4dFxcblwiKVxuICB9KVxufSlcblxuZGVzY3JpYmUoXCJidWlsZFR3aW5GaWxlTmFtZVwiLCAoKSA9PiB7XG4gIGl0KFwicGxhY2VzIHRoZSB0d2luIGJlc2lkZSB0aGUgcGFnZSdzIGluZGV4Lmh0bWxcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChidWlsZFR3aW5GaWxlTmFtZShcIi9cIikpLnRvQmUoXCJpbmRleC5tZFwiKVxuICAgIGV4cGVjdChidWlsZFR3aW5GaWxlTmFtZShcIi9ndWlkZS9kZWVwL1wiKSkudG9CZShcImd1aWRlL2RlZXAvaW5kZXgubWRcIilcbiAgfSlcbn0pXG4iXX0=
@@ -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;