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.
- package/LICENSE.MD +25 -4
- package/README.md +67 -58
- package/config/specra.config.schema.json +16 -0
- package/config/svelte-config.js +63 -0
- package/dist/api-parser.types.d.ts +59 -0
- package/dist/api-parser.types.js +5 -0
- package/dist/api.types.d.ts +137 -0
- package/dist/api.types.js +5 -0
- package/dist/category.d.ts +21 -0
- package/dist/category.js +48 -0
- package/dist/components/ConfigProvider.svelte +13 -0
- package/dist/components/ConfigProvider.svelte.d.ts +31 -0
- package/dist/components/docs/Accordion.svelte +18 -0
- package/dist/components/docs/Accordion.svelte.d.ts +10 -0
- package/dist/components/docs/AccordionItem.svelte +41 -0
- package/dist/components/docs/AccordionItem.svelte.d.ts +10 -0
- package/dist/components/docs/Badge.svelte +28 -0
- package/dist/components/docs/Badge.svelte.d.ts +9 -0
- package/dist/components/docs/Breadcrumb.svelte +80 -0
- package/dist/components/docs/Breadcrumb.svelte.d.ts +8 -0
- package/dist/components/docs/Callout.svelte +96 -0
- package/dist/components/docs/Callout.svelte.d.ts +10 -0
- package/dist/components/docs/Card.svelte +63 -0
- package/dist/components/docs/Card.svelte.d.ts +12 -0
- package/dist/components/docs/CardGrid.svelte +24 -0
- package/dist/components/docs/CardGrid.svelte.d.ts +8 -0
- package/dist/components/docs/CategoryIndex.svelte +110 -0
- package/dist/components/docs/CategoryIndex.svelte.d.ts +29 -0
- package/dist/components/docs/CodeBlock.svelte +172 -0
- package/dist/components/docs/CodeBlock.svelte.d.ts +8 -0
- package/dist/components/docs/Column.svelte +25 -0
- package/dist/components/docs/Column.svelte.d.ts +8 -0
- package/dist/components/docs/Columns.svelte +38 -0
- package/dist/components/docs/Columns.svelte.d.ts +13 -0
- package/dist/components/docs/DevModeBadge.svelte +15 -0
- package/dist/components/docs/DevModeBadge.svelte.d.ts +18 -0
- package/dist/components/docs/DocBadge.svelte +28 -0
- package/dist/components/docs/DocBadge.svelte.d.ts +9 -0
- package/dist/components/docs/DocLayout.svelte +107 -0
- package/dist/components/docs/DocLayout.svelte.d.ts +32 -0
- package/dist/components/docs/DocLoading.svelte +53 -0
- package/dist/components/docs/DocLoading.svelte.d.ts +18 -0
- package/dist/components/docs/DocMetadata.svelte +106 -0
- package/dist/components/docs/DocMetadata.svelte.d.ts +18 -0
- package/dist/components/docs/DocNavigation.svelte +56 -0
- package/dist/components/docs/DocNavigation.svelte.d.ts +12 -0
- package/dist/components/docs/DocTags.svelte +22 -0
- package/dist/components/docs/DocTags.svelte.d.ts +6 -0
- package/dist/components/docs/DraftBadge.svelte +10 -0
- package/dist/components/docs/DraftBadge.svelte.d.ts +18 -0
- package/dist/components/docs/Footer.svelte +72 -0
- package/dist/components/docs/Footer.svelte.d.ts +7 -0
- package/dist/components/docs/Frame.svelte +27 -0
- package/dist/components/docs/Frame.svelte.d.ts +9 -0
- package/dist/components/docs/Header.svelte +123 -0
- package/dist/components/docs/Header.svelte.d.ts +9 -0
- package/dist/components/docs/HeaderWithMenu.svelte +34 -0
- package/dist/components/docs/HeaderWithMenu.svelte.d.ts +17 -0
- package/dist/components/docs/HotReloadIndicator.svelte +44 -0
- package/dist/components/docs/HotReloadIndicator.svelte.d.ts +3 -0
- package/dist/components/docs/Icon.svelte +103 -0
- package/dist/components/docs/Icon.svelte.d.ts +11 -0
- package/dist/components/docs/Image.svelte +88 -0
- package/dist/components/docs/Image.svelte.d.ts +11 -0
- package/dist/components/docs/ImageCard.svelte +91 -0
- package/dist/components/docs/ImageCard.svelte.d.ts +12 -0
- package/dist/components/docs/ImageCardGrid.svelte +25 -0
- package/dist/components/docs/ImageCardGrid.svelte.d.ts +8 -0
- package/dist/components/docs/LayoutProviders.svelte +57 -0
- package/dist/components/docs/LayoutProviders.svelte.d.ts +9 -0
- package/dist/components/docs/Logo.svelte +25 -0
- package/dist/components/docs/Logo.svelte.d.ts +11 -0
- package/dist/components/docs/Math.svelte +54 -0
- package/dist/components/docs/Math.svelte.d.ts +7 -0
- package/dist/components/docs/MdxContent.svelte +41 -0
- package/dist/components/docs/MdxHotReload.svelte +78 -0
- package/dist/components/docs/MdxHotReload.svelte.d.ts +9 -0
- package/dist/components/docs/MdxLayout.svelte +16 -0
- package/dist/components/docs/MdxLayout.svelte.d.ts +6 -0
- package/dist/components/docs/Mermaid.svelte +88 -0
- package/dist/components/docs/Mermaid.svelte.d.ts +7 -0
- package/dist/components/docs/MobileDocLayout.svelte +211 -0
- package/dist/components/docs/MobileDocLayout.svelte.d.ts +35 -0
- package/dist/components/docs/MobileSidebar.svelte +122 -0
- package/dist/components/docs/MobileSidebar.svelte.d.ts +31 -0
- package/dist/components/docs/MobileSidebarWrapper.svelte +122 -0
- package/dist/components/docs/MobileSidebarWrapper.svelte.d.ts +32 -0
- package/dist/components/docs/NotFoundContent.svelte +40 -0
- package/dist/components/docs/NotFoundContent.svelte.d.ts +6 -0
- package/dist/components/docs/SearchHighlight.svelte +116 -0
- package/dist/components/docs/SearchHighlight.svelte.d.ts +3 -0
- package/dist/components/docs/SearchModal.svelte +239 -0
- package/dist/components/docs/SearchModal.svelte.d.ts +9 -0
- package/dist/components/docs/Sidebar.svelte +69 -0
- package/dist/components/docs/Sidebar.svelte.d.ts +31 -0
- package/dist/components/docs/SidebarMenuItems.svelte +344 -0
- package/dist/components/docs/SidebarMenuItems.svelte.d.ts +33 -0
- package/dist/components/docs/SidebarSkeleton.svelte +50 -0
- package/dist/components/docs/SidebarSkeleton.svelte.d.ts +18 -0
- package/dist/components/docs/SiteBanner.svelte +92 -0
- package/dist/components/docs/SiteBanner.svelte.d.ts +7 -0
- package/dist/components/docs/Step.svelte +44 -0
- package/dist/components/docs/Step.svelte.d.ts +8 -0
- package/dist/components/docs/Steps.svelte +15 -0
- package/dist/components/docs/Steps.svelte.d.ts +7 -0
- package/dist/components/docs/Tab.svelte +40 -0
- package/dist/components/docs/Tab.svelte.d.ts +8 -0
- package/dist/components/docs/TabGroups.svelte +183 -0
- package/dist/components/docs/TabGroups.svelte.d.ts +25 -0
- package/dist/components/docs/TableOfContents.svelte +100 -0
- package/dist/components/docs/TableOfContents.svelte.d.ts +9 -0
- package/dist/components/docs/Tabs.svelte +69 -0
- package/dist/components/docs/Tabs.svelte.d.ts +8 -0
- package/dist/components/docs/ThemeToggle.svelte +16 -0
- package/dist/components/docs/ThemeToggle.svelte.d.ts +18 -0
- package/dist/components/docs/Tooltip.svelte +44 -0
- package/dist/components/docs/Tooltip.svelte.d.ts +10 -0
- package/dist/components/docs/VersionSwitcher.svelte +95 -0
- package/dist/components/docs/VersionSwitcher.svelte.d.ts +7 -0
- package/dist/components/docs/Video.svelte +84 -0
- package/dist/components/docs/Video.svelte.d.ts +12 -0
- package/dist/components/docs/api/ApiEndpoint.svelte +61 -0
- package/dist/components/docs/api/ApiEndpoint.svelte.d.ts +11 -0
- package/dist/components/docs/api/ApiParams.svelte +80 -0
- package/dist/components/docs/api/ApiParams.svelte.d.ts +14 -0
- package/dist/components/docs/api/ApiPlayground.svelte +259 -0
- package/dist/components/docs/api/ApiPlayground.svelte.d.ts +16 -0
- package/dist/components/docs/api/ApiReference.svelte +278 -0
- package/dist/components/docs/api/ApiReference.svelte.d.ts +23 -0
- package/dist/components/docs/api/ApiResponse.svelte +66 -0
- package/dist/components/docs/api/ApiResponse.svelte.d.ts +9 -0
- package/dist/components/docs/api/index.d.ts +5 -0
- package/dist/components/docs/api/index.js +5 -0
- package/dist/components/docs/componentTextProps.d.ts +3 -0
- package/dist/components/docs/componentTextProps.js +61 -0
- package/dist/components/docs/index.d.ts +54 -0
- package/dist/components/docs/index.js +56 -0
- package/dist/components/global/VersionNotFound.svelte +48 -0
- package/dist/components/global/VersionNotFound.svelte.d.ts +7 -0
- package/dist/components/global/index.d.ts +1 -0
- package/dist/components/global/index.js +1 -0
- package/dist/components/index.d.ts +6 -822
- package/dist/components/index.js +11 -3854
- package/dist/components/ui/Badge.svelte +48 -0
- package/dist/components/ui/Badge.svelte.d.ts +15 -0
- package/dist/components/ui/Button.svelte +58 -0
- package/dist/components/ui/Button.svelte.d.ts +17 -0
- package/dist/components/ui/Dialog.svelte +16 -0
- package/dist/components/ui/Dialog.svelte.d.ts +9 -0
- package/dist/components/ui/DialogClose.svelte +16 -0
- package/dist/components/ui/DialogClose.svelte.d.ts +9 -0
- package/dist/components/ui/DialogContent.svelte +43 -0
- package/dist/components/ui/DialogContent.svelte.d.ts +10 -0
- package/dist/components/ui/DialogDescription.svelte +21 -0
- package/dist/components/ui/DialogDescription.svelte.d.ts +9 -0
- package/dist/components/ui/DialogFooter.svelte +20 -0
- package/dist/components/ui/DialogFooter.svelte.d.ts +9 -0
- package/dist/components/ui/DialogHeader.svelte +20 -0
- package/dist/components/ui/DialogHeader.svelte.d.ts +9 -0
- package/dist/components/ui/DialogTitle.svelte +21 -0
- package/dist/components/ui/DialogTitle.svelte.d.ts +9 -0
- package/dist/components/ui/Input.svelte +23 -0
- package/dist/components/ui/Input.svelte.d.ts +8 -0
- package/dist/components/ui/Textarea.svelte +19 -0
- package/dist/components/ui/Textarea.svelte.d.ts +7 -0
- package/dist/components/ui/index.d.ts +11 -0
- package/dist/components/ui/index.js +11 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +9 -0
- package/dist/config.schema.json +471 -0
- package/dist/config.server.d.ts +46 -0
- package/dist/config.server.js +149 -0
- package/dist/{mdx-ColN3Cyg.d.mts → config.types.d.ts} +22 -75
- package/dist/config.types.js +39 -0
- package/dist/dev-utils.d.ts +29 -0
- package/dist/dev-utils.js +63 -0
- package/dist/index.d.ts +19 -4
- package/dist/index.js +25 -4861
- package/dist/mdx-cache.d.ts +41 -0
- package/dist/mdx-cache.js +160 -0
- package/dist/mdx-components.js +50 -1931
- package/dist/mdx-security.d.ts +76 -0
- package/dist/mdx-security.js +217 -0
- package/dist/mdx.d.ts +73 -0
- package/dist/mdx.js +1099 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/security.d.ts +22 -47
- package/dist/middleware/security.js +111 -137
- package/dist/parsers/base-parser.d.ts +14 -0
- package/dist/parsers/base-parser.js +1 -0
- package/dist/parsers/index.d.ts +16 -0
- package/dist/parsers/index.js +51 -0
- package/dist/parsers/openapi-parser.d.ts +18 -0
- package/dist/parsers/openapi-parser.js +209 -0
- package/dist/parsers/postman-parser.d.ts +20 -0
- package/dist/parsers/postman-parser.js +260 -0
- package/dist/parsers/specra-parser.d.ts +10 -0
- package/dist/parsers/specra-parser.js +18 -0
- package/dist/redirects.d.ts +12 -0
- package/dist/redirects.js +30 -0
- package/dist/remark-code-meta.d.ts +6 -0
- package/dist/remark-code-meta.js +21 -0
- package/dist/sidebar-utils.d.ts +59 -0
- package/dist/sidebar-utils.js +144 -0
- package/dist/stores/config.d.ts +20 -0
- package/dist/stores/config.js +45 -0
- package/dist/stores/index.d.ts +4 -0
- package/dist/stores/index.js +4 -0
- package/dist/stores/sidebar.d.ts +7 -0
- package/dist/stores/sidebar.js +12 -0
- package/dist/stores/tabs.d.ts +6 -0
- package/dist/stores/tabs.js +41 -0
- package/dist/stores/theme.d.ts +7 -0
- package/dist/stores/theme.js +75 -0
- package/dist/{styles.css → styles/globals.css} +136 -6
- package/dist/toc.d.ts +9 -0
- package/dist/toc.js +15 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.js +30 -0
- package/package.json +47 -90
- package/dist/app/api/mdx-watch/route.d.mts +0 -10
- package/dist/app/api/mdx-watch/route.d.ts +0 -10
- package/dist/app/api/mdx-watch/route.js +0 -118
- package/dist/app/api/mdx-watch/route.js.map +0 -1
- package/dist/app/api/mdx-watch/route.mjs +0 -91
- package/dist/app/api/mdx-watch/route.mjs.map +0 -1
- package/dist/chunk-6S3EJVEO.mjs +0 -259
- package/dist/chunk-6S3EJVEO.mjs.map +0 -1
- package/dist/chunk-BE7EROIW.mjs +0 -212
- package/dist/chunk-BE7EROIW.mjs.map +0 -1
- package/dist/chunk-CWHRZHZO.mjs +0 -168
- package/dist/chunk-CWHRZHZO.mjs.map +0 -1
- package/dist/chunk-D5VDVYFY.mjs +0 -1325
- package/dist/chunk-D5VDVYFY.mjs.map +0 -1
- package/dist/chunk-WMCO2UX5.mjs +0 -585
- package/dist/chunk-WMCO2UX5.mjs.map +0 -1
- package/dist/chunk-XEMGCPZZ.mjs +0 -475
- package/dist/chunk-XEMGCPZZ.mjs.map +0 -1
- package/dist/components/index.d.mts +0 -822
- package/dist/components/index.js.map +0 -1
- package/dist/components/index.mjs +0 -3741
- package/dist/components/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -4
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1897
- package/dist/index.mjs.map +0 -1
- package/dist/layouts/index.d.mts +0 -34
- package/dist/layouts/index.d.ts +0 -34
- package/dist/layouts/index.js +0 -453
- package/dist/layouts/index.js.map +0 -1
- package/dist/layouts/index.mjs +0 -173
- package/dist/layouts/index.mjs.map +0 -1
- package/dist/lib/index.d.mts +0 -583
- package/dist/lib/index.d.ts +0 -583
- package/dist/lib/index.js +0 -1595
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/index.mjs +0 -111
- package/dist/lib/index.mjs.map +0 -1
- package/dist/mdx-ColN3Cyg.d.ts +0 -352
- package/dist/mdx-components.d.mts +0 -86
- package/dist/mdx-components.d.ts +0 -86
- package/dist/mdx-components.js.map +0 -1
- package/dist/mdx-components.mjs +0 -206
- package/dist/mdx-components.mjs.map +0 -1
- package/dist/middleware/security.d.mts +0 -82
- package/dist/middleware/security.js.map +0 -1
- package/dist/middleware/security.mjs +0 -84
- package/dist/middleware/security.mjs.map +0 -1
- package/dist/styles.css.map +0 -1
- package/dist/styles.d.mts +0 -2
- package/dist/styles.d.ts +0 -2
- package/dist/styles.js +0 -2
- package/dist/styles.js.map +0 -1
- package/dist/styles.mjs +0 -1
- package/dist/styles.mjs.map +0 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified sidebar sorting and structure building utilities
|
|
3
|
+
* This module provides consistent sidebar logic across the application
|
|
4
|
+
* to ensure ordering is handled the same way everywhere.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Sort sidebar items by their position.
|
|
8
|
+
* Items with explicit sidebar_position come first (sorted numerically),
|
|
9
|
+
* followed by items without position (sorted by their original order).
|
|
10
|
+
*
|
|
11
|
+
* @param items - Array of items with optional sidebar_position
|
|
12
|
+
* @returns Sorted array of items
|
|
13
|
+
*/
|
|
14
|
+
export function sortSidebarItems(items) {
|
|
15
|
+
return [...items].sort((a, b) => {
|
|
16
|
+
const posA = a.sidebar_position ?? a.meta?.sidebar_position ?? a.meta?.order ?? 999;
|
|
17
|
+
const posB = b.sidebar_position ?? b.meta?.sidebar_position ?? b.meta?.order ?? 999;
|
|
18
|
+
return posA - posB;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Sort sidebar groups by their position.
|
|
23
|
+
* Groups with explicit position come first (sorted numerically),
|
|
24
|
+
* followed by groups without position at the end (sorted by their original order).
|
|
25
|
+
*
|
|
26
|
+
* @param groups - Record of group key to group object with position
|
|
27
|
+
* @returns Sorted array of [key, group] tuples
|
|
28
|
+
*/
|
|
29
|
+
export function sortSidebarGroups(groups) {
|
|
30
|
+
return Object.entries(groups).sort(([, a], [, b]) => {
|
|
31
|
+
const posA = a.position ?? 999;
|
|
32
|
+
const posB = b.position ?? 999;
|
|
33
|
+
return posA - posB;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build hierarchical sidebar structure from flat list of documents
|
|
38
|
+
* This is the single source of truth for sidebar structure used by both
|
|
39
|
+
* the sidebar component and navigation (prev/next) links.
|
|
40
|
+
*
|
|
41
|
+
* @param docs - Array of documents with metadata
|
|
42
|
+
* @returns Object containing root groups and standalone items
|
|
43
|
+
*/
|
|
44
|
+
export function buildSidebarStructure(docs) {
|
|
45
|
+
const rootGroups = {};
|
|
46
|
+
const standalone = [];
|
|
47
|
+
// First pass: collect category metadata from all docs to build complete folder structure
|
|
48
|
+
const categoryMetadata = new Map();
|
|
49
|
+
docs.forEach((doc) => {
|
|
50
|
+
const pathParts = doc.filePath.split("/");
|
|
51
|
+
const folderPath = pathParts.length > 1 ? pathParts.slice(0, -1).join("/") : "";
|
|
52
|
+
if (folderPath && doc.categoryLabel) {
|
|
53
|
+
categoryMetadata.set(folderPath, {
|
|
54
|
+
label: doc.categoryLabel,
|
|
55
|
+
position: doc.categoryPosition,
|
|
56
|
+
icon: doc.categoryIcon,
|
|
57
|
+
collapsible: doc.categoryCollapsible,
|
|
58
|
+
collapsed: doc.categoryCollapsed
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
docs.forEach((doc) => {
|
|
63
|
+
const pathParts = doc.filePath.split("/");
|
|
64
|
+
const isIndexFile = doc.filePath.endsWith("/index") ||
|
|
65
|
+
doc.filePath === "index" ||
|
|
66
|
+
(pathParts.length > 1 && doc.slug === pathParts.slice(0, -1).join("/"));
|
|
67
|
+
const customGroup = doc.meta.sidebar || doc.meta.group;
|
|
68
|
+
if (customGroup) {
|
|
69
|
+
const groupName = customGroup.charAt(0).toUpperCase() + customGroup.slice(1);
|
|
70
|
+
if (!rootGroups[groupName]) {
|
|
71
|
+
rootGroups[groupName] = {
|
|
72
|
+
label: groupName,
|
|
73
|
+
path: customGroup,
|
|
74
|
+
items: [],
|
|
75
|
+
position: 999,
|
|
76
|
+
collapsible: doc.categoryCollapsible ?? true,
|
|
77
|
+
defaultCollapsed: doc.categoryCollapsed ?? false,
|
|
78
|
+
children: {}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (isIndexFile) {
|
|
82
|
+
// Use categoryPosition if available (from _category_.json), otherwise sidebar_position from frontmatter
|
|
83
|
+
rootGroups[groupName].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? 999;
|
|
84
|
+
rootGroups[groupName].icon = doc.categoryIcon;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
rootGroups[groupName].items.push(doc);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (pathParts.length > 1) {
|
|
92
|
+
const folderParts = pathParts.slice(0, -1);
|
|
93
|
+
let currentLevel = rootGroups;
|
|
94
|
+
let currentPath = "";
|
|
95
|
+
for (let i = 0; i < folderParts.length; i++) {
|
|
96
|
+
const folder = folderParts[i];
|
|
97
|
+
currentPath = currentPath ? `${currentPath}/${folder}` : folder;
|
|
98
|
+
const folderLabel = folder.split("-").map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
99
|
+
// Get metadata for this specific folder path
|
|
100
|
+
const metadata = categoryMetadata.get(currentPath);
|
|
101
|
+
if (!currentLevel[folder]) {
|
|
102
|
+
currentLevel[folder] = {
|
|
103
|
+
label: metadata?.label ?? folderLabel,
|
|
104
|
+
path: currentPath,
|
|
105
|
+
icon: metadata?.icon,
|
|
106
|
+
items: [],
|
|
107
|
+
position: metadata?.position ?? 999,
|
|
108
|
+
collapsible: metadata?.collapsible ?? true,
|
|
109
|
+
defaultCollapsed: metadata?.collapsed ?? false,
|
|
110
|
+
children: {}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (i === folderParts.length - 1) {
|
|
114
|
+
if (isIndexFile) {
|
|
115
|
+
// Update position, label, and icon if this is the index file for this folder
|
|
116
|
+
currentLevel[folder].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? currentLevel[folder].position;
|
|
117
|
+
if (doc.categoryLabel) {
|
|
118
|
+
currentLevel[folder].label = doc.categoryLabel;
|
|
119
|
+
}
|
|
120
|
+
if (doc.categoryIcon) {
|
|
121
|
+
currentLevel[folder].icon = doc.categoryIcon;
|
|
122
|
+
}
|
|
123
|
+
if (doc.categoryCollapsible !== undefined) {
|
|
124
|
+
currentLevel[folder].collapsible = doc.categoryCollapsible;
|
|
125
|
+
}
|
|
126
|
+
if (doc.categoryCollapsed !== undefined) {
|
|
127
|
+
currentLevel[folder].defaultCollapsed = doc.categoryCollapsed;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
currentLevel[folder].items.push(doc);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
currentLevel = currentLevel[folder].children;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (!isIndexFile) {
|
|
139
|
+
standalone.push(doc);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return { rootGroups, standalone };
|
|
144
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type SpecraConfig } from '../config.types';
|
|
2
|
+
/**
|
|
3
|
+
* Create and set the config store in a component's context.
|
|
4
|
+
* Call this in your root layout component.
|
|
5
|
+
*/
|
|
6
|
+
export declare function setConfigContext(config: SpecraConfig): import("svelte/store").Writable<SpecraConfig>;
|
|
7
|
+
/**
|
|
8
|
+
* Get the config store from context.
|
|
9
|
+
* Must be called within a component that has a parent with setConfigContext.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getConfigContext(): import("svelte/store").Writable<SpecraConfig>;
|
|
12
|
+
/**
|
|
13
|
+
* Standalone writable config store for cases where context is not available.
|
|
14
|
+
* Prefer using context-based stores (setConfigContext/getConfigContext) in components.
|
|
15
|
+
*/
|
|
16
|
+
export declare const configStore: import("svelte/store").Writable<SpecraConfig>;
|
|
17
|
+
/**
|
|
18
|
+
* Get a specific configuration value by dot-separated path
|
|
19
|
+
*/
|
|
20
|
+
export declare function getConfigValue<T = unknown>(config: SpecraConfig, path: string): T | undefined;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { writable, get } from 'svelte/store';
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
import { defaultConfig } from '../config.types';
|
|
4
|
+
const CONFIG_KEY = Symbol('specra-config');
|
|
5
|
+
/**
|
|
6
|
+
* Create and set the config store in a component's context.
|
|
7
|
+
* Call this in your root layout component.
|
|
8
|
+
*/
|
|
9
|
+
export function setConfigContext(config) {
|
|
10
|
+
const store = writable(config);
|
|
11
|
+
setContext(CONFIG_KEY, store);
|
|
12
|
+
return store;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get the config store from context.
|
|
16
|
+
* Must be called within a component that has a parent with setConfigContext.
|
|
17
|
+
*/
|
|
18
|
+
export function getConfigContext() {
|
|
19
|
+
const store = getContext(CONFIG_KEY);
|
|
20
|
+
if (!store) {
|
|
21
|
+
throw new Error('getConfigContext must be used within a component with setConfigContext');
|
|
22
|
+
}
|
|
23
|
+
return store;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Standalone writable config store for cases where context is not available.
|
|
27
|
+
* Prefer using context-based stores (setConfigContext/getConfigContext) in components.
|
|
28
|
+
*/
|
|
29
|
+
export const configStore = writable(defaultConfig);
|
|
30
|
+
/**
|
|
31
|
+
* Get a specific configuration value by dot-separated path
|
|
32
|
+
*/
|
|
33
|
+
export function getConfigValue(config, path) {
|
|
34
|
+
const keys = path.split('.');
|
|
35
|
+
let value = config;
|
|
36
|
+
for (const key of keys) {
|
|
37
|
+
if (value && typeof value === 'object' && key in value) {
|
|
38
|
+
value = value[key];
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const sidebarStore: {
|
|
2
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<boolean>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
3
|
+
open: () => void;
|
|
4
|
+
close: () => void;
|
|
5
|
+
toggle: () => void;
|
|
6
|
+
set: (this: void, value: boolean) => void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
function createSidebarStore() {
|
|
3
|
+
const { subscribe, set, update } = writable(false);
|
|
4
|
+
return {
|
|
5
|
+
subscribe,
|
|
6
|
+
open: () => set(true),
|
|
7
|
+
close: () => set(false),
|
|
8
|
+
toggle: () => update((v) => !v),
|
|
9
|
+
set
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export const sidebarStore = createSidebarStore();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const tabStore: {
|
|
2
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<string>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
3
|
+
set: (tabId: string) => void;
|
|
4
|
+
initialize: (defaultTab: string) => void;
|
|
5
|
+
get: () => string;
|
|
6
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { writable, get } from 'svelte/store';
|
|
2
|
+
import { browser } from '$app/environment';
|
|
3
|
+
const TAB_STORAGE_KEY = 'specra-active-tab-group';
|
|
4
|
+
function getInitialTab(defaultTab) {
|
|
5
|
+
if (!browser)
|
|
6
|
+
return defaultTab;
|
|
7
|
+
try {
|
|
8
|
+
const stored = localStorage.getItem(TAB_STORAGE_KEY);
|
|
9
|
+
if (stored)
|
|
10
|
+
return stored;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// Ignore localStorage errors
|
|
14
|
+
}
|
|
15
|
+
return defaultTab;
|
|
16
|
+
}
|
|
17
|
+
function createTabStore() {
|
|
18
|
+
const { subscribe, set, update } = writable('');
|
|
19
|
+
function initialize(defaultTab) {
|
|
20
|
+
const initial = getInitialTab(defaultTab);
|
|
21
|
+
set(initial);
|
|
22
|
+
}
|
|
23
|
+
function setActiveTab(tabId) {
|
|
24
|
+
set(tabId);
|
|
25
|
+
if (browser) {
|
|
26
|
+
try {
|
|
27
|
+
localStorage.setItem(TAB_STORAGE_KEY, tabId);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Ignore localStorage errors
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
subscribe,
|
|
36
|
+
set: setActiveTab,
|
|
37
|
+
initialize,
|
|
38
|
+
get: () => get({ subscribe })
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export const tabStore = createTabStore();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type Theme = 'light' | 'dark' | 'system';
|
|
2
|
+
export declare const themeStore: {
|
|
3
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<Theme>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
4
|
+
set: (theme: Theme) => void;
|
|
5
|
+
toggle: () => void;
|
|
6
|
+
getResolved: () => "light" | "dark";
|
|
7
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { browser } from '$app/environment';
|
|
3
|
+
const THEME_STORAGE_KEY = 'specra-theme';
|
|
4
|
+
function getInitialTheme() {
|
|
5
|
+
if (!browser)
|
|
6
|
+
return 'system';
|
|
7
|
+
try {
|
|
8
|
+
const stored = localStorage.getItem(THEME_STORAGE_KEY);
|
|
9
|
+
if (stored === 'light' || stored === 'dark' || stored === 'system') {
|
|
10
|
+
return stored;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// Ignore localStorage errors
|
|
15
|
+
}
|
|
16
|
+
return 'system';
|
|
17
|
+
}
|
|
18
|
+
function getResolvedTheme(theme) {
|
|
19
|
+
if (theme !== 'system')
|
|
20
|
+
return theme;
|
|
21
|
+
if (!browser)
|
|
22
|
+
return 'light';
|
|
23
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
24
|
+
}
|
|
25
|
+
function createThemeStore() {
|
|
26
|
+
const initial = getInitialTheme();
|
|
27
|
+
const { subscribe, set, update } = writable(initial);
|
|
28
|
+
function setTheme(theme) {
|
|
29
|
+
set(theme);
|
|
30
|
+
if (browser) {
|
|
31
|
+
try {
|
|
32
|
+
localStorage.setItem(THEME_STORAGE_KEY, theme);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Ignore localStorage errors
|
|
36
|
+
}
|
|
37
|
+
applyTheme(theme);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function applyTheme(theme) {
|
|
41
|
+
if (!browser)
|
|
42
|
+
return;
|
|
43
|
+
const resolved = getResolvedTheme(theme);
|
|
44
|
+
const root = document.documentElement;
|
|
45
|
+
root.classList.remove('light', 'dark');
|
|
46
|
+
root.classList.add(resolved);
|
|
47
|
+
}
|
|
48
|
+
function toggle() {
|
|
49
|
+
update((current) => {
|
|
50
|
+
const resolved = getResolvedTheme(current);
|
|
51
|
+
const next = resolved === 'dark' ? 'light' : 'dark';
|
|
52
|
+
setTheme(next);
|
|
53
|
+
return next;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Apply initial theme on creation
|
|
57
|
+
if (browser) {
|
|
58
|
+
applyTheme(initial);
|
|
59
|
+
// Listen for system preference changes
|
|
60
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
61
|
+
mediaQuery.addEventListener('change', () => {
|
|
62
|
+
const currentTheme = getInitialTheme();
|
|
63
|
+
if (currentTheme === 'system') {
|
|
64
|
+
applyTheme('system');
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
subscribe,
|
|
70
|
+
set: setTheme,
|
|
71
|
+
toggle,
|
|
72
|
+
getResolved: () => getResolvedTheme(getInitialTheme())
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export const themeStore = createThemeStore();
|