specra 0.1.13 → 0.2.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 (276) hide show
  1. package/LICENSE.MD +25 -4
  2. package/README.md +67 -58
  3. package/config/specra.config.schema.json +16 -0
  4. package/config/svelte-config.js +63 -0
  5. package/dist/api-parser.types.d.ts +59 -0
  6. package/dist/api-parser.types.js +5 -0
  7. package/dist/api.types.d.ts +137 -0
  8. package/dist/api.types.js +5 -0
  9. package/dist/category.d.ts +21 -0
  10. package/dist/category.js +48 -0
  11. package/dist/components/ConfigProvider.svelte +13 -0
  12. package/dist/components/ConfigProvider.svelte.d.ts +31 -0
  13. package/dist/components/docs/Accordion.svelte +18 -0
  14. package/dist/components/docs/Accordion.svelte.d.ts +10 -0
  15. package/dist/components/docs/AccordionItem.svelte +41 -0
  16. package/dist/components/docs/AccordionItem.svelte.d.ts +10 -0
  17. package/dist/components/docs/Badge.svelte +28 -0
  18. package/dist/components/docs/Badge.svelte.d.ts +9 -0
  19. package/dist/components/docs/Breadcrumb.svelte +80 -0
  20. package/dist/components/docs/Breadcrumb.svelte.d.ts +8 -0
  21. package/dist/components/docs/Callout.svelte +96 -0
  22. package/dist/components/docs/Callout.svelte.d.ts +10 -0
  23. package/dist/components/docs/Card.svelte +63 -0
  24. package/dist/components/docs/Card.svelte.d.ts +12 -0
  25. package/dist/components/docs/CardGrid.svelte +24 -0
  26. package/dist/components/docs/CardGrid.svelte.d.ts +8 -0
  27. package/dist/components/docs/CategoryIndex.svelte +110 -0
  28. package/dist/components/docs/CategoryIndex.svelte.d.ts +29 -0
  29. package/dist/components/docs/CodeBlock.svelte +172 -0
  30. package/dist/components/docs/CodeBlock.svelte.d.ts +8 -0
  31. package/dist/components/docs/Column.svelte +25 -0
  32. package/dist/components/docs/Column.svelte.d.ts +8 -0
  33. package/dist/components/docs/Columns.svelte +38 -0
  34. package/dist/components/docs/Columns.svelte.d.ts +13 -0
  35. package/dist/components/docs/DevModeBadge.svelte +15 -0
  36. package/dist/components/docs/DevModeBadge.svelte.d.ts +18 -0
  37. package/dist/components/docs/DocBadge.svelte +28 -0
  38. package/dist/components/docs/DocBadge.svelte.d.ts +9 -0
  39. package/dist/components/docs/DocLayout.svelte +107 -0
  40. package/dist/components/docs/DocLayout.svelte.d.ts +32 -0
  41. package/dist/components/docs/DocLoading.svelte +53 -0
  42. package/dist/components/docs/DocLoading.svelte.d.ts +18 -0
  43. package/dist/components/docs/DocMetadata.svelte +106 -0
  44. package/dist/components/docs/DocMetadata.svelte.d.ts +18 -0
  45. package/dist/components/docs/DocNavigation.svelte +56 -0
  46. package/dist/components/docs/DocNavigation.svelte.d.ts +12 -0
  47. package/dist/components/docs/DocTags.svelte +22 -0
  48. package/dist/components/docs/DocTags.svelte.d.ts +6 -0
  49. package/dist/components/docs/DraftBadge.svelte +10 -0
  50. package/dist/components/docs/DraftBadge.svelte.d.ts +18 -0
  51. package/dist/components/docs/Footer.svelte +72 -0
  52. package/dist/components/docs/Footer.svelte.d.ts +7 -0
  53. package/dist/components/docs/Frame.svelte +27 -0
  54. package/dist/components/docs/Frame.svelte.d.ts +9 -0
  55. package/dist/components/docs/Header.svelte +123 -0
  56. package/dist/components/docs/Header.svelte.d.ts +9 -0
  57. package/dist/components/docs/HeaderWithMenu.svelte +34 -0
  58. package/dist/components/docs/HeaderWithMenu.svelte.d.ts +17 -0
  59. package/dist/components/docs/HotReloadIndicator.svelte +44 -0
  60. package/dist/components/docs/HotReloadIndicator.svelte.d.ts +3 -0
  61. package/dist/components/docs/Icon.svelte +103 -0
  62. package/dist/components/docs/Icon.svelte.d.ts +11 -0
  63. package/dist/components/docs/Image.svelte +88 -0
  64. package/dist/components/docs/Image.svelte.d.ts +11 -0
  65. package/dist/components/docs/ImageCard.svelte +91 -0
  66. package/dist/components/docs/ImageCard.svelte.d.ts +12 -0
  67. package/dist/components/docs/ImageCardGrid.svelte +25 -0
  68. package/dist/components/docs/ImageCardGrid.svelte.d.ts +8 -0
  69. package/dist/components/docs/LayoutProviders.svelte +57 -0
  70. package/dist/components/docs/LayoutProviders.svelte.d.ts +9 -0
  71. package/dist/components/docs/Logo.svelte +25 -0
  72. package/dist/components/docs/Logo.svelte.d.ts +11 -0
  73. package/dist/components/docs/Math.svelte +54 -0
  74. package/dist/components/docs/Math.svelte.d.ts +7 -0
  75. package/dist/components/docs/MdxContent.svelte +41 -0
  76. package/dist/components/docs/MdxHotReload.svelte +78 -0
  77. package/dist/components/docs/MdxHotReload.svelte.d.ts +9 -0
  78. package/dist/components/docs/MdxLayout.svelte +16 -0
  79. package/dist/components/docs/MdxLayout.svelte.d.ts +6 -0
  80. package/dist/components/docs/Mermaid.svelte +88 -0
  81. package/dist/components/docs/Mermaid.svelte.d.ts +7 -0
  82. package/dist/components/docs/MobileDocLayout.svelte +211 -0
  83. package/dist/components/docs/MobileDocLayout.svelte.d.ts +35 -0
  84. package/dist/components/docs/MobileSidebar.svelte +122 -0
  85. package/dist/components/docs/MobileSidebar.svelte.d.ts +31 -0
  86. package/dist/components/docs/MobileSidebarWrapper.svelte +122 -0
  87. package/dist/components/docs/MobileSidebarWrapper.svelte.d.ts +32 -0
  88. package/dist/components/docs/NotFoundContent.svelte +40 -0
  89. package/dist/components/docs/NotFoundContent.svelte.d.ts +6 -0
  90. package/dist/components/docs/SearchHighlight.svelte +116 -0
  91. package/dist/components/docs/SearchHighlight.svelte.d.ts +3 -0
  92. package/dist/components/docs/SearchModal.svelte +239 -0
  93. package/dist/components/docs/SearchModal.svelte.d.ts +9 -0
  94. package/dist/components/docs/Sidebar.svelte +69 -0
  95. package/dist/components/docs/Sidebar.svelte.d.ts +31 -0
  96. package/dist/components/docs/SidebarMenuItems.svelte +344 -0
  97. package/dist/components/docs/SidebarMenuItems.svelte.d.ts +33 -0
  98. package/dist/components/docs/SidebarSkeleton.svelte +50 -0
  99. package/dist/components/docs/SidebarSkeleton.svelte.d.ts +18 -0
  100. package/dist/components/docs/SiteBanner.svelte +92 -0
  101. package/dist/components/docs/SiteBanner.svelte.d.ts +7 -0
  102. package/dist/components/docs/Step.svelte +44 -0
  103. package/dist/components/docs/Step.svelte.d.ts +8 -0
  104. package/dist/components/docs/Steps.svelte +15 -0
  105. package/dist/components/docs/Steps.svelte.d.ts +7 -0
  106. package/dist/components/docs/Tab.svelte +40 -0
  107. package/dist/components/docs/Tab.svelte.d.ts +8 -0
  108. package/dist/components/docs/TabGroups.svelte +183 -0
  109. package/dist/components/docs/TabGroups.svelte.d.ts +25 -0
  110. package/dist/components/docs/TableOfContents.svelte +100 -0
  111. package/dist/components/docs/TableOfContents.svelte.d.ts +9 -0
  112. package/dist/components/docs/Tabs.svelte +69 -0
  113. package/dist/components/docs/Tabs.svelte.d.ts +8 -0
  114. package/dist/components/docs/ThemeToggle.svelte +16 -0
  115. package/dist/components/docs/ThemeToggle.svelte.d.ts +18 -0
  116. package/dist/components/docs/Tooltip.svelte +44 -0
  117. package/dist/components/docs/Tooltip.svelte.d.ts +10 -0
  118. package/dist/components/docs/VersionSwitcher.svelte +95 -0
  119. package/dist/components/docs/VersionSwitcher.svelte.d.ts +7 -0
  120. package/dist/components/docs/Video.svelte +84 -0
  121. package/dist/components/docs/Video.svelte.d.ts +12 -0
  122. package/dist/components/docs/api/ApiEndpoint.svelte +61 -0
  123. package/dist/components/docs/api/ApiEndpoint.svelte.d.ts +11 -0
  124. package/dist/components/docs/api/ApiParams.svelte +80 -0
  125. package/dist/components/docs/api/ApiParams.svelte.d.ts +14 -0
  126. package/dist/components/docs/api/ApiPlayground.svelte +259 -0
  127. package/dist/components/docs/api/ApiPlayground.svelte.d.ts +16 -0
  128. package/dist/components/docs/api/ApiReference.svelte +278 -0
  129. package/dist/components/docs/api/ApiReference.svelte.d.ts +23 -0
  130. package/dist/components/docs/api/ApiResponse.svelte +66 -0
  131. package/dist/components/docs/api/ApiResponse.svelte.d.ts +9 -0
  132. package/dist/components/docs/api/index.d.ts +5 -0
  133. package/dist/components/docs/api/index.js +5 -0
  134. package/dist/components/docs/componentTextProps.d.ts +3 -0
  135. package/dist/components/docs/componentTextProps.js +61 -0
  136. package/dist/components/docs/index.d.ts +54 -0
  137. package/dist/components/docs/index.js +56 -0
  138. package/dist/components/global/VersionNotFound.svelte +48 -0
  139. package/dist/components/global/VersionNotFound.svelte.d.ts +7 -0
  140. package/dist/components/global/index.d.ts +1 -0
  141. package/dist/components/global/index.js +1 -0
  142. package/dist/components/index.d.ts +6 -822
  143. package/dist/components/index.js +11 -3854
  144. package/dist/components/ui/Badge.svelte +48 -0
  145. package/dist/components/ui/Badge.svelte.d.ts +15 -0
  146. package/dist/components/ui/Button.svelte +58 -0
  147. package/dist/components/ui/Button.svelte.d.ts +17 -0
  148. package/dist/components/ui/Dialog.svelte +16 -0
  149. package/dist/components/ui/Dialog.svelte.d.ts +9 -0
  150. package/dist/components/ui/DialogClose.svelte +16 -0
  151. package/dist/components/ui/DialogClose.svelte.d.ts +9 -0
  152. package/dist/components/ui/DialogContent.svelte +43 -0
  153. package/dist/components/ui/DialogContent.svelte.d.ts +10 -0
  154. package/dist/components/ui/DialogDescription.svelte +21 -0
  155. package/dist/components/ui/DialogDescription.svelte.d.ts +9 -0
  156. package/dist/components/ui/DialogFooter.svelte +20 -0
  157. package/dist/components/ui/DialogFooter.svelte.d.ts +9 -0
  158. package/dist/components/ui/DialogHeader.svelte +20 -0
  159. package/dist/components/ui/DialogHeader.svelte.d.ts +9 -0
  160. package/dist/components/ui/DialogTitle.svelte +21 -0
  161. package/dist/components/ui/DialogTitle.svelte.d.ts +9 -0
  162. package/dist/components/ui/Input.svelte +23 -0
  163. package/dist/components/ui/Input.svelte.d.ts +8 -0
  164. package/dist/components/ui/Textarea.svelte +19 -0
  165. package/dist/components/ui/Textarea.svelte.d.ts +7 -0
  166. package/dist/components/ui/index.d.ts +11 -0
  167. package/dist/components/ui/index.js +11 -0
  168. package/dist/config.d.ts +8 -0
  169. package/dist/config.js +9 -0
  170. package/dist/config.schema.json +471 -0
  171. package/dist/config.server.d.ts +46 -0
  172. package/dist/config.server.js +149 -0
  173. package/dist/{mdx-ColN3Cyg.d.mts → config.types.d.ts} +22 -75
  174. package/dist/config.types.js +39 -0
  175. package/dist/dev-utils.d.ts +29 -0
  176. package/dist/dev-utils.js +63 -0
  177. package/dist/index.d.ts +19 -4
  178. package/dist/index.js +25 -4861
  179. package/dist/mdx-cache.d.ts +41 -0
  180. package/dist/mdx-cache.js +160 -0
  181. package/dist/mdx-components.js +50 -1931
  182. package/dist/mdx-security.d.ts +76 -0
  183. package/dist/mdx-security.js +217 -0
  184. package/dist/mdx.d.ts +73 -0
  185. package/dist/mdx.js +1099 -0
  186. package/dist/middleware/index.d.ts +1 -0
  187. package/dist/middleware/index.js +2 -0
  188. package/dist/middleware/security.d.ts +22 -47
  189. package/dist/middleware/security.js +111 -137
  190. package/dist/parsers/base-parser.d.ts +14 -0
  191. package/dist/parsers/base-parser.js +1 -0
  192. package/dist/parsers/index.d.ts +16 -0
  193. package/dist/parsers/index.js +51 -0
  194. package/dist/parsers/openapi-parser.d.ts +18 -0
  195. package/dist/parsers/openapi-parser.js +209 -0
  196. package/dist/parsers/postman-parser.d.ts +20 -0
  197. package/dist/parsers/postman-parser.js +260 -0
  198. package/dist/parsers/specra-parser.d.ts +10 -0
  199. package/dist/parsers/specra-parser.js +18 -0
  200. package/dist/redirects.d.ts +12 -0
  201. package/dist/redirects.js +30 -0
  202. package/dist/remark-code-meta.d.ts +6 -0
  203. package/dist/remark-code-meta.js +21 -0
  204. package/dist/sidebar-utils.d.ts +59 -0
  205. package/dist/sidebar-utils.js +144 -0
  206. package/dist/stores/config.d.ts +20 -0
  207. package/dist/stores/config.js +45 -0
  208. package/dist/stores/index.d.ts +4 -0
  209. package/dist/stores/index.js +4 -0
  210. package/dist/stores/sidebar.d.ts +7 -0
  211. package/dist/stores/sidebar.js +12 -0
  212. package/dist/stores/tabs.d.ts +6 -0
  213. package/dist/stores/tabs.js +41 -0
  214. package/dist/stores/theme.d.ts +7 -0
  215. package/dist/stores/theme.js +75 -0
  216. package/dist/{styles.css → styles/globals.css} +136 -6
  217. package/dist/toc.d.ts +9 -0
  218. package/dist/toc.js +15 -0
  219. package/dist/utils.d.ts +13 -0
  220. package/dist/utils.js +30 -0
  221. package/package.json +47 -90
  222. package/dist/app/api/mdx-watch/route.d.mts +0 -10
  223. package/dist/app/api/mdx-watch/route.d.ts +0 -10
  224. package/dist/app/api/mdx-watch/route.js +0 -118
  225. package/dist/app/api/mdx-watch/route.js.map +0 -1
  226. package/dist/app/api/mdx-watch/route.mjs +0 -91
  227. package/dist/app/api/mdx-watch/route.mjs.map +0 -1
  228. package/dist/chunk-6S3EJVEO.mjs +0 -259
  229. package/dist/chunk-6S3EJVEO.mjs.map +0 -1
  230. package/dist/chunk-BE7EROIW.mjs +0 -212
  231. package/dist/chunk-BE7EROIW.mjs.map +0 -1
  232. package/dist/chunk-CWHRZHZO.mjs +0 -168
  233. package/dist/chunk-CWHRZHZO.mjs.map +0 -1
  234. package/dist/chunk-D5VDVYFY.mjs +0 -1325
  235. package/dist/chunk-D5VDVYFY.mjs.map +0 -1
  236. package/dist/chunk-WMCO2UX5.mjs +0 -585
  237. package/dist/chunk-WMCO2UX5.mjs.map +0 -1
  238. package/dist/chunk-XEMGCPZZ.mjs +0 -475
  239. package/dist/chunk-XEMGCPZZ.mjs.map +0 -1
  240. package/dist/components/index.d.mts +0 -822
  241. package/dist/components/index.js.map +0 -1
  242. package/dist/components/index.mjs +0 -3741
  243. package/dist/components/index.mjs.map +0 -1
  244. package/dist/index.d.mts +0 -4
  245. package/dist/index.js.map +0 -1
  246. package/dist/index.mjs +0 -1897
  247. package/dist/index.mjs.map +0 -1
  248. package/dist/layouts/index.d.mts +0 -34
  249. package/dist/layouts/index.d.ts +0 -34
  250. package/dist/layouts/index.js +0 -453
  251. package/dist/layouts/index.js.map +0 -1
  252. package/dist/layouts/index.mjs +0 -173
  253. package/dist/layouts/index.mjs.map +0 -1
  254. package/dist/lib/index.d.mts +0 -583
  255. package/dist/lib/index.d.ts +0 -583
  256. package/dist/lib/index.js +0 -1595
  257. package/dist/lib/index.js.map +0 -1
  258. package/dist/lib/index.mjs +0 -111
  259. package/dist/lib/index.mjs.map +0 -1
  260. package/dist/mdx-ColN3Cyg.d.ts +0 -352
  261. package/dist/mdx-components.d.mts +0 -86
  262. package/dist/mdx-components.d.ts +0 -86
  263. package/dist/mdx-components.js.map +0 -1
  264. package/dist/mdx-components.mjs +0 -206
  265. package/dist/mdx-components.mjs.map +0 -1
  266. package/dist/middleware/security.d.mts +0 -82
  267. package/dist/middleware/security.js.map +0 -1
  268. package/dist/middleware/security.mjs +0 -84
  269. package/dist/middleware/security.mjs.map +0 -1
  270. package/dist/styles.css.map +0 -1
  271. package/dist/styles.d.mts +0 -2
  272. package/dist/styles.d.ts +0 -2
  273. package/dist/styles.js +0 -2
  274. package/dist/styles.js.map +0 -1
  275. package/dist/styles.mjs +0 -1
  276. package/dist/styles.mjs.map +0 -1
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ children?: Snippet;
6
+ type?: 'single' | 'multiple';
7
+ collapsible?: boolean;
8
+ class?: string;
9
+ }
10
+
11
+ let { children, type = 'multiple', collapsible, class: className }: Props = $props();
12
+ </script>
13
+
14
+ <div class={className || 'my-6 space-y-2'}>
15
+ {#if children}
16
+ {@render children()}
17
+ {/if}
18
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ children?: Snippet;
4
+ type?: 'single' | 'multiple';
5
+ collapsible?: boolean;
6
+ class?: string;
7
+ }
8
+ declare const Accordion: import("svelte").Component<Props, {}, "">;
9
+ type Accordion = ReturnType<typeof Accordion>;
10
+ export default Accordion;
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ import { ChevronDown } from 'lucide-svelte';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ title: string;
7
+ defaultOpen?: boolean;
8
+ value?: string;
9
+ children?: Snippet;
10
+ }
11
+
12
+ let { title, defaultOpen = false, value, children }: Props = $props();
13
+
14
+ let isOpen = $state(defaultOpen);
15
+
16
+ function toggle() {
17
+ isOpen = !isOpen;
18
+ }
19
+ </script>
20
+
21
+ <div class="border border-border rounded-xl overflow-hidden mb-2">
22
+ <button
23
+ onclick={toggle}
24
+ class="w-full flex items-center justify-between p-4 text-left bg-muted/30 hover:bg-muted/50 transition-colors"
25
+ aria-expanded={isOpen}
26
+ >
27
+ <span class="font-medium text-foreground">{title}</span>
28
+ <ChevronDown
29
+ class="h-5 w-5 text-muted-foreground transition-transform {isOpen ? 'rotate-180' : ''}"
30
+ />
31
+ </button>
32
+ {#if isOpen}
33
+ <div class="p-4 border-t border-border bg-background">
34
+ <div class="prose prose-sm dark:prose-invert max-w-none [&>*:last-child]:mb-0">
35
+ {#if children}
36
+ {@render children()}
37
+ {/if}
38
+ </div>
39
+ </div>
40
+ {/if}
41
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ title: string;
4
+ defaultOpen?: boolean;
5
+ value?: string;
6
+ children?: Snippet;
7
+ }
8
+ declare const AccordionItem: import("svelte").Component<Props, {}, "">;
9
+ type AccordionItem = ReturnType<typeof AccordionItem>;
10
+ export default AccordionItem;
@@ -0,0 +1,28 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ type BadgeVariant = 'default' | 'success' | 'warning' | 'error' | 'info';
5
+
6
+ interface Props {
7
+ variant?: BadgeVariant;
8
+ children?: Snippet;
9
+ }
10
+
11
+ let { variant = 'default', children }: Props = $props();
12
+
13
+ const variants: Record<BadgeVariant, string> = {
14
+ default: 'bg-muted text-foreground border-border',
15
+ success: 'bg-green-500/10 text-green-600 dark:text-green-400 border-green-500/20',
16
+ warning: 'bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 border-yellow-500/20',
17
+ error: 'bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20',
18
+ info: 'bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/20',
19
+ };
20
+
21
+ let classes = $derived(variants[variant] || variants.default);
22
+ </script>
23
+
24
+ <span class="inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium border {classes}">
25
+ {#if children}
26
+ {@render children()}
27
+ {/if}
28
+ </span>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ type BadgeVariant = 'default' | 'success' | 'warning' | 'error' | 'info';
3
+ interface Props {
4
+ variant?: BadgeVariant;
5
+ children?: Snippet;
6
+ }
7
+ declare const Badge: import("svelte").Component<Props, {}, "">;
8
+ type Badge = ReturnType<typeof Badge>;
9
+ export default Badge;
@@ -0,0 +1,80 @@
1
+ <script lang="ts">
2
+ import { ChevronRight } from 'lucide-svelte';
3
+ import { getConfigContext } from '../../stores/config.js';
4
+
5
+ interface Props {
6
+ version: string;
7
+ slug: string;
8
+ title: string;
9
+ }
10
+
11
+ let { version, slug, title }: Props = $props();
12
+
13
+ const configStore = getConfigContext();
14
+ let config = $derived($configStore);
15
+
16
+ let breadcrumbs = $derived.by(() => {
17
+ const i18n = config.features?.i18n;
18
+ const locales = typeof i18n === 'object' ? i18n.locales : i18n ? ['en'] : [];
19
+ const defaultLocale = typeof i18n === 'object' ? i18n.defaultLocale : 'en';
20
+
21
+ const parts = slug.split('/');
22
+
23
+ // Check if first part is a locale
24
+ const potentialLocale = parts[0];
25
+ const isLc = locales.includes(potentialLocale);
26
+
27
+ const homeHref = isLc ? `/docs/${version}/${potentialLocale}` : `/docs/${version}`;
28
+
29
+ const crumbs: Array<{ label: string; href: string }> = [
30
+ { label: 'Docs', href: homeHref }
31
+ ];
32
+
33
+ // Build breadcrumb path
34
+ let currentPath = '';
35
+ for (let i = 0; i < parts.length - 1; i++) {
36
+ const part = parts[i];
37
+ currentPath += (currentPath ? '/' : '') + part;
38
+
39
+ // Skip the locale part in the breadcrumb visual trail if it's the first part
40
+ if (i === 0 && isLc) {
41
+ continue;
42
+ }
43
+
44
+ crumbs.push({
45
+ label: part
46
+ .replace(/-/g, ' ')
47
+ .replace(/\b\w/g, (l) => l.toUpperCase()),
48
+ href: `/docs/${version}/${currentPath}`
49
+ });
50
+ }
51
+
52
+ // Add current page
53
+ crumbs.push({
54
+ label: title,
55
+ href: `/docs/${version}/${slug}`
56
+ });
57
+
58
+ return crumbs;
59
+ });
60
+ </script>
61
+
62
+ <nav class="flex items-center gap-2 text-sm text-muted-foreground mb-4" aria-label="Breadcrumb">
63
+ {#each breadcrumbs as crumb, index (crumb.href)}
64
+ <div class="flex items-center gap-2">
65
+ {#if index > 0}
66
+ <ChevronRight class="h-4 w-4" />
67
+ {/if}
68
+ {#if index === breadcrumbs.length - 1}
69
+ <span class="text-foreground font-medium">{crumb.label}</span>
70
+ {:else}
71
+ <a
72
+ href={crumb.href}
73
+ class="hover:text-foreground transition-colors"
74
+ >
75
+ {crumb.label}
76
+ </a>
77
+ {/if}
78
+ </div>
79
+ {/each}
80
+ </nav>
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ version: string;
3
+ slug: string;
4
+ title: string;
5
+ }
6
+ declare const Breadcrumb: import("svelte").Component<Props, {}, "">;
7
+ type Breadcrumb = ReturnType<typeof Breadcrumb>;
8
+ export default Breadcrumb;
@@ -0,0 +1,96 @@
1
+ <script lang="ts">
2
+ import {
3
+ Info,
4
+ AlertTriangle,
5
+ CheckCircle2,
6
+ XCircle,
7
+ Lightbulb,
8
+ } from 'lucide-svelte';
9
+ import type { Snippet } from 'svelte';
10
+
11
+ type CalloutType = 'info' | 'warning' | 'success' | 'error' | 'tip' | 'note' | 'danger';
12
+
13
+ interface Props {
14
+ type?: CalloutType;
15
+ title?: string;
16
+ children?: Snippet;
17
+ }
18
+
19
+ let { type = 'info', title, children }: Props = $props();
20
+
21
+ const configs: Record<CalloutType, {
22
+ icon: typeof Info;
23
+ className: string;
24
+ iconClassName: string;
25
+ titleClassName: string;
26
+ defaultTitle: string;
27
+ }> = {
28
+ info: {
29
+ icon: Info,
30
+ className: 'bg-blue-500/10 border-blue-500/30 text-blue-900 dark:bg-blue-400/5 dark:border-blue-500/20 dark:text-blue-400',
31
+ iconClassName: 'text-blue-600 dark:text-blue-400',
32
+ titleClassName: 'text-blue-700 dark:text-blue-300',
33
+ defaultTitle: 'Info',
34
+ },
35
+ note: {
36
+ icon: Info,
37
+ className: 'bg-blue-500/10 border-blue-500/30 text-blue-900 dark:bg-blue-400/5 dark:border-blue-500/20 dark:text-blue-400',
38
+ iconClassName: 'text-blue-600 dark:text-blue-400',
39
+ titleClassName: 'text-blue-700 dark:text-blue-300',
40
+ defaultTitle: 'Note',
41
+ },
42
+ warning: {
43
+ icon: AlertTriangle,
44
+ className: 'bg-yellow-500/10 border-yellow-500/30 text-yellow-900 dark:bg-yellow-400/5 dark:border-yellow-500/20 dark:text-yellow-400',
45
+ iconClassName: 'text-yellow-600 dark:text-yellow-400',
46
+ titleClassName: 'text-yellow-700 dark:text-yellow-300',
47
+ defaultTitle: 'Warning',
48
+ },
49
+ success: {
50
+ icon: CheckCircle2,
51
+ className: 'bg-green-500/10 border-green-500/30 text-green-900 dark:bg-green-400/5 dark:border-green-500/20 dark:text-green-400',
52
+ iconClassName: 'text-green-600 dark:text-green-400',
53
+ titleClassName: 'text-green-700 dark:text-green-300',
54
+ defaultTitle: 'Success',
55
+ },
56
+ error: {
57
+ icon: XCircle,
58
+ className: 'bg-red-500/10 border-red-500/30 text-red-900 dark:bg-red-400/5 dark:border-red-500/20 dark:text-red-400',
59
+ iconClassName: 'text-red-600 dark:text-red-400',
60
+ titleClassName: 'text-red-700 dark:text-red-300',
61
+ defaultTitle: 'Error',
62
+ },
63
+ danger: {
64
+ icon: XCircle,
65
+ className: 'bg-red-500/10 border-red-500/30 text-red-900 dark:bg-red-400/5 dark:border-red-500/20 dark:text-red-400',
66
+ iconClassName: 'text-red-600 dark:text-red-400',
67
+ titleClassName: 'text-red-700 dark:text-red-300',
68
+ defaultTitle: 'Danger',
69
+ },
70
+ tip: {
71
+ icon: Lightbulb,
72
+ className: 'bg-purple-500/10 border-purple-500/30 text-purple-900 dark:bg-purple-400/5 dark:border-purple-500/20 dark:text-purple-400',
73
+ iconClassName: 'text-purple-600 dark:text-purple-400',
74
+ titleClassName: 'text-purple-700 dark:text-purple-300',
75
+ defaultTitle: 'Tip',
76
+ },
77
+ };
78
+
79
+ let config = $derived(configs[type] || configs.info);
80
+ let displayTitle = $derived(title || config.defaultTitle);
81
+ let IconComponent = $derived(config.icon);
82
+ </script>
83
+
84
+ <div class="flex gap-3 p-4 rounded-xl border my-2 {config.className}">
85
+ <div class="flex-shrink-0 mt-0.5">
86
+ <IconComponent class="h-5 w-5 {config.iconClassName}" />
87
+ </div>
88
+ <div class="flex-1 space-y-0">
89
+ <div class="font-semibold text-sm {config.titleClassName}">{displayTitle}</div>
90
+ <div class="text-sm leading-relaxed [&>p]:mb-0 [&>p]:text-current">
91
+ {#if children}
92
+ {@render children()}
93
+ {/if}
94
+ </div>
95
+ </div>
96
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ type CalloutType = 'info' | 'warning' | 'success' | 'error' | 'tip' | 'note' | 'danger';
3
+ interface Props {
4
+ type?: CalloutType;
5
+ title?: string;
6
+ children?: Snippet;
7
+ }
8
+ declare const Callout: import("svelte").Component<Props, {}, "">;
9
+ type Callout = ReturnType<typeof Callout>;
10
+ export default Callout;
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ import { ArrowRight, ExternalLink } from 'lucide-svelte';
3
+ import type { Snippet } from 'svelte';
4
+ import Icon from './Icon.svelte';
5
+
6
+ interface Props {
7
+ title: string;
8
+ description?: string;
9
+ href?: string;
10
+ icon?: string;
11
+ external?: boolean;
12
+ children?: Snippet;
13
+ }
14
+
15
+ let { title, description, href, icon, external = false, children }: Props = $props();
16
+ </script>
17
+
18
+ {#snippet cardContent(isLink: boolean)}
19
+ <div class="flex items-center gap-3">
20
+ {#if icon}
21
+ <div class="shrink-0 w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center text-primary">
22
+ <Icon {icon} size={20} />
23
+ </div>
24
+ {/if}
25
+ <div class="flex-1 min-w-0">
26
+ <h3 class="font-semibold text-foreground mb-1 no-underline {isLink ? 'group-hover:text-primary transition-colors' : ''}">
27
+ {title}
28
+ </h3>
29
+ {#if description}
30
+ <p class="text-sm text-muted-foreground line-clamp-2 no-underline">{description}</p>
31
+ {/if}
32
+ {#if children}
33
+ <div class="mt-2 text-sm text-muted-foreground no-underline">
34
+ {@render children()}
35
+ </div>
36
+ {/if}
37
+ </div>
38
+ {#if href}
39
+ <div class="shrink-0 self-start mt-1">
40
+ {#if external}
41
+ <ExternalLink class="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
42
+ {:else}
43
+ <ArrowRight class="h-4 w-4 text-muted-foreground group-hover:text-primary group-hover:translate-x-1 transition-all" />
44
+ {/if}
45
+ </div>
46
+ {/if}
47
+ </div>
48
+ {/snippet}
49
+
50
+ {#if href}
51
+ <a
52
+ {href}
53
+ class="card-link group block p-4 rounded-xl border border-border hover:border-primary/50 hover:bg-muted/50 transition-all"
54
+ target={external ? '_blank' : undefined}
55
+ rel={external ? 'noopener noreferrer' : undefined}
56
+ >
57
+ {@render cardContent(true)}
58
+ </a>
59
+ {:else}
60
+ <div class="p-4 rounded-xl border border-border bg-muted/30 no-underline">
61
+ {@render cardContent(false)}
62
+ </div>
63
+ {/if}
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ title: string;
4
+ description?: string;
5
+ href?: string;
6
+ icon?: string;
7
+ external?: boolean;
8
+ children?: Snippet;
9
+ }
10
+ declare const Card: import("svelte").Component<Props, {}, "">;
11
+ type Card = ReturnType<typeof Card>;
12
+ export default Card;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ cols?: 1 | 2 | 3;
6
+ children?: Snippet;
7
+ }
8
+
9
+ let { cols = 2, children }: Props = $props();
10
+
11
+ const gridCols: Record<number, string> = {
12
+ 1: 'grid-cols-1',
13
+ 2: 'grid-cols-1 md:grid-cols-2',
14
+ 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
15
+ };
16
+
17
+ let gridClass = $derived(gridCols[cols] || gridCols[2]);
18
+ </script>
19
+
20
+ <div class="grid {gridClass} gap-4 my-6">
21
+ {#if children}
22
+ {@render children()}
23
+ {/if}
24
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ cols?: 1 | 2 | 3;
4
+ children?: Snippet;
5
+ }
6
+ declare const CardGrid: import("svelte").Component<Props, {}, "">;
7
+ type CardGrid = ReturnType<typeof CardGrid>;
8
+ export default CardGrid;
@@ -0,0 +1,110 @@
1
+ <script lang="ts">
2
+ import { FileText, ArrowRight } from 'lucide-svelte';
3
+ import type { SpecraConfig } from '../../config.types.js';
4
+ import type { Snippet } from 'svelte';
5
+
6
+ interface DocItem {
7
+ slug: string;
8
+ filePath: string;
9
+ version?: string;
10
+ meta?: {
11
+ title?: string;
12
+ description?: string;
13
+ sidebar_position?: number;
14
+ icon?: string;
15
+ [key: string]: unknown;
16
+ };
17
+ title?: string;
18
+ description?: string;
19
+ [key: string]: unknown;
20
+ }
21
+
22
+ interface Props {
23
+ categoryPath: string;
24
+ version: string;
25
+ allDocs: DocItem[];
26
+ title?: string;
27
+ description?: string;
28
+ content?: Snippet;
29
+ config: SpecraConfig;
30
+ }
31
+
32
+ let { categoryPath, version, allDocs, title, description, content, config }: Props = $props();
33
+
34
+ // Filter docs that belong to this category (direct children)
35
+ const childDocs = $derived(() => {
36
+ if (!allDocs || allDocs.length === 0) return [];
37
+
38
+ return allDocs
39
+ .filter((doc) => {
40
+ const docPath = doc.filePath || doc.slug;
41
+ // Match direct children of this category path
42
+ if (!docPath.startsWith(categoryPath + '/')) return false;
43
+ const remaining = docPath.slice(categoryPath.length + 1);
44
+ // Only direct children (no further slashes, or is an index)
45
+ return !remaining.includes('/') && remaining !== 'index';
46
+ })
47
+ .sort((a, b) => {
48
+ const posA = a.meta?.sidebar_position ?? 999;
49
+ const posB = b.meta?.sidebar_position ?? 999;
50
+ return posA - posB;
51
+ });
52
+ });
53
+
54
+ const baseUrl = $derived(config.site?.baseUrl?.replace(/\/$/, '') || '');
55
+ </script>
56
+
57
+ <div class="space-y-8">
58
+ <!-- Category Header -->
59
+ {#if title}
60
+ <div class="space-y-2">
61
+ <h1 class="text-3xl font-bold tracking-tight text-foreground">{title}</h1>
62
+ {#if description}
63
+ <p class="text-lg text-muted-foreground">{description}</p>
64
+ {/if}
65
+ </div>
66
+ {/if}
67
+
68
+ <!-- Rendered mdsvex content via slot -->
69
+ {#if content}
70
+ <div class="prose dark:prose-invert max-w-none">
71
+ {@render content()}
72
+ </div>
73
+ {/if}
74
+
75
+ <!-- Child Documents Grid -->
76
+ {#if childDocs().length > 0}
77
+ <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-8">
78
+ {#each childDocs() as doc}
79
+ {@const docTitle = doc.meta?.title || doc.title || doc.slug.split('/').pop() || 'Untitled'}
80
+ {@const docDescription = doc.meta?.description || doc.description || ''}
81
+ {@const docSlug = doc.slug}
82
+
83
+ <a
84
+ href="{baseUrl}/{version}/{docSlug}"
85
+ class="group flex flex-col gap-2 p-5 rounded-lg border border-border bg-card hover:bg-accent/50 hover:border-accent-foreground/20 transition-all duration-200"
86
+ >
87
+ <div class="flex items-start justify-between gap-2">
88
+ <div class="flex items-center gap-2">
89
+ <FileText class="h-4 w-4 text-muted-foreground shrink-0 mt-0.5" />
90
+ <h3 class="text-sm font-semibold text-foreground group-hover:text-primary transition-colors">
91
+ {docTitle}
92
+ </h3>
93
+ </div>
94
+ <ArrowRight class="h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity shrink-0 mt-0.5" />
95
+ </div>
96
+ {#if docDescription}
97
+ <p class="text-sm text-muted-foreground line-clamp-2 pl-6">
98
+ {docDescription}
99
+ </p>
100
+ {/if}
101
+ </a>
102
+ {/each}
103
+ </div>
104
+ {:else if !content}
105
+ <div class="flex flex-col items-center justify-center py-12 text-center">
106
+ <FileText class="h-10 w-10 text-muted-foreground mb-4" />
107
+ <p class="text-muted-foreground">No documents found in this category.</p>
108
+ </div>
109
+ {/if}
110
+ </div>
@@ -0,0 +1,29 @@
1
+ import type { SpecraConfig } from '../../config.types.js';
2
+ import type { Snippet } from 'svelte';
3
+ interface DocItem {
4
+ slug: string;
5
+ filePath: string;
6
+ version?: string;
7
+ meta?: {
8
+ title?: string;
9
+ description?: string;
10
+ sidebar_position?: number;
11
+ icon?: string;
12
+ [key: string]: unknown;
13
+ };
14
+ title?: string;
15
+ description?: string;
16
+ [key: string]: unknown;
17
+ }
18
+ interface Props {
19
+ categoryPath: string;
20
+ version: string;
21
+ allDocs: DocItem[];
22
+ title?: string;
23
+ description?: string;
24
+ content?: Snippet;
25
+ config: SpecraConfig;
26
+ }
27
+ declare const CategoryIndex: import("svelte").Component<Props, {}, "">;
28
+ type CategoryIndex = ReturnType<typeof CategoryIndex>;
29
+ export default CategoryIndex;