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
@@ -1,9 +1,11 @@
1
- import { cpSync, existsSync, rmSync } from "node:fs"
1
+ import { cpSync, existsSync, rmSync, statSync } from "node:fs"
2
2
  import { join, sep } from "node:path"
3
- import { watch as chokidarWatch } from "chokidar"
4
- import type { ConfigEnv, Plugin, UserConfig as ViteUserConfig, ViteDevServer } from "vite"
3
+ import type { ConfigEnv, Plugin, UserConfig as ViteUserConfig } from "vite"
5
4
  import { mergeConfig } from "vite"
5
+ import packageJson from "../../package.json" with { type: "json" }
6
6
  import { buildTarget } from "../actions/target/build.ts"
7
+ import { renderInlineMarkdown } from "../helpers/render-inline-markdown.ts"
8
+ import { resolveTargetExport } from "../helpers/target-export.ts"
7
9
  import type { Config } from "../models/config.ts"
8
10
  import { WebsiteConfig } from "../models/config.ts"
9
11
  import { ESCAPABLE_FILES, ESCAPABLE_FOLDERS } from "../settings.ts"
@@ -13,13 +15,15 @@ export interface LivemarkOptions {
13
15
  }
14
16
 
15
17
  const SOURCE_DIR = join(import.meta.dirname, "..")
18
+ const IS_INSTALLED = SOURCE_DIR.includes(`${sep}node_modules${sep}`)
16
19
 
17
20
  /** Single virtual module exposing livemark's runtime values to consumer
18
21
  * override files via named exports:
19
22
  *
20
23
  * import { config } from "livemark:virtual"
21
24
  *
22
- * Currently exports `config` (validated `WebsiteConfig`); future
25
+ * Currently exports `config` (validated `WebsiteConfig`) and `bannerHtml`
26
+ * (`config.banner` rendered from inline Markdown at build time); future
23
27
  * additions (e.g. `articles`, `sections`) land here as new named
24
28
  * exports without consumers changing their import statements.
25
29
  *
@@ -29,33 +33,36 @@ const SOURCE_DIR = join(import.meta.dirname, "..")
29
33
  const VIRTUAL_ID = "livemark:virtual"
30
34
  const VIRTUAL_RESOLVED_ID = `\0${VIRTUAL_ID}`
31
35
 
32
- /** Owns the per-consumer `targets/<hash>/` mount: synthesizes it via
36
+ /** Owns the project's `.livemark/.target/` mount: synthesizes it via
33
37
  * `buildTarget()`, returns the Vite config that anchors there, and
34
- * watches the consumer's `.livemark/` (plus livemark's `source/` in
35
- * dev) for changes that need to be re-copied into the target. The
36
- * override mechanism is pure file-system (full copies) — no resolveId
37
- * redirection, no realpath surprises. */
38
+ * copies `.livemark/` edits (plus livemark's `source/` in its own dev)
39
+ * into the target. Vite watches the target natively, so its own HMR
40
+ * decides between Fast Refresh, CSS updates and a page reload. */
38
41
  export function livemark(opts: LivemarkOptions): Plugin {
39
42
  const overridesRoot = join(opts.config.root, ".livemark")
43
+ const outDir = join(overridesRoot, "build")
40
44
  let targetDir = ""
41
45
  return {
42
46
  name: "livemark",
43
47
  enforce: "pre",
44
48
  async config(_, env) {
45
- targetDir = buildTarget(opts.config.configPath)
49
+ targetDir = buildTarget({
50
+ configPath: opts.config.configPath,
51
+ sourceDir: SOURCE_DIR,
52
+ })
46
53
  const base: ViteUserConfig = {
47
54
  root: targetDir,
55
+ // The default `<root>/node_modules/.vite` would land inside the
56
+ // dependency link, i.e. in livemark's shared install.
57
+ cacheDir: join(targetDir, ".vite"),
48
58
  // Mount everything (asset URLs, modulepreloads, dev server) under
49
59
  // `config.base` so the same build works at root or at a sub-path
50
60
  // (e.g. GitHub Pages `https://user.github.io/repo/`). The router
51
61
  // and asset-path resolver mirror this at runtime.
52
62
  base: opts.config.base ? `${opts.config.base}/` : "/",
53
- // outDir lives outside the target root (in the consumer's
54
- // .livemark/) so the consumer can find their deployable output
55
- // without digging into node_modules. Vite's default refusal to
56
- // empty out-of-root directories doesn't apply here because the
57
- // target/ root is livemark's, not the consumer's.
58
- build: { outDir: join(overridesRoot, "build"), emptyOutDir: true },
63
+ // outDir lives outside the target root, so Vite's refusal to
64
+ // empty out-of-root directories needs `emptyOutDir`.
65
+ build: { outDir, emptyOutDir: true },
59
66
  resolve: { dedupe: ["react", "react-dom"] },
60
67
  // For the SSR build only, inline every node_modules dep into
61
68
  // server.js. The prerender step (which runs server.js with
@@ -72,62 +79,44 @@ export function livemark(opts: LivemarkOptions): Plugin {
72
79
  },
73
80
  resolveId(id) {
74
81
  if (id === VIRTUAL_ID) return VIRTUAL_RESOLVED_ID
75
- return null
82
+ return resolveTargetExport({ id, targetDir, exports: packageJson.exports }) ?? null
76
83
  },
77
84
  load(id) {
78
85
  if (id !== VIRTUAL_RESOLVED_ID) return null
79
86
  const config = WebsiteConfig.parse(opts.config)
80
- return `export const config = ${JSON.stringify(config)}`
87
+ const bannerHtml = config.banner
88
+ ? renderInlineMarkdown(config.banner, config.base)
89
+ : undefined
90
+ return [
91
+ `export const config = ${JSON.stringify(config)}`,
92
+ `export const bannerHtml = ${JSON.stringify(bannerHtml)}`,
93
+ ].join("\n")
81
94
  },
82
95
  configureServer(server) {
83
- // Two reasons we don't use Vite's own `server.watcher`:
84
- // 1. Vite 8 bundles chokidar 3 with `disableGlobbing: true`, and
85
- // paths added via `server.watcher.add()` for surfaces outside
86
- // Vite's root never fire — getWatched() reports them but no
87
- // events arrive for external editors.
88
- // 2. Vite's chokidar ignores `**\/node_modules/**` by default, so
89
- // even if (1) were fixed, our targetDir (which lives inside
90
- // livemark's own node_modules in consumer projects) would be
91
- // silently filtered. We emit the change event manually onto
92
- // `server.watcher` after cpSync — see {@link notifyVite}.
93
- // A dedicated chokidar 5 watcher set up directly on these paths
94
- // fires reliably; we forward events into Vite's HMR pipeline below.
95
- const overlayPaths: string[] = []
96
- for (const folder of ESCAPABLE_FOLDERS) {
97
- overlayPaths.push(join(overridesRoot, folder))
98
- }
99
- for (const file of ESCAPABLE_FILES) {
100
- overlayPaths.push(join(overridesRoot, file))
101
- }
102
- const watcher = chokidarWatch(
103
- [opts.config.configPath, ...overlayPaths, SOURCE_DIR],
104
- { ignoreInitial: true, ignorePermissionErrors: true },
105
- )
106
- watcher.on("change", file => onChange(file, "change"))
107
- watcher.on("add", file => onChange(file, "add"))
108
- watcher.on("unlink", file => onChange(file, "unlink"))
109
- const closeWatcher = () => {
110
- watcher.close()
111
- }
112
- server.httpServer?.once("close", closeWatcher)
96
+ // Vite watches only its root (the target); the files the target is
97
+ // copied from join its watcher here. `.livemark/` always exists
98
+ // because the target lives inside it.
99
+ server.watcher.add([opts.config.configPath, overridesRoot])
100
+ if (!IS_INSTALLED) server.watcher.add(SOURCE_DIR)
101
+ server.watcher.on("change", file => onChange(file, "change"))
102
+ server.watcher.on("add", file => onChange(file, "add"))
103
+ server.watcher.on("unlink", file => onChange(file, "unlink"))
104
+ server.watcher.on("unlinkDir", file => onChange(file, "unlink"))
113
105
 
114
106
  function onChange(file: string, kind: "change" | "add" | "unlink") {
115
107
  if (file === opts.config.configPath) {
116
108
  server.restart()
117
109
  return
118
110
  }
119
- const overlayHit = matchOverlay(file, overridesRoot)
111
+ if (isWithin(file, targetDir) || isWithin(file, outDir)) return
112
+ const overlayHit = matchPath(file, overridesRoot)
120
113
  if (overlayHit) {
121
114
  syncOverlay(overlayHit, kind, targetDir, overridesRoot)
122
- notifyVite(server, join(targetDir, overlayHit.rel), kind)
123
- if (kind !== "change") fullReload(server)
124
115
  return
125
116
  }
126
- const sourceHit = matchSource(file)
127
- if (sourceHit) {
117
+ const sourceHit = matchPath(file, SOURCE_DIR)
118
+ if (sourceHit && !sourceHit.rel.includes("routeTree.gen.ts")) {
128
119
  syncSource(sourceHit, kind, targetDir, overridesRoot)
129
- notifyVite(server, join(targetDir, sourceHit.rel), kind)
130
- if (kind !== "change") fullReload(server)
131
120
  }
132
121
  }
133
122
  },
@@ -139,21 +128,14 @@ interface Hit {
139
128
  category: "folder" | "file" | null
140
129
  }
141
130
 
142
- function matchOverlay(file: string, overridesRoot: string): Hit | null {
143
- const prefix = `${overridesRoot}${sep}`
144
- if (!file.startsWith(prefix)) return null
145
- const rel = file.slice(prefix.length)
131
+ function matchPath(file: string, root: string): Hit | null {
132
+ if (!isWithin(file, root) || file === root) return null
133
+ const rel = file.slice(root.length + sep.length)
146
134
  return { rel, category: classify(rel) }
147
135
  }
148
136
 
149
- function matchSource(file: string): Hit | null {
150
- const prefix = `${SOURCE_DIR}${sep}`
151
- if (!file.startsWith(prefix)) return null
152
- // Skip the targets/ output dir itself (sibling of source/) and any
153
- // `.gen.ts` files that downstream tools regenerate inside the target.
154
- const rel = file.slice(prefix.length)
155
- if (rel === "" || rel.includes("routeTree.gen.ts")) return null
156
- return { rel, category: classify(rel) }
137
+ function isWithin(file: string, dir: string) {
138
+ return file === dir || file.startsWith(`${dir}${sep}`)
157
139
  }
158
140
 
159
141
  function classify(rel: string): "folder" | "file" | null {
@@ -175,7 +157,11 @@ function syncOverlay(
175
157
  const dest = join(targetDir, hit.rel)
176
158
  const source = join(SOURCE_DIR, hit.rel)
177
159
  if (kind === "unlink") {
178
- rmSync(dest, { force: true, recursive: true })
160
+ // Copy a file's default over the escape in one write: an unlink then
161
+ // an add reaches Vite as two events and costs a page reload.
162
+ if (!existsSync(source) || statSync(source).isDirectory()) {
163
+ rmSync(dest, { force: true, recursive: true })
164
+ }
179
165
  if (existsSync(source)) cpSync(source, dest, { recursive: true, force: true })
180
166
  return
181
167
  }
@@ -201,33 +187,6 @@ function syncSource(
201
187
  if (existsSync(source)) cpSync(source, dest, { recursive: true, force: true })
202
188
  }
203
189
 
204
- function fullReload(server: ViteDevServer) {
205
- server.ws.send({ type: "full-reload" })
206
- }
207
-
208
- /** Drive Vite's HMR pipeline manually for a target file we just synced.
209
- * Vite's chokidar ignores `**\/node_modules/**` by default and our
210
- * targetDir lives inside livemark's own node_modules in consumer
211
- * projects, so cpSync writes there are silently filtered out.
212
- *
213
- * Emitting on `server.watcher` runs Vite's HMR analysis per environment
214
- * (CSS gets `hmr update`, route modules trigger `(ssr) page reload`).
215
- * But `(ssr) page reload` only sends `full-reload` on the SSR
216
- * environment's hot channel — the browser is connected to the *client*
217
- * channel and never sees it. So we also fire `full-reload` on the
218
- * client hot directly, which is what TanStack Start needs for route
219
- * edits to actually refresh the page. CSS HMR still works because
220
- * Vite's analysis runs first and updates already-flushed before our
221
- * reload. */
222
- function notifyVite(
223
- server: ViteDevServer,
224
- targetFile: string,
225
- kind: "change" | "add" | "unlink",
226
- ) {
227
- server.watcher.emit(kind, targetFile)
228
- server.environments.client.hot.send({ type: "full-reload" })
229
- }
230
-
231
190
  /** Resolve livemark.config.ts's `vite` field — either a config object
232
191
  * or a function `(env) => config` (matching Vite's own `defineConfig`).
233
192
  * Schema stores it as `unknown`; typing for the consumer's editor
package/source/program.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander"
2
2
  import { build } from "./commands/build.ts"
3
+ import { clear } from "./commands/clear.ts"
3
4
  import { escape } from "./commands/escape.ts"
4
5
  import { preview } from "./commands/preview.ts"
5
6
  import { start } from "./commands/start.ts"
@@ -16,3 +17,4 @@ export const program = new Command()
16
17
  .addCommand(build)
17
18
  .addCommand(preview)
18
19
  .addCommand(escape)
20
+ .addCommand(clear)
@@ -1,4 +1,6 @@
1
+ import { config } from "livemark:virtual"
1
2
  import { createFileRoute, notFound, redirect } from "@tanstack/react-router"
3
+ import { z } from "zod"
2
4
  import {
3
5
  currentSection,
4
6
  firstArticle,
@@ -6,12 +8,16 @@ import {
6
8
  sortedArticles,
7
9
  } from "../content/article.ts"
8
10
  import { sectionTags } from "../content/tag.ts"
11
+ import { buildPageHead } from "../helpers/head.ts"
9
12
  import { Article } from "../components/Article.tsx"
10
13
  import { BlogIndex } from "../components/BlogIndex.tsx"
11
14
  import { ChangelogIndex } from "../components/ChangelogIndex.tsx"
15
+ import { Layout } from "../components/Layout.tsx"
12
16
  import { TagIndex } from "../components/TagIndex.tsx"
13
17
 
14
18
  export const Route = createFileRoute("/$")({
19
+ // Loose, so keys this route does not own (UTM tags, devtools flags) survive.
20
+ validateSearch: z.looseObject({ highlight: z.string().optional().catch(undefined) }),
15
21
  loader: ({ params }) => {
16
22
  if (!params._splat) {
17
23
  if (homeArticle) return { ...homeArticle, sidebar: homeArticle.sidebar }
@@ -62,19 +68,31 @@ export const Route = createFileRoute("/$")({
62
68
 
63
69
  throw notFound()
64
70
  },
65
- head: ({ loaderData }) => ({
66
- meta: [
67
- ...(loaderData ? [{ title: loaderData.title }] : []),
68
- ...("description" in loaderData && loaderData.description
69
- ? [{ name: "description", content: loaderData.description }]
70
- : []),
71
- ],
72
- }),
71
+ head: ({ loaderData, params }) =>
72
+ buildPageHead({
73
+ config,
74
+ path: params._splat ? `/${params._splat}/` : "/",
75
+ title: loaderData?.title,
76
+ description:
77
+ loaderData && "description" in loaderData ? loaderData.description : undefined,
78
+ image: loaderData && "image" in loaderData ? loaderData.image : undefined,
79
+ isArticle: loaderData && "file" in loaderData,
80
+ }),
73
81
  component: Component,
74
82
  })
75
83
 
76
84
  function Component() {
77
85
  const data = Route.useLoaderData()
86
+ return (
87
+ <Layout withSidebar={data.sidebar}>
88
+ <Page />
89
+ </Layout>
90
+ )
91
+ }
92
+
93
+ function Page() {
94
+ const data = Route.useLoaderData()
95
+ const search = Route.useSearch()
78
96
  if ("blogIndex" in data) {
79
97
  return <BlogIndex sectionPrefix={data.sectionPrefix} />
80
98
  }
@@ -84,5 +102,5 @@ function Component() {
84
102
  if ("tagPage" in data) {
85
103
  return <TagIndex sectionPrefix={data.sectionPrefix} tag={data.tag} />
86
104
  }
87
- return <Article article={data} />
105
+ return <Article article={data} highlight={search.highlight} />
88
106
  }
@@ -1,72 +1,39 @@
1
1
  import { config } from "livemark:virtual"
2
2
  import { TanStackDevtools } from "@tanstack/react-devtools"
3
3
  import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools"
4
- import {
5
- createRootRoute,
6
- HeadContent,
7
- Outlet,
8
- Scripts,
9
- useMatch,
10
- } from "@tanstack/react-router"
4
+ import { createRootRoute, HeadContent, Outlet, Scripts } from "@tanstack/react-router"
11
5
  import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
12
6
  import type * as React from "react"
7
+ import { useEffect } from "react"
13
8
  import { Layout } from "../components/Layout.tsx"
9
+ import { Root } from "../components/Root.tsx"
14
10
  import { DefaultCatchBoundary } from "../components/DefaultCatchBoundary.tsx"
15
11
  import { NotFound } from "../components/NotFound.tsx"
12
+ import { useHydrated } from "../hooks/hydrated.ts"
16
13
  import { Toaster } from "../elements/sonner.tsx"
17
- import { faviconType } from "../helpers/favicon.ts"
18
- import { prefixUrl } from "../helpers/prefix-url.ts"
14
+ import { buildRootHead } from "../helpers/head.ts"
15
+ import { startTheme } from "../helpers/theme.ts"
16
+ import { customizeHead } from "../head.ts"
19
17
  import defaultFavicon from "../assets/logo.svg"
20
18
  import generalCss from "../styles/general.css?url"
21
19
  import markdownCss from "../styles/markdown.css?url"
22
20
 
23
21
  export const Route = createRootRoute({
24
- head: () => {
25
- const favicon = prefixUrl(
26
- config.favicon ?? config.logo ?? defaultFavicon,
27
- config.base,
28
- )
29
- const feedLinks = config.site
30
- ? (config.sections ?? [])
31
- .filter(s => s.type === "blog")
32
- .map(s => ({
33
- rel: "alternate",
34
- type: "application/rss+xml",
35
- title: `${s.siteTitle ?? s.title} RSS Feed`,
36
- href: prefixUrl(`${s.prefix}rss.xml`, config.base),
37
- }))
38
- : []
39
- return {
40
- meta: [
41
- { charSet: "utf-8" },
42
- { title: config.title },
43
- { name: "description", content: config.description },
44
- { property: "og:title", content: config.title },
45
- {
46
- property: "og:description",
47
- content: config.description,
48
- },
49
- { property: "og:site_name", content: config.title },
50
- { property: "og:type", content: "website" },
51
- {
52
- name: "viewport",
53
- content: "width=device-width, initial-scale=1",
54
- },
55
- ],
56
- links: [
57
- { rel: "icon", href: favicon, type: faviconType(favicon) },
58
- { rel: "shortcut icon", href: favicon, type: faviconType(favicon) },
59
- { rel: "stylesheet", href: generalCss },
60
- { rel: "stylesheet", href: markdownCss },
61
- ...feedLinks,
62
- ],
63
- }
64
- },
65
- notFoundComponent: () => <NotFound />,
22
+ head: () =>
23
+ customizeHead(
24
+ buildRootHead({ config, defaultFavicon, stylesheets: [generalCss, markdownCss] }),
25
+ ),
26
+ notFoundComponent: () => (
27
+ <Layout>
28
+ <NotFound />
29
+ </Layout>
30
+ ),
66
31
  errorComponent: props => {
67
32
  return (
68
33
  <Document>
69
- <DefaultCatchBoundary {...props} />
34
+ <Layout>
35
+ <DefaultCatchBoundary {...props} />
36
+ </Layout>
70
37
  </Document>
71
38
  )
72
39
  },
@@ -80,32 +47,45 @@ export const Route = createRootRoute({
80
47
  })
81
48
 
82
49
  function Document(props: { children: React.ReactNode }) {
83
- const articleRoute = useMatch({ from: "/$", shouldThrow: false })
84
- const withSidebar = articleRoute?.loaderData?.sidebar
50
+ // Off the raw URL, not the router's parsed search: a route whose validateSearch
51
+ // does not declare this key strips it.
52
+ const hydrated = useHydrated()
53
+ const devtools = hydrated && window.location.search.includes("tanstack-devtools")
54
+
55
+ useEffect(startTheme, [])
85
56
 
86
57
  return (
87
- <html lang="en">
58
+ <html lang="en" suppressHydrationWarning>
88
59
  <head>
89
60
  <HeadContent />
90
61
  </head>
91
62
  <body>
92
- <Layout withSidebar={withSidebar}>{props.children}</Layout>
63
+ <Root>{props.children}</Root>
93
64
  <Toaster position="top-center" />
94
- <TanStackDevtools
95
- config={{ hideUntilHover: true, position: "bottom-left" }}
96
- plugins={[
97
- {
98
- name: "TanStack Query",
99
- render: <ReactQueryDevtoolsPanel />,
100
- defaultOpen: true,
101
- },
102
- {
103
- name: "TanStack Router",
104
- render: <TanStackRouterDevtoolsPanel />,
105
- defaultOpen: false,
106
- },
107
- ]}
108
- />
65
+ {/* Gated here, not by the devtools' own `requireUrlFlag`: that setting seeds
66
+ localStorage on a browser's first run and is read from there afterwards,
67
+ so a browser that loaded the site before it was set keeps the trigger. */}
68
+ {/* The build strips the devtools element alone; the fragment keeps
69
+ `devtools && (<></>)` valid instead of the syntax error `&& ()`. */}
70
+ {devtools && (
71
+ <>
72
+ <TanStackDevtools
73
+ config={{ requireUrlFlag: true, position: "bottom-left" }}
74
+ plugins={[
75
+ {
76
+ name: "TanStack Query",
77
+ render: <ReactQueryDevtoolsPanel />,
78
+ defaultOpen: true,
79
+ },
80
+ {
81
+ name: "TanStack Router",
82
+ render: <TanStackRouterDevtoolsPanel />,
83
+ defaultOpen: false,
84
+ },
85
+ ]}
86
+ />
87
+ </>
88
+ )}
109
89
  <Scripts />
110
90
  </body>
111
91
  </html>
@@ -14,6 +14,7 @@ export const ESCAPABLE_FILES: readonly string[] = [
14
14
  "client.tsx",
15
15
  "server.ts",
16
16
  "router.tsx",
17
+ "head.ts",
17
18
  ]
18
19
 
19
20
  /** Glob patterns auto-excluded from content scanning when the consumer's
@@ -1,5 +1,6 @@
1
1
  @import "tailwindcss";
2
2
  @import "tw-animate-css";
3
+ @import "./shape.css";
3
4
  @plugin "@tailwindcss/typography";
4
5
 
5
6
  @custom-variant dark (&:is(.dark *));
@@ -13,14 +14,28 @@
13
14
  --popover-foreground: oklch(0.145 0 0);
14
15
  --primary: oklch(54.6% 0.245 262.881);
15
16
  --primary-foreground: oklch(0.985 0 0);
16
- --secondary: oklch(89.4% 0.057 293.283);
17
- --secondary-foreground: oklch(0.205 0 0);
18
- --muted: oklch(0.97 0 0);
17
+ --secondary: oklch(54.1% 0.281 293.009);
18
+ --secondary-foreground: oklch(0.985 0 0);
19
+ --banner: oklch(89.4% 0.057 293.283);
20
+ --banner-foreground: oklch(0.205 0 0);
21
+ --muted: oklch(0.985 0 0);
19
22
  --muted-foreground: oklch(0.5 0 0);
20
23
  --accent: oklch(0.97 0 0);
21
24
  --accent-foreground: oklch(0.205 0 0);
22
- --destructive: oklch(0.577 0.245 27.325);
23
- --destructive-foreground: oklch(0.577 0.245 27.325);
25
+ --positive: oklch(0.648 0.2 131.684);
26
+ --positive-foreground: oklch(0.205 0 0);
27
+ --positive-tint: oklch(96.7% 0.067 122.328);
28
+ --positive-tint-foreground: oklch(53.2% 0.157 131.589);
29
+ --warning: oklch(79.5% 0.184 86.047);
30
+ --warning-foreground: oklch(0.205 0 0);
31
+ --warning-tint: oklch(97.3% 0.071 103.193);
32
+ --warning-tint-foreground: oklch(47.6% 0.114 61.907);
33
+ --highlight: oklch(90.5% 0.182 98.111);
34
+ --highlight-foreground: oklch(0.205 0 0);
35
+ --destructive: oklch(0.55 0.2 25);
36
+ --destructive-foreground: oklch(0.985 0 0);
37
+ --destructive-tint: oklch(93.6% 0.032 17.717);
38
+ --destructive-tint-foreground: oklch(50.5% 0.213 27.518);
24
39
  --border: oklch(0.922 0 0);
25
40
  --input: oklch(0.922 0 0);
26
41
  --ring: oklch(0.708 0 0);
@@ -30,7 +45,7 @@
30
45
  --chart-4: oklch(0.828 0.189 84.429);
31
46
  --chart-5: oklch(0.769 0.188 70.08);
32
47
  --radius: 0.625rem;
33
- --sidebar: oklch(0.985 0 0);
48
+ --sidebar: var(--muted);
34
49
  --sidebar-foreground: oklch(0.145 0 0);
35
50
  --sidebar-primary: oklch(0.205 0 0);
36
51
  --sidebar-primary-foreground: oklch(0.985 0 0);
@@ -49,14 +64,28 @@
49
64
  --popover-foreground: oklch(0.985 0 0);
50
65
  --primary: oklch(0.623 0.214 259.815);
51
66
  --primary-foreground: oklch(0.985 0 0);
52
- --secondary: oklch(0.269 0 0);
67
+ --secondary: oklch(60.6% 0.25 292.717);
53
68
  --secondary-foreground: oklch(0.985 0 0);
54
- --muted: oklch(0.269 0 0);
69
+ --banner: oklch(0.269 0 0);
70
+ --banner-foreground: oklch(0.985 0 0);
71
+ --muted: oklch(0.205 0 0);
55
72
  --muted-foreground: oklch(0.708 0 0);
56
73
  --accent: oklch(0.269 0 0);
57
74
  --accent-foreground: oklch(0.985 0 0);
58
- --destructive: oklch(0.396 0.141 25.723);
59
- --destructive-foreground: oklch(0.637 0.237 25.331);
75
+ --positive: oklch(0.841 0.238 128.85);
76
+ --positive-foreground: oklch(0.205 0 0);
77
+ --positive-tint: oklch(27.4% 0.072 132.109);
78
+ --positive-tint-foreground: oklch(84.1% 0.238 128.85);
79
+ --warning: oklch(85.2% 0.199 91.936);
80
+ --warning-foreground: oklch(0.22 0.04 70);
81
+ --warning-tint: oklch(28.6% 0.066 53.813);
82
+ --warning-tint-foreground: oklch(85.2% 0.199 91.936);
83
+ --highlight: oklch(55.4% 0.135 66.442);
84
+ --highlight-foreground: oklch(0.985 0 0);
85
+ --destructive: oklch(0.7 0.17 25);
86
+ --destructive-foreground: oklch(0.2 0.03 25);
87
+ --destructive-tint: oklch(25.8% 0.092 26.042);
88
+ --destructive-tint-foreground: oklch(70.4% 0.191 22.216);
60
89
  --border: oklch(0.269 0 0);
61
90
  --input: oklch(0.269 0 0);
62
91
  --ring: oklch(0.439 0 0);
@@ -65,7 +94,7 @@
65
94
  --chart-3: oklch(0.769 0.188 70.08);
66
95
  --chart-4: oklch(0.627 0.265 303.9);
67
96
  --chart-5: oklch(0.645 0.246 16.439);
68
- --sidebar: oklch(0.205 0 0);
97
+ --sidebar: var(--muted);
69
98
  --sidebar-foreground: oklch(0.985 0 0);
70
99
  --sidebar-primary: oklch(0.488 0.243 264.376);
71
100
  --sidebar-primary-foreground: oklch(0.985 0 0);
@@ -86,12 +115,26 @@
86
115
  --color-primary-foreground: var(--primary-foreground);
87
116
  --color-secondary: var(--secondary);
88
117
  --color-secondary-foreground: var(--secondary-foreground);
118
+ --color-banner: var(--banner);
119
+ --color-banner-foreground: var(--banner-foreground);
89
120
  --color-muted: var(--muted);
90
121
  --color-muted-foreground: var(--muted-foreground);
91
122
  --color-accent: var(--accent);
92
123
  --color-accent-foreground: var(--accent-foreground);
124
+ --color-positive: var(--positive);
125
+ --color-positive-foreground: var(--positive-foreground);
126
+ --color-positive-tint: var(--positive-tint);
127
+ --color-positive-tint-foreground: var(--positive-tint-foreground);
128
+ --color-warning: var(--warning);
129
+ --color-warning-foreground: var(--warning-foreground);
130
+ --color-warning-tint: var(--warning-tint);
131
+ --color-warning-tint-foreground: var(--warning-tint-foreground);
132
+ --color-highlight: var(--highlight);
133
+ --color-highlight-foreground: var(--highlight-foreground);
93
134
  --color-destructive: var(--destructive);
94
135
  --color-destructive-foreground: var(--destructive-foreground);
136
+ --color-destructive-tint: var(--destructive-tint);
137
+ --color-destructive-tint-foreground: var(--destructive-tint-foreground);
95
138
  --color-border: var(--border);
96
139
  --color-input: var(--input);
97
140
  --color-ring: var(--ring);
@@ -122,6 +165,11 @@
122
165
  @apply bg-background text-foreground;
123
166
  }
124
167
 
168
+ ::highlight(search-match) {
169
+ background-color: var(--highlight);
170
+ color: var(--highlight-foreground);
171
+ }
172
+
125
173
  html {
126
174
  scroll-behavior: smooth;
127
175
  scrollbar-color: #ddd transparent;