sdocs 0.0.14 → 0.0.16
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/bin/sdocs.js +1 -1
- package/dist/client/App.svelte +16 -39
- package/dist/client/App.svelte.d.ts +1 -1
- package/dist/client/favicon.png +0 -0
- package/dist/client/tree-builder.js +57 -14
- package/dist/client/{CollapsiblePanel.svelte → views/CollapsiblePanel.svelte} +5 -5
- package/dist/client/{ComponentView.svelte → views/ComponentView.svelte} +39 -13
- package/dist/client/{ComponentView.svelte.d.ts → views/ComponentView.svelte.d.ts} +1 -1
- package/dist/client/{ControlsPanel.svelte → views/ControlsPanel.svelte} +10 -15
- package/dist/client/{ControlsPanel.svelte.d.ts → views/ControlsPanel.svelte.d.ts} +1 -1
- package/dist/client/{DataTable.svelte → views/DataTable.svelte} +8 -8
- package/dist/client/{HomePage.svelte → views/HomePage.svelte} +10 -8
- package/dist/client/{HomePage.svelte.d.ts → views/HomePage.svelte.d.ts} +1 -1
- package/dist/client/{LayoutView.svelte → views/LayoutView.svelte} +1 -1
- package/dist/client/{LayoutView.svelte.d.ts → views/LayoutView.svelte.d.ts} +1 -1
- package/dist/client/{PageView.svelte → views/PageView.svelte} +7 -7
- package/dist/client/{PageView.svelte.d.ts → views/PageView.svelte.d.ts} +1 -1
- package/dist/client/{PreviewFrame.svelte → views/PreviewFrame.svelte} +10 -3
- package/dist/client/views/Sidebar.svelte +369 -0
- package/dist/client/{Sidebar.svelte.d.ts → views/Sidebar.svelte.d.ts} +2 -2
- package/dist/commands/build.js +2 -2
- package/dist/commands/dev.js +2 -2
- package/dist/commands/init.js +4 -4
- package/dist/commands/preview.js +1 -1
- package/dist/{app-gen.d.ts → server/app-gen.d.ts} +1 -1
- package/dist/{app-gen.js → server/app-gen.js} +4 -4
- package/dist/{cli.js → server/cli.js} +4 -4
- package/dist/{config.d.ts → server/config.d.ts} +1 -1
- package/dist/{config.js → server/config.js} +7 -2
- package/dist/server/discovery.d.ts +1 -1
- package/dist/server/discovery.js +1 -1
- package/dist/server/meta-parser.js +1 -1
- package/dist/server/prop-parser.js +12 -4
- package/dist/server/snippet-compiler.js +8 -0
- package/dist/server/snippet-extractor.d.ts +1 -1
- package/dist/server/snippet-extractor.js +40 -5
- package/dist/server/toc-extractor.d.ts +0 -2
- package/dist/server/toc-extractor.js +0 -14
- package/dist/types.d.ts +3 -3
- package/dist/ui/About.page.sdoc +37 -0
- package/dist/ui/Button/Button.sdoc +51 -0
- package/dist/ui/Button/Button.svelte +90 -0
- package/dist/ui/Button/Button.svelte.d.ts +27 -0
- package/dist/ui/Button/index.d.ts +1 -0
- package/dist/ui/Button/index.js +1 -0
- package/dist/ui/Control/Checkbox.sdoc +17 -0
- package/dist/{client/controls/CheckboxControl.svelte → ui/Control/Checkbox.svelte} +1 -1
- package/dist/ui/Control/Checkbox.svelte.d.ts +8 -0
- package/dist/ui/Control/Color.sdoc +17 -0
- package/dist/{client/controls/ColorControl.svelte → ui/Control/Color.svelte} +4 -4
- package/dist/ui/Control/Color.svelte.d.ts +8 -0
- package/dist/ui/Control/Dimension.sdoc +17 -0
- package/dist/{client/controls/DimensionControl.svelte → ui/Control/Dimension.svelte} +5 -5
- package/dist/ui/Control/Dimension.svelte.d.ts +8 -0
- package/dist/ui/Control/Number.sdoc +17 -0
- package/dist/{client/controls/NumberControl.svelte → ui/Control/Number.svelte} +4 -4
- package/dist/ui/Control/Number.svelte.d.ts +8 -0
- package/dist/ui/Control/Select.sdoc +18 -0
- package/dist/{client/controls/SelectControl.svelte → ui/Control/Select.svelte} +4 -4
- package/dist/ui/Control/Select.svelte.d.ts +9 -0
- package/dist/ui/Control/Text.sdoc +17 -0
- package/dist/{client/controls/TextControl.svelte → ui/Control/Text.svelte} +4 -4
- package/dist/ui/Control/Text.svelte.d.ts +8 -0
- package/dist/ui/Control/index.d.ts +6 -0
- package/dist/ui/Control/index.js +6 -0
- package/dist/ui/Dashboard.layout.sdoc +60 -0
- package/dist/ui/Frame/Frame.sdoc +54 -0
- package/dist/ui/Frame/Frame.svelte +88 -0
- package/dist/ui/Frame/Frame.svelte.d.ts +15 -0
- package/dist/ui/Frame/index.d.ts +1 -0
- package/dist/ui/Frame/index.js +1 -0
- package/dist/ui/Icon/Icon.sdoc +45 -0
- package/dist/ui/Icon/Icon.svelte +47 -0
- package/dist/ui/Icon/Icon.svelte.d.ts +16 -0
- package/dist/ui/Icon/icons/bookmark.svg +1 -0
- package/dist/ui/Icon/icons/chevron-down.svg +1 -0
- package/dist/ui/Icon/icons/chevron-left.svg +1 -0
- package/dist/ui/Icon/icons/chevron-right.svg +1 -0
- package/dist/ui/Icon/icons/chevron-up.svg +1 -0
- package/dist/ui/Icon/icons/code.svg +1 -0
- package/dist/ui/Icon/icons/component.svg +1 -0
- package/dist/ui/Icon/icons/copy.svg +1 -0
- package/dist/ui/Icon/icons/diamond.svg +1 -0
- package/dist/ui/Icon/icons/file-code.svg +1 -0
- package/dist/ui/Icon/icons/file-text.svg +1 -0
- package/dist/ui/Icon/icons/folder-open.svg +1 -0
- package/dist/ui/Icon/icons/folder.svg +1 -0
- package/dist/ui/Icon/icons/panels-top-left.svg +1 -0
- package/dist/ui/Icon/icons/sdocs.svg +8 -0
- package/dist/ui/Icon/index.d.ts +1 -0
- package/dist/ui/Icon/index.js +1 -0
- package/dist/ui/NavTree/Group.sdoc +46 -0
- package/dist/ui/NavTree/Group.svelte +82 -0
- package/dist/ui/NavTree/Group.svelte.d.ts +11 -0
- package/dist/ui/NavTree/Item.sdoc +70 -0
- package/dist/ui/NavTree/Item.svelte +164 -0
- package/dist/ui/NavTree/Item.svelte.d.ts +33 -0
- package/dist/ui/NavTree/NavTree.sdoc +119 -0
- package/dist/ui/NavTree/NavTree.svelte +31 -0
- package/dist/ui/NavTree/NavTree.svelte.d.ts +8 -0
- package/dist/ui/NavTree/index.js +6 -0
- package/dist/ui/Stack/Stack.sdoc +44 -0
- package/dist/ui/Stack/Stack.svelte +41 -0
- package/dist/ui/Stack/Stack.svelte.d.ts +19 -0
- package/dist/ui/Stack/index.d.ts +1 -0
- package/dist/ui/Stack/index.js +1 -0
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +6 -0
- package/dist/ui/styles/fonts/jetbrains-mono-italic-latin-ext.woff2 +0 -0
- package/dist/ui/styles/fonts/jetbrains-mono-italic-latin.woff2 +0 -0
- package/dist/ui/styles/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
- package/dist/ui/styles/fonts/jetbrains-mono-latin.woff2 +0 -0
- package/dist/ui/styles/fonts.css +87 -0
- package/dist/ui/styles/theme.css +910 -0
- package/dist/vite.js +47 -51
- package/package.json +5 -2
- package/dist/client/Sidebar.svelte +0 -329
- package/dist/client/controls/CheckboxControl.svelte.d.ts +0 -8
- package/dist/client/controls/ColorControl.svelte.d.ts +0 -8
- package/dist/client/controls/DimensionControl.svelte.d.ts +0 -8
- package/dist/client/controls/NumberControl.svelte.d.ts +0 -8
- package/dist/client/controls/SelectControl.svelte.d.ts +0 -9
- package/dist/client/controls/TextControl.svelte.d.ts +0 -8
- package/dist/client/theme.css +0 -80
- package/dist/server/sdocx-parser.d.ts +0 -11
- package/dist/server/sdocx-parser.js +0 -197
- /package/dist/client/{CollapsiblePanel.svelte.d.ts → views/CollapsiblePanel.svelte.d.ts} +0 -0
- /package/dist/client/{DataTable.svelte.d.ts → views/DataTable.svelte.d.ts} +0 -0
- /package/dist/client/{PreviewFrame.svelte.d.ts → views/PreviewFrame.svelte.d.ts} +0 -0
- /package/dist/{cli.d.ts → server/cli.d.ts} +0 -0
- /package/dist/{client → ui/styles}/fonts/figtree-italic-latin-ext.woff2 +0 -0
- /package/dist/{client → ui/styles}/fonts/figtree-italic-latin.woff2 +0 -0
- /package/dist/{client → ui/styles}/fonts/figtree-latin-ext.woff2 +0 -0
- /package/dist/{client → ui/styles}/fonts/figtree-latin.woff2 +0 -0
package/dist/vite.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { loadConfig, resolveConfig } from './config.js';
|
|
2
|
+
import { loadConfig, resolveConfig } from './server/config.js';
|
|
3
3
|
import { discoverDocFiles, getSdocKind } from './server/discovery.js';
|
|
4
4
|
import { parseDocSource } from './server/meta-parser.js';
|
|
5
5
|
import { parseComponent } from './server/prop-parser.js';
|
|
6
6
|
import { extractSnippets, extractMarkupBody, hasDefaultSnippet, generateAutoDefault, } from './server/snippet-extractor.js';
|
|
7
7
|
import { highlight, disposeHighlighter } from './server/highlighter.js';
|
|
8
8
|
import { extractTocFromHtml } from './server/toc-extractor.js';
|
|
9
|
-
import { parseSdocx } from './server/sdocx-parser.js';
|
|
10
9
|
import { parseIframeId, parsePreviewUrl, resolveImportsToAbsolute, generateIframeComponent, generatePreviewHtml, iframeVirtualId, previewUrl, buildPreviewUrl, } from './server/snippet-compiler.js';
|
|
11
10
|
const VIRTUAL_MODULE_ID = 'virtual:sdocs';
|
|
12
11
|
const RESOLVED_VIRTUAL_ID = '\0virtual:sdocs';
|
|
@@ -68,7 +67,7 @@ export function sdocsPlugin(userConfig) {
|
|
|
68
67
|
if (isDocFile(filePath)) {
|
|
69
68
|
console.log(`[sdocs] New doc file: ${filePath}`);
|
|
70
69
|
await processDocFile(filePath);
|
|
71
|
-
invalidateVirtualModule();
|
|
70
|
+
invalidateVirtualModule(filePath);
|
|
72
71
|
}
|
|
73
72
|
});
|
|
74
73
|
server.watcher.on('unlink', (filePath) => {
|
|
@@ -83,12 +82,12 @@ export function sdocsPlugin(userConfig) {
|
|
|
83
82
|
if (isDocFile(filePath)) {
|
|
84
83
|
console.log(`[sdocs] Doc file changed: ${filePath}`);
|
|
85
84
|
await processDocFile(filePath);
|
|
86
|
-
invalidateVirtualModule();
|
|
85
|
+
invalidateVirtualModule(filePath);
|
|
87
86
|
}
|
|
88
87
|
else if (isComponentReferencedByDoc(filePath)) {
|
|
89
88
|
console.log(`[sdocs] Component changed: ${filePath}`);
|
|
90
89
|
await reprocessComponentEntries(filePath);
|
|
91
|
-
invalidateVirtualModule();
|
|
90
|
+
invalidateVirtualModule(filePath);
|
|
92
91
|
}
|
|
93
92
|
});
|
|
94
93
|
},
|
|
@@ -99,6 +98,17 @@ export function sdocsPlugin(userConfig) {
|
|
|
99
98
|
console.log(` - ${file}`);
|
|
100
99
|
await processDocFile(file);
|
|
101
100
|
}
|
|
101
|
+
// Explicitly watch doc files and their directories (outside Vite root)
|
|
102
|
+
if (server) {
|
|
103
|
+
const dirs = new Set();
|
|
104
|
+
for (const file of files) {
|
|
105
|
+
server.watcher.add(file);
|
|
106
|
+
dirs.add(file.substring(0, file.lastIndexOf('/')));
|
|
107
|
+
}
|
|
108
|
+
for (const dir of dirs) {
|
|
109
|
+
server.watcher.add(dir);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
102
112
|
},
|
|
103
113
|
resolveId(id) {
|
|
104
114
|
if (id === VIRTUAL_MODULE_ID)
|
|
@@ -134,54 +144,27 @@ export function sdocsPlugin(userConfig) {
|
|
|
134
144
|
async function processDocFile(filePath) {
|
|
135
145
|
const source = await readFile(filePath, 'utf-8');
|
|
136
146
|
const kind = getSdocKind(filePath);
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
147
|
+
const parsed = parseDocSource(source, filePath);
|
|
148
|
+
const meta = parsed.meta;
|
|
149
|
+
const componentPath = parsed.componentPath;
|
|
150
|
+
const imports = parsed.imports;
|
|
141
151
|
let snippets;
|
|
142
152
|
let toc;
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
imports = result.imports;
|
|
149
|
-
snippets = result.snippets;
|
|
150
|
-
toc = result.toc;
|
|
151
|
-
// For component kind, auto-generate Default if missing
|
|
152
|
-
if (kind === 'component') {
|
|
153
|
-
const hasDefault = snippets.some((s) => s.name === 'Default');
|
|
154
|
-
if (!hasDefault && componentPath) {
|
|
155
|
-
const componentName = componentPath.split('/').pop()?.replace('.svelte', '') ?? 'Component';
|
|
156
|
-
snippets.unshift({
|
|
157
|
-
name: 'Default',
|
|
158
|
-
body: generateAutoDefault(componentName),
|
|
159
|
-
});
|
|
160
|
-
}
|
|
153
|
+
if (kind === 'page' || kind === 'layout') {
|
|
154
|
+
const body = extractMarkupBody(source);
|
|
155
|
+
snippets = [{ name: 'Content', body }];
|
|
156
|
+
if (kind === 'page') {
|
|
157
|
+
toc = extractTocFromHtml(body);
|
|
161
158
|
}
|
|
162
159
|
}
|
|
163
160
|
else {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
snippets = [{ name: 'Content', body }];
|
|
172
|
-
if (kind === 'page') {
|
|
173
|
-
toc = extractTocFromHtml(body);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
snippets = extractSnippets(source);
|
|
178
|
-
if (!hasDefaultSnippet(snippets)) {
|
|
179
|
-
const componentName = componentPath?.split('/').pop()?.replace('.svelte', '') ?? 'Component';
|
|
180
|
-
snippets.unshift({
|
|
181
|
-
name: 'Default',
|
|
182
|
-
body: generateAutoDefault(componentName),
|
|
183
|
-
});
|
|
184
|
-
}
|
|
161
|
+
snippets = extractSnippets(source);
|
|
162
|
+
if (!hasDefaultSnippet(snippets)) {
|
|
163
|
+
const componentName = componentPath?.split('/').pop()?.replace('.svelte', '') ?? 'Component';
|
|
164
|
+
snippets.unshift({
|
|
165
|
+
name: 'Default',
|
|
166
|
+
body: generateAutoDefault(componentName),
|
|
167
|
+
});
|
|
185
168
|
}
|
|
186
169
|
}
|
|
187
170
|
// If component is specified as a path but not imported, auto-add the import
|
|
@@ -245,17 +228,30 @@ export function sdocsPlugin(userConfig) {
|
|
|
245
228
|
return `export const docs = ${JSON.stringify(data)};\nexport const cssNames = ${JSON.stringify(cssNames)};\nexport default docs;`;
|
|
246
229
|
}
|
|
247
230
|
// ─── HMR helpers ───
|
|
248
|
-
function invalidateVirtualModule() {
|
|
231
|
+
function invalidateVirtualModule(docFilePath) {
|
|
249
232
|
if (!server)
|
|
250
233
|
return;
|
|
251
234
|
const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
|
|
252
235
|
if (mod) {
|
|
253
236
|
server.moduleGraph.invalidateModule(mod);
|
|
254
|
-
server.ws.send({ type: 'full-reload' });
|
|
255
237
|
}
|
|
238
|
+
// Also invalidate iframe virtual modules for the changed doc file
|
|
239
|
+
if (docFilePath) {
|
|
240
|
+
const entry = docEntries.get(docFilePath);
|
|
241
|
+
if (entry) {
|
|
242
|
+
for (const snippet of entry.snippets) {
|
|
243
|
+
const iframeId = '\0' + iframeVirtualId(docFilePath, snippet.name);
|
|
244
|
+
const iframeMod = server.moduleGraph.getModuleById(iframeId);
|
|
245
|
+
if (iframeMod) {
|
|
246
|
+
server.moduleGraph.invalidateModule(iframeMod);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
server.ws.send({ type: 'full-reload' });
|
|
256
252
|
}
|
|
257
253
|
function isDocFile(filePath) {
|
|
258
|
-
return filePath.endsWith('.sdoc')
|
|
254
|
+
return filePath.endsWith('.sdoc');
|
|
259
255
|
}
|
|
260
256
|
function isComponentReferencedByDoc(filePath) {
|
|
261
257
|
for (const entry of docEntries.values()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdocs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "A lightweight documentation tool for Svelte 5 components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
},
|
|
19
19
|
"./client": {
|
|
20
20
|
"svelte": "./dist/client/App.svelte"
|
|
21
|
+
},
|
|
22
|
+
"./ui": {
|
|
23
|
+
"types": "./dist/ui/index.d.ts",
|
|
24
|
+
"svelte": "./dist/ui/index.js"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"files": [
|
|
@@ -45,7 +49,6 @@
|
|
|
45
49
|
"test": "vitest run"
|
|
46
50
|
},
|
|
47
51
|
"dependencies": {
|
|
48
|
-
"mdsvex": "^0.12.6",
|
|
49
52
|
"shiki": "^3.22.0",
|
|
50
53
|
"tinyglobby": "^0.2.15",
|
|
51
54
|
"typescript": "^5.7.0"
|
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { SvelteSet } from 'svelte/reactivity';
|
|
3
|
-
import type { TreeNode } from './tree-builder.js';
|
|
4
|
-
import { pathToHash } from './router.svelte.js';
|
|
5
|
-
|
|
6
|
-
type ThemeMode = 'light' | 'dark' | 'system';
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
tree: TreeNode[];
|
|
10
|
-
currentPath: string[];
|
|
11
|
-
logo: string;
|
|
12
|
-
cssNames?: string[];
|
|
13
|
-
activeStylesheet?: string;
|
|
14
|
-
theme?: ThemeMode;
|
|
15
|
-
onToggleFullscreen?: () => void;
|
|
16
|
-
onStylesheetChange?: (name: string) => void;
|
|
17
|
-
onThemeChange?: (theme: ThemeMode) => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
let { tree, currentPath, logo, cssNames = [], activeStylesheet, theme = 'system', onToggleFullscreen, onStylesheetChange, onThemeChange }: Props = $props();
|
|
21
|
-
|
|
22
|
-
const themeIcons: Record<ThemeMode, string> = { light: '\u2600', dark: '\u263D', system: '\u25D1' };
|
|
23
|
-
const themeLabels: Record<ThemeMode, string> = { light: 'Light', dark: 'Dark', system: 'System' };
|
|
24
|
-
const themeCycle: Record<ThemeMode, ThemeMode> = { light: 'dark', dark: 'system', system: 'light' };
|
|
25
|
-
|
|
26
|
-
function cycleTheme() {
|
|
27
|
-
onThemeChange?.(themeCycle[theme]);
|
|
28
|
-
}
|
|
29
|
-
let searchQuery = $state('');
|
|
30
|
-
|
|
31
|
-
// Track expanded state by path key (SvelteSet for reactivity)
|
|
32
|
-
let expandedSet = new SvelteSet<string>();
|
|
33
|
-
let initialized = false;
|
|
34
|
-
|
|
35
|
-
// Initialize expanded state from tree defaults
|
|
36
|
-
$effect(() => {
|
|
37
|
-
if (!initialized && tree.length > 0) {
|
|
38
|
-
collectDefaults(tree, expandedSet);
|
|
39
|
-
initialized = true;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
function collectDefaults(nodes: TreeNode[], set: SvelteSet<string>) {
|
|
44
|
-
for (const node of nodes) {
|
|
45
|
-
if (node.defaultExpanded || node.type === 'group') {
|
|
46
|
-
set.add(node.path.join('/'));
|
|
47
|
-
}
|
|
48
|
-
if (node.children.length > 0) {
|
|
49
|
-
collectDefaults(node.children, set);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function toggleExpanded(pathKey: string) {
|
|
55
|
-
if (expandedSet.has(pathKey)) {
|
|
56
|
-
expandedSet.delete(pathKey);
|
|
57
|
-
} else {
|
|
58
|
-
expandedSet.add(pathKey);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function isExpanded(pathKey: string): boolean {
|
|
63
|
-
if (searchQuery.trim()) return true; // Auto-expand when searching
|
|
64
|
-
return expandedSet.has(pathKey);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const filteredTree = $derived(
|
|
68
|
-
searchQuery.trim() ? filterTree(tree, searchQuery.trim().toLowerCase()) : tree,
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
function filterTree(nodes: TreeNode[], query: string): TreeNode[] {
|
|
72
|
-
const result: TreeNode[] = [];
|
|
73
|
-
for (const node of nodes) {
|
|
74
|
-
if (node.name.toLowerCase().includes(query)) {
|
|
75
|
-
result.push(node);
|
|
76
|
-
} else if (node.children.length > 0) {
|
|
77
|
-
const filtered = filterTree(node.children, query);
|
|
78
|
-
if (filtered.length > 0) {
|
|
79
|
-
result.push({ ...node, children: filtered });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function isActive(nodePath: string[]): boolean {
|
|
87
|
-
if (nodePath.length > currentPath.length) return false;
|
|
88
|
-
return nodePath.every((seg, i) => seg === currentPath[i]);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function isExactActive(nodePath: string[]): boolean {
|
|
92
|
-
return nodePath.length === currentPath.length && nodePath.every((seg, i) => seg === currentPath[i]);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function nodeIcon(node: TreeNode): string {
|
|
96
|
-
switch (node.type) {
|
|
97
|
-
case 'component': return '◆';
|
|
98
|
-
case 'page': return '◇';
|
|
99
|
-
case 'layout': return '▣';
|
|
100
|
-
case 'folder': return '▸';
|
|
101
|
-
default: return '';
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
</script>
|
|
105
|
-
|
|
106
|
-
<aside class="sdocs-sidebar">
|
|
107
|
-
<div class="sdocs-sidebar-header">
|
|
108
|
-
<span class="sdocs-logo">{logo}</span>
|
|
109
|
-
<div class="sdocs-header-actions">
|
|
110
|
-
{#if cssNames.length > 1}
|
|
111
|
-
<select
|
|
112
|
-
class="sdocs-css-picker"
|
|
113
|
-
value={activeStylesheet}
|
|
114
|
-
onchange={(e) => onStylesheetChange?.(e.currentTarget.value)}
|
|
115
|
-
>
|
|
116
|
-
{#each cssNames as name (name)}
|
|
117
|
-
<option value={name}>{name}</option>
|
|
118
|
-
{/each}
|
|
119
|
-
</select>
|
|
120
|
-
{/if}
|
|
121
|
-
<button class="sdocs-theme-btn" onclick={cycleTheme} title="{themeLabels[theme]} theme">
|
|
122
|
-
{themeIcons[theme]}
|
|
123
|
-
</button>
|
|
124
|
-
<button class="sdocs-fullscreen-btn" onclick={() => onToggleFullscreen?.()} title="Fullscreen">
|
|
125
|
-
⛶
|
|
126
|
-
</button>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
<div class="sdocs-sidebar-search">
|
|
131
|
-
<input
|
|
132
|
-
type="text"
|
|
133
|
-
placeholder="Search..."
|
|
134
|
-
bind:value={searchQuery}
|
|
135
|
-
class="sdocs-search-input"
|
|
136
|
-
/>
|
|
137
|
-
</div>
|
|
138
|
-
|
|
139
|
-
<nav class="sdocs-sidebar-tree">
|
|
140
|
-
{#each filteredTree as node (node.path.join('/'))}
|
|
141
|
-
{@render treeItem(node, 0)}
|
|
142
|
-
{/each}
|
|
143
|
-
</nav>
|
|
144
|
-
</aside>
|
|
145
|
-
|
|
146
|
-
{#snippet treeItem(node: TreeNode, depth: number)}
|
|
147
|
-
{@const pathKey = node.path.join('/')}
|
|
148
|
-
{@const isExpandable = node.type === 'folder' || node.type === 'group' || (node.type === 'component' && node.children.length > 0)}
|
|
149
|
-
{@const isGroup = node.type === 'group'}
|
|
150
|
-
{@const isSelectable = node.type === 'page' || node.type === 'layout' || (node.type === 'component' && node.children.length === 0)}
|
|
151
|
-
{@const activeExact = isExactActive(node.path)}
|
|
152
|
-
{@const activeContains = isActive(node.path)}
|
|
153
|
-
|
|
154
|
-
<div class="sdocs-tree-item" style:--depth={depth}>
|
|
155
|
-
{#if isGroup}
|
|
156
|
-
<div class="sdocs-group-label">{node.name.toUpperCase()}</div>
|
|
157
|
-
{:else if isExpandable}
|
|
158
|
-
<button
|
|
159
|
-
class="sdocs-tree-btn"
|
|
160
|
-
class:sdocs-active={activeContains}
|
|
161
|
-
onclick={() => toggleExpanded(pathKey)}
|
|
162
|
-
>
|
|
163
|
-
<span class="sdocs-tree-arrow" class:expanded={isExpanded(pathKey)}>▶</span>
|
|
164
|
-
<span class="sdocs-tree-icon">{nodeIcon(node)}</span>
|
|
165
|
-
<span>{node.name}</span>
|
|
166
|
-
</button>
|
|
167
|
-
{:else if isSelectable}
|
|
168
|
-
<a
|
|
169
|
-
href={pathToHash(node.path)}
|
|
170
|
-
class="sdocs-tree-link"
|
|
171
|
-
class:sdocs-active={activeExact}
|
|
172
|
-
>
|
|
173
|
-
<span class="sdocs-tree-icon">{nodeIcon(node)}</span>
|
|
174
|
-
<span>{node.name}</span>
|
|
175
|
-
</a>
|
|
176
|
-
{:else}
|
|
177
|
-
<a
|
|
178
|
-
href={pathToHash(node.path)}
|
|
179
|
-
class="sdocs-tree-link"
|
|
180
|
-
class:sdocs-active={activeExact}
|
|
181
|
-
>
|
|
182
|
-
<span>{node.name}</span>
|
|
183
|
-
</a>
|
|
184
|
-
{/if}
|
|
185
|
-
|
|
186
|
-
{#if (isExpandable || isGroup) && isExpanded(pathKey)}
|
|
187
|
-
<div class="sdocs-tree-children">
|
|
188
|
-
{#each node.children as child (child.path.join('/'))}
|
|
189
|
-
{@render treeItem(child, depth + 1)}
|
|
190
|
-
{/each}
|
|
191
|
-
</div>
|
|
192
|
-
{/if}
|
|
193
|
-
</div>
|
|
194
|
-
{/snippet}
|
|
195
|
-
|
|
196
|
-
<style>
|
|
197
|
-
.sdocs-sidebar {
|
|
198
|
-
width: 260px;
|
|
199
|
-
height: 100vh;
|
|
200
|
-
overflow-y: auto;
|
|
201
|
-
border-right: 1px solid var(--sdocs-border);
|
|
202
|
-
background: var(--sdocs-bg-subtle);
|
|
203
|
-
display: flex;
|
|
204
|
-
flex-direction: column;
|
|
205
|
-
font-family: var(--sdocs-font-sans);
|
|
206
|
-
font-size: 13px;
|
|
207
|
-
}
|
|
208
|
-
.sdocs-sidebar-header {
|
|
209
|
-
padding: 12px 16px;
|
|
210
|
-
border-bottom: 1px solid var(--sdocs-border);
|
|
211
|
-
display: flex;
|
|
212
|
-
align-items: center;
|
|
213
|
-
justify-content: space-between;
|
|
214
|
-
}
|
|
215
|
-
.sdocs-logo {
|
|
216
|
-
font-weight: 700;
|
|
217
|
-
font-size: 16px;
|
|
218
|
-
color: var(--sdocs-text-heading);
|
|
219
|
-
}
|
|
220
|
-
.sdocs-header-actions {
|
|
221
|
-
display: flex;
|
|
222
|
-
align-items: center;
|
|
223
|
-
gap: 6px;
|
|
224
|
-
}
|
|
225
|
-
.sdocs-css-picker {
|
|
226
|
-
font-size: 12px;
|
|
227
|
-
padding: 2px 4px;
|
|
228
|
-
border: 1px solid var(--sdocs-border);
|
|
229
|
-
border-radius: 4px;
|
|
230
|
-
background: var(--sdocs-bg);
|
|
231
|
-
color: var(--sdocs-text);
|
|
232
|
-
}
|
|
233
|
-
.sdocs-theme-btn {
|
|
234
|
-
padding: 2px 6px;
|
|
235
|
-
border: 1px solid var(--sdocs-border);
|
|
236
|
-
border-radius: 4px;
|
|
237
|
-
background: var(--sdocs-bg);
|
|
238
|
-
color: var(--sdocs-text);
|
|
239
|
-
cursor: pointer;
|
|
240
|
-
font-size: 14px;
|
|
241
|
-
line-height: 1;
|
|
242
|
-
}
|
|
243
|
-
.sdocs-theme-btn:hover {
|
|
244
|
-
background: var(--sdocs-bg-hover);
|
|
245
|
-
}
|
|
246
|
-
.sdocs-fullscreen-btn {
|
|
247
|
-
padding: 2px 6px;
|
|
248
|
-
border: 1px solid var(--sdocs-border);
|
|
249
|
-
border-radius: 4px;
|
|
250
|
-
background: var(--sdocs-bg);
|
|
251
|
-
color: var(--sdocs-text);
|
|
252
|
-
cursor: pointer;
|
|
253
|
-
font-size: 14px;
|
|
254
|
-
line-height: 1;
|
|
255
|
-
}
|
|
256
|
-
.sdocs-fullscreen-btn:hover {
|
|
257
|
-
background: var(--sdocs-bg-hover);
|
|
258
|
-
}
|
|
259
|
-
.sdocs-sidebar-search {
|
|
260
|
-
padding: 8px 16px;
|
|
261
|
-
}
|
|
262
|
-
.sdocs-search-input {
|
|
263
|
-
width: 100%;
|
|
264
|
-
padding: 6px 10px;
|
|
265
|
-
border: 1px solid var(--sdocs-border);
|
|
266
|
-
border-radius: 6px;
|
|
267
|
-
font-size: 13px;
|
|
268
|
-
outline: none;
|
|
269
|
-
box-sizing: border-box;
|
|
270
|
-
background: var(--sdocs-bg);
|
|
271
|
-
color: var(--sdocs-text);
|
|
272
|
-
}
|
|
273
|
-
.sdocs-search-input:focus {
|
|
274
|
-
border-color: var(--sdocs-primary);
|
|
275
|
-
box-shadow: 0 0 0 2px var(--sdocs-primary-bg);
|
|
276
|
-
}
|
|
277
|
-
.sdocs-sidebar-tree {
|
|
278
|
-
flex: 1;
|
|
279
|
-
overflow-y: auto;
|
|
280
|
-
padding: 8px 0;
|
|
281
|
-
}
|
|
282
|
-
.sdocs-tree-item {
|
|
283
|
-
padding-left: calc(var(--depth, 0) * 16px);
|
|
284
|
-
}
|
|
285
|
-
.sdocs-group-label {
|
|
286
|
-
padding: 12px 16px 4px;
|
|
287
|
-
font-size: 11px;
|
|
288
|
-
font-weight: 600;
|
|
289
|
-
color: var(--sdocs-text-muted);
|
|
290
|
-
letter-spacing: 0.05em;
|
|
291
|
-
}
|
|
292
|
-
.sdocs-tree-btn,
|
|
293
|
-
.sdocs-tree-link {
|
|
294
|
-
display: flex;
|
|
295
|
-
align-items: center;
|
|
296
|
-
gap: 6px;
|
|
297
|
-
width: 100%;
|
|
298
|
-
padding: 4px 16px;
|
|
299
|
-
border: none;
|
|
300
|
-
background: none;
|
|
301
|
-
font: inherit;
|
|
302
|
-
color: var(--sdocs-text);
|
|
303
|
-
text-decoration: none;
|
|
304
|
-
cursor: pointer;
|
|
305
|
-
text-align: left;
|
|
306
|
-
}
|
|
307
|
-
.sdocs-tree-btn:hover,
|
|
308
|
-
.sdocs-tree-link:hover {
|
|
309
|
-
background: var(--sdocs-border);
|
|
310
|
-
}
|
|
311
|
-
.sdocs-active {
|
|
312
|
-
color: var(--sdocs-primary);
|
|
313
|
-
font-weight: 500;
|
|
314
|
-
}
|
|
315
|
-
.sdocs-tree-arrow {
|
|
316
|
-
font-size: 8px;
|
|
317
|
-
transition: transform 0.15s;
|
|
318
|
-
display: inline-block;
|
|
319
|
-
width: 10px;
|
|
320
|
-
}
|
|
321
|
-
.sdocs-tree-arrow.expanded {
|
|
322
|
-
transform: rotate(90deg);
|
|
323
|
-
}
|
|
324
|
-
.sdocs-tree-icon {
|
|
325
|
-
font-size: 10px;
|
|
326
|
-
width: 14px;
|
|
327
|
-
text-align: center;
|
|
328
|
-
}
|
|
329
|
-
</style>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
interface Props {
|
|
2
|
-
label: string;
|
|
3
|
-
value: string;
|
|
4
|
-
onchange: (value: string) => void;
|
|
5
|
-
}
|
|
6
|
-
declare const DimensionControl: import("svelte").Component<Props, {}, "">;
|
|
7
|
-
type DimensionControl = ReturnType<typeof DimensionControl>;
|
|
8
|
-
export default DimensionControl;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
interface Props {
|
|
2
|
-
label: string;
|
|
3
|
-
value: string;
|
|
4
|
-
options: string[];
|
|
5
|
-
onchange: (value: string) => void;
|
|
6
|
-
}
|
|
7
|
-
declare const SelectControl: import("svelte").Component<Props, {}, "">;
|
|
8
|
-
type SelectControl = ReturnType<typeof SelectControl>;
|
|
9
|
-
export default SelectControl;
|
package/dist/client/theme.css
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/* Figtree — variable font (300–900) */
|
|
2
|
-
@font-face {
|
|
3
|
-
font-family: 'Figtree';
|
|
4
|
-
font-style: normal;
|
|
5
|
-
font-weight: 300 900;
|
|
6
|
-
font-display: swap;
|
|
7
|
-
src: url('./fonts/figtree-latin.woff2') format('woff2');
|
|
8
|
-
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
|
|
9
|
-
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
|
|
10
|
-
U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
11
|
-
}
|
|
12
|
-
@font-face {
|
|
13
|
-
font-family: 'Figtree';
|
|
14
|
-
font-style: normal;
|
|
15
|
-
font-weight: 300 900;
|
|
16
|
-
font-display: swap;
|
|
17
|
-
src: url('./fonts/figtree-latin-ext.woff2') format('woff2');
|
|
18
|
-
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
|
|
19
|
-
U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
|
|
20
|
-
U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
|
|
21
|
-
U+A720-A7FF;
|
|
22
|
-
}
|
|
23
|
-
@font-face {
|
|
24
|
-
font-family: 'Figtree';
|
|
25
|
-
font-style: italic;
|
|
26
|
-
font-weight: 300 900;
|
|
27
|
-
font-display: swap;
|
|
28
|
-
src: url('./fonts/figtree-italic-latin.woff2') format('woff2');
|
|
29
|
-
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
|
|
30
|
-
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
|
|
31
|
-
U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
32
|
-
}
|
|
33
|
-
@font-face {
|
|
34
|
-
font-family: 'Figtree';
|
|
35
|
-
font-style: italic;
|
|
36
|
-
font-weight: 300 900;
|
|
37
|
-
font-display: swap;
|
|
38
|
-
src: url('./fonts/figtree-italic-latin-ext.woff2') format('woff2');
|
|
39
|
-
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
|
|
40
|
-
U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
|
|
41
|
-
U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
|
|
42
|
-
U+A720-A7FF;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/* sdocs design tokens */
|
|
46
|
-
|
|
47
|
-
:root,
|
|
48
|
-
[data-sdocs-theme="light"] {
|
|
49
|
-
--sdocs-font-sans: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
50
|
-
--sdocs-font-mono: 'SF Mono', Monaco, Consolas, monospace;
|
|
51
|
-
--sdocs-bg: #ffffff;
|
|
52
|
-
--sdocs-bg-subtle: #f8fafc;
|
|
53
|
-
--sdocs-bg-hover: #f1f5f9;
|
|
54
|
-
--sdocs-border: #e2e8f0;
|
|
55
|
-
--sdocs-border-muted: #cbd5e1;
|
|
56
|
-
--sdocs-text: #475569;
|
|
57
|
-
--sdocs-text-secondary: #64748b;
|
|
58
|
-
--sdocs-text-muted: #94a3b8;
|
|
59
|
-
--sdocs-text-heading: #1e293b;
|
|
60
|
-
--sdocs-text-strong: #334155;
|
|
61
|
-
--sdocs-primary: #3b82f6;
|
|
62
|
-
--sdocs-primary-bg: rgba(59, 130, 246, 0.1);
|
|
63
|
-
--sdocs-shadow: rgba(0, 0, 0, 0.1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
[data-sdocs-theme="dark"] {
|
|
67
|
-
--sdocs-bg: #0f172a;
|
|
68
|
-
--sdocs-bg-subtle: #1e293b;
|
|
69
|
-
--sdocs-bg-hover: #334155;
|
|
70
|
-
--sdocs-border: #334155;
|
|
71
|
-
--sdocs-border-muted: #475569;
|
|
72
|
-
--sdocs-text: #cbd5e1;
|
|
73
|
-
--sdocs-text-secondary: #94a3b8;
|
|
74
|
-
--sdocs-text-muted: #64748b;
|
|
75
|
-
--sdocs-text-heading: #f1f5f9;
|
|
76
|
-
--sdocs-text-strong: #e2e8f0;
|
|
77
|
-
--sdocs-primary: #60a5fa;
|
|
78
|
-
--sdocs-primary-bg: rgba(96, 165, 250, 0.15);
|
|
79
|
-
--sdocs-shadow: rgba(0, 0, 0, 0.3);
|
|
80
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { SdocMeta, ExtractedSnippet, TocHeading } from '../types.js';
|
|
2
|
-
interface SdocxParseResult {
|
|
3
|
-
meta: SdocMeta;
|
|
4
|
-
componentPath: string | null;
|
|
5
|
-
imports: string[];
|
|
6
|
-
snippets: ExtractedSnippet[];
|
|
7
|
-
toc?: TocHeading[];
|
|
8
|
-
}
|
|
9
|
-
/** Parse a .sdocx file (markdown format) */
|
|
10
|
-
export declare function parseSdocx(source: string, filePath: string, kind: 'component' | 'page' | 'layout'): Promise<SdocxParseResult>;
|
|
11
|
-
export {};
|