livemark 0.23.0 → 0.24.1

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 (281) hide show
  1. package/.agents/skills/change-review/SKILL.md +47 -0
  2. package/{skills/configuration → .agents/skills/livemark-configuration}/SKILL.md +2 -4
  3. package/build/actions/changelog/build.d.ts +21 -9
  4. package/build/actions/changelog/build.js +31 -23
  5. package/build/actions/changelog/build.unit.js +156 -2
  6. package/build/actions/config/load.js +1 -1
  7. package/build/actions/config/load.unit.js +1 -1
  8. package/build/actions/target/build.js +2 -5
  9. package/build/commands/build.js +1 -1
  10. package/build/commands/escape.js +1 -1
  11. package/build/commands/preview.js +1 -1
  12. package/build/commands/start.js +1 -1
  13. package/build/components/Abbr.js +2 -2
  14. package/build/components/Article.js +2 -2
  15. package/build/components/BlogIndex.js +2 -4
  16. package/build/components/Callout.js +2 -2
  17. package/build/components/ChangelogIndex.js +1 -1
  18. package/build/components/CodeBlock.js +3 -5
  19. package/build/components/CodeTabs.js +1 -1
  20. package/build/components/Columns.js +2 -4
  21. package/build/components/Content.js +2 -2
  22. package/build/components/ContentTab.js +1 -1
  23. package/build/components/ContentTabs.js +1 -1
  24. package/build/components/DefinitionList.js +1 -1
  25. package/build/components/FileTree.js +1 -1
  26. package/build/components/FootnoteRef.js +2 -2
  27. package/build/components/InlineToc.js +1 -1
  28. package/build/components/Layout.js +1 -1
  29. package/build/components/LinkButton.js +2 -2
  30. package/build/components/Mermaid.js +1 -1
  31. package/build/components/PackageTabs.js +2 -2
  32. package/build/components/PageToolbar.js +2 -2
  33. package/build/components/PrevNext.js +3 -7
  34. package/build/components/SearchDialog.js +1 -1
  35. package/build/components/Section.js +2 -2
  36. package/build/components/SectionHeader.js +2 -2
  37. package/build/components/Sidebar.js +2 -2
  38. package/build/components/SidebarArticles.js +2 -2
  39. package/build/components/SidebarLinks.js +2 -2
  40. package/build/components/TagIndex.js +2 -4
  41. package/build/components/Toc.js +1 -1
  42. package/build/content/article.js +1 -1
  43. package/build/content-collections.js +6 -7
  44. package/build/elements/accordion.js +2 -2
  45. package/build/elements/alert-dialog.js +5 -5
  46. package/build/elements/alert.js +2 -2
  47. package/build/elements/aspect-ratio.js +2 -2
  48. package/build/elements/avatar.d.ts +1 -1
  49. package/build/elements/avatar.js +3 -3
  50. package/build/elements/badge.js +2 -2
  51. package/build/elements/breadcrumb.js +2 -2
  52. package/build/elements/button-group.d.ts +1 -1
  53. package/build/elements/button-group.js +3 -3
  54. package/build/elements/button.js +2 -2
  55. package/build/elements/calendar.js +5 -5
  56. package/build/elements/card.js +2 -2
  57. package/build/elements/carousel.js +2 -2
  58. package/build/elements/chart.js +5 -15
  59. package/build/elements/checkbox.js +2 -2
  60. package/build/elements/collapsible.js +3 -3
  61. package/build/elements/command.js +2 -2
  62. package/build/elements/context-menu.js +5 -5
  63. package/build/elements/dialog.js +2 -2
  64. package/build/elements/direction.d.ts +1 -1
  65. package/build/elements/direction.js +2 -2
  66. package/build/elements/drawer.js +2 -2
  67. package/build/elements/dropdown-menu.js +3 -3
  68. package/build/elements/empty.d.ts +1 -1
  69. package/build/elements/empty.js +3 -3
  70. package/build/elements/field.js +2 -2
  71. package/build/elements/hover-card.js +3 -3
  72. package/build/elements/input-group.js +2 -2
  73. package/build/elements/input-otp.js +2 -2
  74. package/build/elements/input.js +2 -2
  75. package/build/elements/item.js +2 -2
  76. package/build/elements/kbd.js +2 -2
  77. package/build/elements/label.js +2 -2
  78. package/build/elements/menubar.js +2 -2
  79. package/build/elements/native-select.js +2 -2
  80. package/build/elements/navigation-menu.js +2 -2
  81. package/build/elements/pagination.js +3 -3
  82. package/build/elements/popover.js +2 -2
  83. package/build/elements/progress.d.ts +1 -1
  84. package/build/elements/progress.js +3 -3
  85. package/build/elements/radio-group.js +2 -2
  86. package/build/elements/resizable.js +3 -3
  87. package/build/elements/scroll-area.js +2 -2
  88. package/build/elements/select.js +2 -2
  89. package/build/elements/separator.js +2 -2
  90. package/build/elements/sheet.js +2 -2
  91. package/build/elements/sidebar.js +3 -4
  92. package/build/elements/skeleton.js +2 -2
  93. package/build/elements/slider.js +2 -2
  94. package/build/elements/spinner.js +2 -2
  95. package/build/elements/switch.js +2 -2
  96. package/build/elements/table.js +2 -2
  97. package/build/elements/tabs.js +2 -2
  98. package/build/elements/textarea.js +2 -2
  99. package/build/elements/toggle-group.js +2 -2
  100. package/build/elements/toggle.js +2 -2
  101. package/build/elements/tooltip.js +2 -2
  102. package/build/helpers/changelog-source.js +1 -1
  103. package/build/helpers/dynamic-icon-resolver.js +1 -1
  104. package/build/helpers/resolve-asset-path.unit.js +1 -1
  105. package/build/helpers/resolve-base.unit.js +2 -2
  106. package/build/helpers/resolve-includes.js +2 -2
  107. package/build/helpers/resolve-includes.unit.js +1 -1
  108. package/build/helpers/rss.js +2 -4
  109. package/build/helpers/rss.unit.js +1 -1
  110. package/build/helpers/section.js +2 -3
  111. package/build/helpers/section.unit.js +4 -13
  112. package/build/helpers/toc.unit.js +2 -4
  113. package/build/plugins/rehype-inline-code.js +2 -2
  114. package/build/plugins/rehype-task-list-a11y.js +1 -1
  115. package/build/plugins/remark-abbr.js +2 -4
  116. package/build/plugins/remark-ansi.js +2 -4
  117. package/build/plugins/remark-ansi.unit.js +1 -1
  118. package/build/plugins/remark-badge.js +2 -4
  119. package/build/plugins/remark-button.unit.js +1 -1
  120. package/build/plugins/remark-callout.js +1 -1
  121. package/build/plugins/remark-card.js +1 -1
  122. package/build/plugins/remark-code-tabs.js +4 -8
  123. package/build/plugins/remark-columns.js +1 -1
  124. package/build/plugins/remark-custom-heading-id.unit.js +1 -1
  125. package/build/plugins/remark-deflist.js +1 -1
  126. package/build/plugins/remark-details.js +2 -4
  127. package/build/plugins/remark-filetree.js +1 -1
  128. package/build/plugins/remark-filetree.unit.js +1 -1
  129. package/build/plugins/remark-media.js +3 -7
  130. package/build/plugins/remark-media.unit.js +1 -1
  131. package/build/plugins/remark-steps.unit.js +1 -1
  132. package/build/plugins/remark-tab.js +4 -2
  133. package/build/plugins/remark-tab.unit.js +3 -7
  134. package/build/plugins/remark-toc.unit.js +1 -1
  135. package/build/plugins/shiki-icon.js +1 -1
  136. package/build/plugins/shiki-line-highlight.js +1 -1
  137. package/build/plugins/vite-livemark.js +1 -1
  138. package/build/plugins/vite-robots.js +1 -1
  139. package/build/plugins/vite-robots.unit.js +1 -1
  140. package/build/routes/$.js +1 -1
  141. package/build/vite.config.js +3 -8
  142. package/package.json +17 -19
  143. package/source/actions/changelog/build.ts +32 -35
  144. package/source/actions/changelog/build.unit.ts +191 -1
  145. package/source/actions/config/load.ts +1 -3
  146. package/source/actions/config/load.unit.ts +2 -7
  147. package/source/actions/target/build.ts +1 -4
  148. package/source/commands/build.ts +1 -7
  149. package/source/commands/escape.ts +3 -8
  150. package/source/commands/preview.ts +1 -7
  151. package/source/commands/start.ts +1 -7
  152. package/source/components/Abbr.tsx +1 -5
  153. package/source/components/Article.tsx +1 -5
  154. package/source/components/BlogIndex.tsx +3 -9
  155. package/source/components/Callout.tsx +2 -7
  156. package/source/components/ChangelogIndex.tsx +1 -3
  157. package/source/components/CodeBlock.tsx +4 -14
  158. package/source/components/CodeTabs.tsx +1 -3
  159. package/source/components/Columns.tsx +1 -3
  160. package/source/components/Content.tsx +1 -5
  161. package/source/components/ContentTab.tsx +1 -4
  162. package/source/components/ContentTabs.tsx +3 -10
  163. package/source/components/DefinitionList.tsx +1 -4
  164. package/source/components/FileTree.tsx +1 -5
  165. package/source/components/FootnoteRef.tsx +1 -5
  166. package/source/components/InlineToc.tsx +1 -4
  167. package/source/components/Layout.tsx +3 -10
  168. package/source/components/LinkButton.tsx +2 -8
  169. package/source/components/Mermaid.tsx +1 -3
  170. package/source/components/PackageTabs.tsx +1 -5
  171. package/source/components/PageToolbar.tsx +1 -5
  172. package/source/components/PrevNext.tsx +2 -6
  173. package/source/components/SearchDialog.tsx +2 -6
  174. package/source/components/Section.tsx +1 -1
  175. package/source/components/SectionHeader.tsx +2 -8
  176. package/source/components/Sidebar.tsx +2 -7
  177. package/source/components/SidebarArticles.tsx +4 -20
  178. package/source/components/SidebarLinks.tsx +2 -6
  179. package/source/components/TagIndex.tsx +3 -9
  180. package/source/components/Toc.tsx +2 -7
  181. package/source/content/article.ts +1 -2
  182. package/source/content-collections.ts +6 -8
  183. package/source/elements/accordion.tsx +1 -1
  184. package/source/elements/alert-dialog.tsx +8 -30
  185. package/source/elements/alert.tsx +2 -5
  186. package/source/elements/aspect-ratio.tsx +1 -1
  187. package/source/elements/avatar.tsx +5 -21
  188. package/source/elements/badge.tsx +3 -5
  189. package/source/elements/breadcrumb.tsx +4 -14
  190. package/source/elements/button-group.tsx +2 -7
  191. package/source/elements/button.tsx +1 -1
  192. package/source/elements/calendar.tsx +7 -24
  193. package/source/elements/card.tsx +1 -1
  194. package/source/elements/carousel.tsx +4 -11
  195. package/source/elements/chart.tsx +9 -34
  196. package/source/elements/checkbox.tsx +1 -1
  197. package/source/elements/collapsible.tsx +2 -6
  198. package/source/elements/command.tsx +4 -13
  199. package/source/elements/context-menu.tsx +8 -25
  200. package/source/elements/dialog.tsx +4 -14
  201. package/source/elements/direction.tsx +1 -4
  202. package/source/elements/drawer.tsx +4 -10
  203. package/source/elements/dropdown-menu.tsx +5 -19
  204. package/source/elements/empty.tsx +3 -13
  205. package/source/elements/field.tsx +3 -7
  206. package/source/elements/hover-card.tsx +2 -4
  207. package/source/elements/input-group.tsx +15 -28
  208. package/source/elements/input-otp.tsx +1 -1
  209. package/source/elements/input.tsx +1 -1
  210. package/source/elements/item.tsx +4 -13
  211. package/source/elements/kbd.tsx +1 -1
  212. package/source/elements/label.tsx +1 -1
  213. package/source/elements/menubar.tsx +5 -14
  214. package/source/elements/native-select.tsx +4 -15
  215. package/source/elements/navigation-menu.tsx +2 -5
  216. package/source/elements/pagination.tsx +4 -14
  217. package/source/elements/popover.tsx +2 -5
  218. package/source/elements/progress.tsx +4 -16
  219. package/source/elements/radio-group.tsx +1 -1
  220. package/source/elements/resizable.tsx +4 -12
  221. package/source/elements/scroll-area.tsx +2 -6
  222. package/source/elements/select.tsx +4 -14
  223. package/source/elements/separator.tsx +1 -1
  224. package/source/elements/sheet.tsx +3 -10
  225. package/source/elements/sidebar.tsx +7 -25
  226. package/source/elements/skeleton.tsx +1 -1
  227. package/source/elements/slider.tsx +1 -1
  228. package/source/elements/spinner.tsx +1 -1
  229. package/source/elements/switch.tsx +1 -1
  230. package/source/elements/table.tsx +4 -13
  231. package/source/elements/tabs.tsx +1 -1
  232. package/source/elements/textarea.tsx +1 -1
  233. package/source/elements/toggle-group.tsx +2 -4
  234. package/source/elements/toggle.tsx +1 -1
  235. package/source/elements/tooltip.tsx +3 -10
  236. package/source/helpers/changelog-source.ts +1 -3
  237. package/source/helpers/dynamic-icon-resolver.tsx +1 -4
  238. package/source/helpers/resolve-asset-path.unit.ts +6 -12
  239. package/source/helpers/resolve-base.unit.ts +1 -2
  240. package/source/helpers/resolve-includes.ts +2 -8
  241. package/source/helpers/resolve-includes.unit.ts +9 -36
  242. package/source/helpers/rss.ts +3 -9
  243. package/source/helpers/rss.unit.ts +1 -3
  244. package/source/helpers/section.ts +1 -4
  245. package/source/helpers/section.unit.ts +5 -18
  246. package/source/helpers/toc.unit.ts +1 -3
  247. package/source/plugins/rehype-inline-code.ts +5 -21
  248. package/source/plugins/rehype-task-list-a11y.ts +1 -2
  249. package/source/plugins/remark-abbr.ts +1 -3
  250. package/source/plugins/remark-ansi.ts +2 -5
  251. package/source/plugins/remark-ansi.unit.ts +6 -18
  252. package/source/plugins/remark-badge.ts +1 -3
  253. package/source/plugins/remark-button.unit.ts +3 -9
  254. package/source/plugins/remark-callout.ts +35 -40
  255. package/source/plugins/remark-card.ts +25 -29
  256. package/source/plugins/remark-code-tabs.ts +3 -7
  257. package/source/plugins/remark-columns.ts +13 -17
  258. package/source/plugins/remark-custom-heading-id.unit.ts +2 -6
  259. package/source/plugins/remark-deflist.ts +1 -2
  260. package/source/plugins/remark-details.ts +28 -34
  261. package/source/plugins/remark-filetree.ts +28 -34
  262. package/source/plugins/remark-filetree.unit.ts +1 -4
  263. package/source/plugins/remark-media.ts +2 -6
  264. package/source/plugins/remark-media.unit.ts +2 -6
  265. package/source/plugins/remark-steps.unit.ts +2 -7
  266. package/source/plugins/remark-tab.ts +26 -30
  267. package/source/plugins/remark-tab.unit.ts +2 -6
  268. package/source/plugins/remark-toc.unit.ts +1 -3
  269. package/source/plugins/shiki-icon.ts +1 -4
  270. package/source/plugins/shiki-line-highlight.ts +4 -11
  271. package/source/plugins/vite-livemark.ts +3 -10
  272. package/source/plugins/vite-robots.ts +1 -6
  273. package/source/plugins/vite-robots.unit.ts +1 -3
  274. package/source/routes/$.tsx +1 -3
  275. package/source/styles/general.css +1 -5
  276. package/source/vite.config.ts +2 -7
  277. package/build/utils/style.d.ts +0 -2
  278. package/build/utils/style.js +0 -6
  279. package/source/utils/style.ts +0 -6
  280. /package/{skills/authoring → .agents/skills/livemark-authoring}/SKILL.md +0 -0
  281. /package/{skills/customization → .agents/skills/livemark-customization}/SKILL.md +0 -0
@@ -1,4 +1,4 @@
1
- import { cn } from "../utils/style.ts"
1
+ import { cn } from "cn"
2
2
 
3
3
  function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
4
  return (
@@ -1,7 +1,7 @@
1
1
  import * as React from "react"
2
2
  import { Slider as SliderPrimitive } from "@base-ui/react/slider"
3
3
 
4
- import { cn } from "../utils/style.ts"
4
+ import { cn } from "cn"
5
5
 
6
6
  function Slider({
7
7
  className,
@@ -1,6 +1,6 @@
1
1
  import { Loader2Icon } from "lucide-react"
2
2
 
3
- import { cn } from "../utils/style.ts"
3
+ import { cn } from "cn"
4
4
 
5
5
  function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
6
6
  return (
@@ -1,6 +1,6 @@
1
1
  import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
2
2
 
3
- import { cn } from "../utils/style.ts"
3
+ import { cn } from "cn"
4
4
 
5
5
  function Switch({
6
6
  className,
@@ -1,11 +1,8 @@
1
- import { cn } from "../utils/style.ts"
1
+ import { cn } from "cn"
2
2
 
3
3
  function Table({ className, ...props }: React.ComponentProps<"table">) {
4
4
  return (
5
- <div
6
- data-slot="table-container"
7
- className="relative w-full overflow-x-auto"
8
- >
5
+ <div data-slot="table-container" className="relative w-full overflow-x-auto">
9
6
  <table
10
7
  data-slot="table"
11
8
  className={cn("w-full caption-bottom text-sm", className)}
@@ -39,10 +36,7 @@ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
39
36
  return (
40
37
  <tfoot
41
38
  data-slot="table-footer"
42
- className={cn(
43
- "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
44
- className,
45
- )}
39
+ className={cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className)}
46
40
  {...props}
47
41
  />
48
42
  )
@@ -87,10 +81,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
87
81
  )
88
82
  }
89
83
 
90
- function TableCaption({
91
- className,
92
- ...props
93
- }: React.ComponentProps<"caption">) {
84
+ function TableCaption({ className, ...props }: React.ComponentProps<"caption">) {
94
85
  return (
95
86
  <caption
96
87
  data-slot="table-caption"
@@ -1,6 +1,6 @@
1
1
  import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"
2
2
  import { cva, type VariantProps } from "class-variance-authority"
3
- import { cn } from "../utils/style.ts"
3
+ import { cn } from "cn"
4
4
 
5
5
  function Tabs({
6
6
  className,
@@ -1,4 +1,4 @@
1
- import { cn } from "../utils/style.ts"
1
+ import { cn } from "cn"
2
2
 
3
3
  function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
4
4
  return (
@@ -3,7 +3,7 @@ import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"
3
3
  import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group"
4
4
  import { type VariantProps } from "class-variance-authority"
5
5
 
6
- import { cn } from "../utils/style.ts"
6
+ import { cn } from "cn"
7
7
  import { toggleVariants } from "./toggle.tsx"
8
8
 
9
9
  const ToggleGroupContext = React.createContext<
@@ -45,9 +45,7 @@ function ToggleGroup({
45
45
  )}
46
46
  {...props}
47
47
  >
48
- <ToggleGroupContext.Provider
49
- value={{ variant, size, spacing, orientation }}
50
- >
48
+ <ToggleGroupContext.Provider value={{ variant, size, spacing, orientation }}>
51
49
  {children}
52
50
  </ToggleGroupContext.Provider>
53
51
  </ToggleGroupPrimitive>
@@ -1,7 +1,7 @@
1
1
  import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"
2
2
  import { cva, type VariantProps } from "class-variance-authority"
3
3
 
4
- import { cn } from "../utils/style.ts"
4
+ import { cn } from "cn"
5
5
 
6
6
  const toggleVariants = cva(
7
7
  "group/toggle inline-flex items-center justify-center gap-1 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
@@ -1,16 +1,9 @@
1
1
  import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
2
- import { cn } from "../utils/style.ts"
2
+ import { cn } from "cn"
3
3
 
4
- function TooltipProvider({
5
- delay = 0,
6
- ...props
7
- }: TooltipPrimitive.Provider.Props) {
4
+ function TooltipProvider({ delay = 0, ...props }: TooltipPrimitive.Provider.Props) {
8
5
  return (
9
- <TooltipPrimitive.Provider
10
- data-slot="tooltip-provider"
11
- delay={delay}
12
- {...props}
13
- />
6
+ <TooltipPrimitive.Provider data-slot="tooltip-provider" delay={delay} {...props} />
14
7
  )
15
8
  }
16
9
 
@@ -5,9 +5,7 @@ export function isGitHubUrl(source: string) {
5
5
 
6
6
  /** Extract `{ owner, repo }` from a GitHub URL. Returns undefined if unparseable */
7
7
  export function parseGitHubRepo(source: string) {
8
- const match = source.match(
9
- /^(?:https?:\/\/)?(?:www\.)?github\.com\/([^/]+)\/([^/#?]+)/,
10
- )
8
+ const match = source.match(/^(?:https?:\/\/)?(?:www\.)?github\.com\/([^/]+)\/([^/#?]+)/)
11
9
  if (!match) return undefined
12
10
  const owner = match[1]
13
11
  const repo = match[2]?.replace(/\.git$/, "")
@@ -8,10 +8,7 @@ function toPascalCase(name: string) {
8
8
  }
9
9
 
10
10
  /** Resolves a Lucide icon by kebab-case name from the full registry */
11
- export default function DynamicIconResolver(props: {
12
- name: string
13
- className?: string
14
- }) {
11
+ export default function DynamicIconResolver(props: { name: string; className?: string }) {
15
12
  const key = toPascalCase(props.name)
16
13
  if (!(key in icons)) return null
17
14
  const Icon = icons[key as keyof typeof icons]
@@ -6,15 +6,11 @@ describe("resolveAssetPath", () => {
6
6
  const filePath = "/site/docs/page.md"
7
7
 
8
8
  it("should resolve a sibling relative path", () => {
9
- expect(resolveAssetPath("./logo.png", filePath, root)).toBe(
10
- "/docs/logo.png",
11
- )
9
+ expect(resolveAssetPath("./logo.png", filePath, root)).toBe("/docs/logo.png")
12
10
  })
13
11
 
14
12
  it("should resolve a parent relative path", () => {
15
- expect(resolveAssetPath("../assets/x.png", filePath, root)).toBe(
16
- "/assets/x.png",
17
- )
13
+ expect(resolveAssetPath("../assets/x.png", filePath, root)).toBe("/assets/x.png")
18
14
  })
19
15
 
20
16
  it("should pass through a root-relative url", () => {
@@ -40,9 +36,7 @@ describe("resolveAssetPath", () => {
40
36
  })
41
37
 
42
38
  it("should prefix a root-relative url with base", () => {
43
- expect(resolveAssetPath("/foo.png", filePath, root, "/repo")).toBe(
44
- "/repo/foo.png",
45
- )
39
+ expect(resolveAssetPath("/foo.png", filePath, root, "/repo")).toBe("/repo/foo.png")
46
40
  })
47
41
 
48
42
  it("should not double-prefix an already-prefixed url", () => {
@@ -52,8 +46,8 @@ describe("resolveAssetPath", () => {
52
46
  })
53
47
 
54
48
  it("should not prefix external urls when base is set", () => {
55
- expect(
56
- resolveAssetPath("https://x.com/y.png", filePath, root, "/repo"),
57
- ).toBe("https://x.com/y.png")
49
+ expect(resolveAssetPath("https://x.com/y.png", filePath, root, "/repo")).toBe(
50
+ "https://x.com/y.png",
51
+ )
58
52
  })
59
53
  })
@@ -43,8 +43,7 @@ describe("resolveBase", () => {
43
43
  })
44
44
 
45
45
  it("should handle a function returning undefined", () => {
46
- const fn = (cmd: "build" | "serve") =>
47
- cmd === "serve" ? undefined : "prod"
46
+ const fn = (cmd: "build" | "serve") => (cmd === "serve" ? undefined : "prod")
48
47
  expect(resolveBase(fn, "serve")).toBeUndefined()
49
48
  expect(resolveBase(fn, "build")).toBe("/prod")
50
49
  })
@@ -76,9 +76,7 @@ function resolveDirective(
76
76
  const filename = file.split("/").pop()!
77
77
  const title = `title="${filename}"`
78
78
  const meta = attrs.meta ? ` ${attrs.meta}` : ""
79
- return (
80
- "```" + lang + " " + title + meta + "\n" + included.trimEnd() + "\n```"
81
- )
79
+ return "```" + lang + " " + title + meta + "\n" + included.trimEnd() + "\n```"
82
80
  }
83
81
 
84
82
  included = included.replace(FRONTMATTER_RE, "")
@@ -89,11 +87,7 @@ function resolveDirective(
89
87
  }
90
88
 
91
89
  /** Resolves ::include{file="..."} directives by replacing them with referenced file contents */
92
- export function resolveIncludes(
93
- content: string,
94
- filePath: string,
95
- depth = 0,
96
- ): string {
90
+ export function resolveIncludes(content: string, filePath: string, depth = 0): string {
97
91
  if (depth > 5) return content
98
92
 
99
93
  const fileDir = dirname(filePath)
@@ -8,23 +8,14 @@ describe("resolveIncludes", () => {
8
8
  it("should replace include directive with file content", () => {
9
9
  const dir = temporaryDirectory()
10
10
  writeFileSync(join(dir, "snippet.md"), "Hello from snippet")
11
- const result = resolveIncludes(
12
- '::include{file="snippet.md"}',
13
- join(dir, "main.md"),
14
- )
11
+ const result = resolveIncludes('::include{file="snippet.md"}', join(dir, "main.md"))
15
12
  expect(result).toBe("Hello from snippet")
16
13
  })
17
14
 
18
15
  it("should strip frontmatter from included files", () => {
19
16
  const dir = temporaryDirectory()
20
- writeFileSync(
21
- join(dir, "snippet.md"),
22
- "---\ntitle: Test\n---\nContent here",
23
- )
24
- const result = resolveIncludes(
25
- '::include{file="snippet.md"}',
26
- join(dir, "main.md"),
27
- )
17
+ writeFileSync(join(dir, "snippet.md"), "---\ntitle: Test\n---\nContent here")
18
+ const result = resolveIncludes('::include{file="snippet.md"}', join(dir, "main.md"))
28
19
  expect(result).toBe("Content here")
29
20
  })
30
21
 
@@ -39,10 +30,7 @@ describe("resolveIncludes", () => {
39
30
  })
40
31
 
41
32
  it("should keep directive when file is missing", () => {
42
- const result = resolveIncludes(
43
- '::include{file="nonexistent.md"}',
44
- "/tmp/main.md",
45
- )
33
+ const result = resolveIncludes('::include{file="nonexistent.md"}', "/tmp/main.md")
46
34
  expect(result).toBe('::include{file="nonexistent.md"}')
47
35
  })
48
36
 
@@ -50,20 +38,14 @@ describe("resolveIncludes", () => {
50
38
  const dir = temporaryDirectory()
51
39
  writeFileSync(join(dir, "inner.md"), "Inner content")
52
40
  writeFileSync(join(dir, "outer.md"), '::include{file="inner.md"}')
53
- const result = resolveIncludes(
54
- '::include{file="outer.md"}',
55
- join(dir, "main.md"),
56
- )
41
+ const result = resolveIncludes('::include{file="outer.md"}', join(dir, "main.md"))
57
42
  expect(result).toBe("Inner content")
58
43
  })
59
44
 
60
45
  it("should limit recursion depth", () => {
61
46
  const dir = temporaryDirectory()
62
47
  writeFileSync(join(dir, "recursive.md"), '::include{file="recursive.md"}')
63
- const result = resolveIncludes(
64
- '::include{file="recursive.md"}',
65
- join(dir, "main.md"),
66
- )
48
+ const result = resolveIncludes('::include{file="recursive.md"}', join(dir, "main.md"))
67
49
  expect(result).toBe('::include{file="recursive.md"}')
68
50
  })
69
51
 
@@ -72,10 +54,7 @@ describe("resolveIncludes", () => {
72
54
  mkdirSync(join(dir, "sub"))
73
55
  writeFileSync(join(dir, "sub", "child.md"), "Child content")
74
56
  writeFileSync(join(dir, "parent.md"), '::include{file="sub/child.md"}')
75
- const result = resolveIncludes(
76
- '::include{file="parent.md"}',
77
- join(dir, "main.md"),
78
- )
57
+ const result = resolveIncludes('::include{file="parent.md"}', join(dir, "main.md"))
79
58
  expect(result).toBe("Child content")
80
59
  })
81
60
 
@@ -93,10 +72,7 @@ describe("resolveIncludes", () => {
93
72
  it("should wrap code files in fenced blocks", () => {
94
73
  const dir = temporaryDirectory()
95
74
  writeFileSync(join(dir, "example.ts"), 'const x = 1\nconst y = "hello"')
96
- const result = resolveIncludes(
97
- '::include{file="example.ts"}',
98
- join(dir, "main.md"),
99
- )
75
+ const result = resolveIncludes('::include{file="example.ts"}', join(dir, "main.md"))
100
76
  expect(result).toBe(
101
77
  '```typescript title="example.ts"\nconst x = 1\nconst y = "hello"\n```',
102
78
  )
@@ -117,10 +93,7 @@ describe("resolveIncludes", () => {
117
93
  it("should treat unknown extensions as markdown", () => {
118
94
  const dir = temporaryDirectory()
119
95
  writeFileSync(join(dir, "notes.txt"), "Plain text")
120
- const result = resolveIncludes(
121
- '::include{file="notes.txt"}',
122
- join(dir, "main.md"),
123
- )
96
+ const result = resolveIncludes('::include{file="notes.txt"}', join(dir, "main.md"))
124
97
  expect(result).toBe("Plain text")
125
98
  })
126
99
  })
@@ -37,19 +37,13 @@ export function renderRssFeed(feed: RssFeed) {
37
37
  lines.push(` <link>${escapeXml(item.link)}</link>`)
38
38
  lines.push(` <guid isPermaLink="true">${escapeXml(item.guid)}</guid>`)
39
39
  if (item.description) {
40
- lines.push(
41
- ` <description>${escapeXml(item.description)}</description>`,
42
- )
40
+ lines.push(` <description>${escapeXml(item.description)}</description>`)
43
41
  }
44
42
  if (item.pubDate) {
45
- lines.push(
46
- ` <pubDate>${escapeXml(toRfc822(item.pubDate))}</pubDate>`,
47
- )
43
+ lines.push(` <pubDate>${escapeXml(toRfc822(item.pubDate))}</pubDate>`)
48
44
  }
49
45
  if (item.author) {
50
- const author = Array.isArray(item.author)
51
- ? item.author.join(", ")
52
- : item.author
46
+ const author = Array.isArray(item.author) ? item.author.join(", ") : item.author
53
47
  lines.push(` <author>${escapeXml(author)}</author>`)
54
48
  }
55
49
  if (item.categories) {
@@ -106,9 +106,7 @@ describe("renderRssFeed", () => {
106
106
  },
107
107
  ],
108
108
  })
109
- expect(xml).toContain(
110
- "<title>Title &amp; &quot;quoted&quot; &lt;tag&gt;</title>",
111
- )
109
+ expect(xml).toContain("<title>Title &amp; &quot;quoted&quot; &lt;tag&gt;</title>")
112
110
  expect(xml).toContain("<description>A &amp; B</description>")
113
111
  expect(xml).toContain("<title>1 &lt; 2 &amp; 3 &gt; 0</title>")
114
112
  expect(xml).toContain("<description>It&apos;s fine</description>")
@@ -63,10 +63,7 @@ export function matchSection<S extends { prefix: string }>(
63
63
  let best: S | undefined
64
64
  let bestLen = 0
65
65
  for (const section of sections) {
66
- if (
67
- articlePath.startsWith(section.prefix) &&
68
- section.prefix.length > bestLen
69
- ) {
66
+ if (articlePath.startsWith(section.prefix) && section.prefix.length > bestLen) {
70
67
  best = section
71
68
  bestLen = section.prefix.length
72
69
  }
@@ -53,14 +53,8 @@ describe("partitionBySection", () => {
53
53
 
54
54
  it("should split articles into section buckets", () => {
55
55
  const result = partitionBySection(articles, sections)
56
- expect(result.get("/")?.map(a => a.path)).toEqual([
57
- "/getting-started/",
58
- "/guide/",
59
- ])
60
- expect(result.get("/api/")?.map(a => a.path)).toEqual([
61
- "/api/users/",
62
- "/api/auth/",
63
- ])
56
+ expect(result.get("/")?.map(a => a.path)).toEqual(["/getting-started/", "/guide/"])
57
+ expect(result.get("/api/")?.map(a => a.path)).toEqual(["/api/users/", "/api/auth/"])
64
58
  })
65
59
 
66
60
  it("should put unmatched articles in __default__ bucket", () => {
@@ -70,10 +64,7 @@ describe("partitionBySection", () => {
70
64
  "/getting-started/",
71
65
  "/guide/",
72
66
  ])
73
- expect(result.get("/api/")?.map(a => a.path)).toEqual([
74
- "/api/users/",
75
- "/api/auth/",
76
- ])
67
+ expect(result.get("/api/")?.map(a => a.path)).toEqual(["/api/users/", "/api/auth/"])
77
68
  })
78
69
  })
79
70
 
@@ -152,16 +143,12 @@ describe("activeSiteSection", () => {
152
143
  })
153
144
 
154
145
  it("should return the custom section matching by internal url", () => {
155
- expect(activeSiteSection("/api/v2/users/", [docs, apiCustom])?.title).toBe(
156
- "API",
157
- )
146
+ expect(activeSiteSection("/api/v2/users/", [docs, apiCustom])?.title).toBe("API")
158
147
  })
159
148
 
160
149
  it("should pick the longest match among overlapping prefixes", () => {
161
150
  expect(activeSiteSection("/blog/post/", [docs, blog])?.title).toBe("Blog")
162
- expect(activeSiteSection("/api/v2/foo/", [docs, apiCustom])?.title).toBe(
163
- "API",
164
- )
151
+ expect(activeSiteSection("/api/v2/foo/", [docs, apiCustom])?.title).toBe("API")
165
152
  })
166
153
 
167
154
  it("should ignore custom sections with absolute URLs", () => {
@@ -35,9 +35,7 @@ describe("extractToc", () => {
35
35
  it("should handle code formatting with custom ids", () => {
36
36
  const content = "## `config` Options [#config-opts]"
37
37
  const toc = extractToc(content)
38
- expect(toc).toEqual([
39
- { url: "#config-opts", title: "config Options", depth: 2 },
40
- ])
38
+ expect(toc).toEqual([{ url: "#config-opts", title: "config Options", depth: 2 }])
41
39
  })
42
40
 
43
41
  it("should skip h1 headings", () => {
@@ -1,23 +1,13 @@
1
1
  import type { Plugin } from "unified"
2
2
  import { visit } from "unist-util-visit"
3
- import {
4
- type BundledLanguage,
5
- bundledLanguages,
6
- getSingletonHighlighter,
7
- } from "shiki"
3
+ import { type BundledLanguage, bundledLanguages, getSingletonHighlighter } from "shiki"
8
4
 
9
5
  interface HastText {
10
6
  type: "text"
11
7
  value: string
12
8
  }
13
9
 
14
- type PropertyValue =
15
- | boolean
16
- | number
17
- | string
18
- | null
19
- | undefined
20
- | Array<string | number>
10
+ type PropertyValue = boolean | number | string | null | undefined | Array<string | number>
21
11
 
22
12
  interface HastElement {
23
13
  type: "element"
@@ -56,15 +46,10 @@ export const rehypeInlineCode: Plugin<[], HastRoot> = () => {
56
46
  visit(
57
47
  tree,
58
48
  "element",
59
- (
60
- node: HastNode,
61
- _index: number | undefined,
62
- parent: HastNode | undefined,
63
- ) => {
49
+ (node: HastNode, _index: number | undefined, parent: HastNode | undefined) => {
64
50
  if (node.type !== "element") return
65
51
  if (node.tagName !== "code") return
66
- if (parent && parent.type === "element" && parent.tagName === "pre")
67
- return
52
+ if (parent && parent.type === "element" && parent.tagName === "pre") return
68
53
 
69
54
  const textChild = node.children[0]
70
55
  if (!textChild || textChild.type !== "text") return
@@ -92,8 +77,7 @@ export const rehypeInlineCode: Plugin<[], HastRoot> = () => {
92
77
  const codeEl = pre.children[0]
93
78
  if (codeEl && codeEl.type === "element" && "children" in codeEl) {
94
79
  node.children = codeEl.children.filter(
95
- (c): c is HastElement | HastText =>
96
- c.type === "element" || c.type === "text",
80
+ (c): c is HastElement | HastText => c.type === "element" || c.type === "text",
97
81
  )
98
82
  node.properties = {
99
83
  ...node.properties,
@@ -14,8 +14,7 @@ export function rehypeTaskListA11y() {
14
14
  visit(tree, "element", (node: HastNode) => {
15
15
  if (node.tagName !== "li") return
16
16
  const classes = node.properties?.className
17
- const hasTaskClass =
18
- Array.isArray(classes) && classes.includes("task-list-item")
17
+ const hasTaskClass = Array.isArray(classes) && classes.includes("task-list-item")
19
18
  if (!hasTaskClass) return
20
19
 
21
20
  for (const child of node.children ?? []) {
@@ -8,9 +8,7 @@ export function transformAbbrDirectives(tree: Root) {
8
8
  visit(tree, "textDirective", (node: TextDirective, index, parent) => {
9
9
  if (node.name !== "abbr" || index === undefined || !parent) return
10
10
 
11
- const text = node.children
12
- .map(c => ("value" in c ? String(c.value) : ""))
13
- .join("")
11
+ const text = node.children.map(c => ("value" in c ? String(c.value) : "")).join("")
14
12
 
15
13
  const title = node.attributes?.title ?? ""
16
14
 
@@ -41,8 +41,7 @@ function color256(n: number): string | undefined {
41
41
  const r = Math.floor(idx / 36)
42
42
  const g = Math.floor((idx % 36) / 6)
43
43
  const b = idx % 6
44
- const toHex = (v: number) =>
45
- (v === 0 ? 0 : 55 + v * 40).toString(16).padStart(2, "0")
44
+ const toHex = (v: number) => (v === 0 ? 0 : 55 + v * 40).toString(16).padStart(2, "0")
46
45
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`
47
46
  }
48
47
  if (n < 256) {
@@ -192,9 +191,7 @@ export function ansiToHtml(input: string): string {
192
191
 
193
192
  const rawParams = match[1]!
194
193
  const params =
195
- rawParams === ""
196
- ? [0]
197
- : rawParams.split(";").map(s => Number.parseInt(s, 10))
194
+ rawParams === "" ? [0] : rawParams.split(";").map(s => Number.parseInt(s, 10))
198
195
  applyParams(state, params)
199
196
  lastIndex = match.index + match[0].length
200
197
  match = sgr.exec(input)
@@ -17,9 +17,7 @@ describe("ansiToHtml", () => {
17
17
 
18
18
  it("should render standard foreground colors", () => {
19
19
  const input = "\x1b[31mred text\x1b[0m"
20
- expect(ansiToHtml(input)).toBe(
21
- '<span style="color:#bf616a">red text</span>',
22
- )
20
+ expect(ansiToHtml(input)).toBe('<span style="color:#bf616a">red text</span>')
23
21
  })
24
22
 
25
23
  it("should render bold text", () => {
@@ -29,9 +27,7 @@ describe("ansiToHtml", () => {
29
27
 
30
28
  it("should render italic text", () => {
31
29
  const input = "\x1b[3mitalic\x1b[0m"
32
- expect(ansiToHtml(input)).toBe(
33
- '<span style="font-style:italic">italic</span>',
34
- )
30
+ expect(ansiToHtml(input)).toBe('<span style="font-style:italic">italic</span>')
35
31
  })
36
32
 
37
33
  it("should render underline text", () => {
@@ -69,9 +65,7 @@ describe("ansiToHtml", () => {
69
65
 
70
66
  it("should handle bright foreground colors", () => {
71
67
  const input = "\x1b[91mbright red\x1b[0m"
72
- expect(ansiToHtml(input)).toBe(
73
- '<span style="color:#bf616a">bright red</span>',
74
- )
68
+ expect(ansiToHtml(input)).toBe('<span style="color:#bf616a">bright red</span>')
75
69
  })
76
70
 
77
71
  it("should handle bright background colors", () => {
@@ -88,9 +82,7 @@ describe("ansiToHtml", () => {
88
82
 
89
83
  it("should handle 256-color background", () => {
90
84
  const input = "\x1b[48;5;21mbg\x1b[0m"
91
- expect(ansiToHtml(input)).toBe(
92
- '<span style="background-color:#0000ff">bg</span>',
93
- )
85
+ expect(ansiToHtml(input)).toBe('<span style="background-color:#0000ff">bg</span>')
94
86
  })
95
87
 
96
88
  it("should handle 24-bit RGB foreground", () => {
@@ -100,16 +92,12 @@ describe("ansiToHtml", () => {
100
92
 
101
93
  it("should handle 24-bit RGB background", () => {
102
94
  const input = "\x1b[48;2;0;128;255mbg\x1b[0m"
103
- expect(ansiToHtml(input)).toBe(
104
- '<span style="background-color:#0080ff">bg</span>',
105
- )
95
+ expect(ansiToHtml(input)).toBe('<span style="background-color:#0080ff">bg</span>')
106
96
  })
107
97
 
108
98
  it("should handle reset via empty escape", () => {
109
99
  const input = "\x1b[31mred\x1b[mnormal"
110
- expect(ansiToHtml(input)).toBe(
111
- '<span style="color:#bf616a">red</span>normal',
112
- )
100
+ expect(ansiToHtml(input)).toBe('<span style="color:#bf616a">red</span>normal')
113
101
  })
114
102
 
115
103
  it("should handle multiple segments", () => {
@@ -8,9 +8,7 @@ export function transformBadgeDirectives(tree: Root) {
8
8
  visit(tree, "textDirective", (node: TextDirective, index, parent) => {
9
9
  if (node.name !== "badge" || index === undefined || !parent) return
10
10
 
11
- const label = node.children
12
- .map(c => ("value" in c ? String(c.value) : ""))
13
- .join("")
11
+ const label = node.children.map(c => ("value" in c ? String(c.value) : "")).join("")
14
12
 
15
13
  const variant = node.attributes?.variant
16
14
 
@@ -47,9 +47,7 @@ describe("transformButtonDirectives", () => {
47
47
 
48
48
  it("should convert ::button with label attribute to LinkButton JSX element", () => {
49
49
  const tree = process(
50
- makeTree(
51
- makeLeafDirective("button", { href: "/docs", label: "Read Docs" }),
52
- ),
50
+ makeTree(makeLeafDirective("button", { href: "/docs", label: "Read Docs" })),
53
51
  )
54
52
  const node = tree.children[0]
55
53
  expect(node).toMatchObject({
@@ -122,17 +120,13 @@ describe("transformButtonDirectives", () => {
122
120
  })
123
121
 
124
122
  it("should skip button directive without href", () => {
125
- const tree = process(
126
- makeTree(makeLeafDirective("button", { label: "No Link" })),
127
- )
123
+ const tree = process(makeTree(makeLeafDirective("button", { label: "No Link" })))
128
124
  const node = tree.children[0]
129
125
  expect(node).toMatchObject({ type: "leafDirective", name: "button" })
130
126
  })
131
127
 
132
128
  it("should skip button directive without label or bracket text", () => {
133
- const tree = process(
134
- makeTree(makeLeafDirective("button", { href: "/no-label" })),
135
- )
129
+ const tree = process(makeTree(makeLeafDirective("button", { href: "/no-label" })))
136
130
  const node = tree.children[0]
137
131
  expect(node).toMatchObject({ type: "leafDirective", name: "button" })
138
132
  })