sdocs 0.0.39 → 0.0.41
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/CHANGELOG.md +29 -0
- package/dist/explorer/views/ComponentView.svelte +5 -2
- package/dist/grammar/sdoc.tmLanguage.json +245 -0
- package/dist/language/index.d.ts +2 -0
- package/dist/language/index.js +2 -0
- package/dist/language/parser.d.ts +82 -0
- package/dist/language/parser.js +293 -0
- package/dist/language/parser.test.d.ts +1 -0
- package/dist/language/parser.test.js +158 -0
- package/dist/language/scanner.d.ts +82 -0
- package/dist/language/scanner.js +529 -0
- package/dist/language/scanner.test.d.ts +1 -0
- package/dist/language/scanner.test.js +146 -0
- package/dist/server/snippet-compiler.d.ts +1 -1
- package/dist/server/snippet-compiler.js +15 -6
- package/dist/server/snippet-compiler.test.d.ts +1 -0
- package/dist/server/snippet-compiler.test.js +23 -0
- package/dist/vite.js +2 -1
- package/package.json +6 -1
|
@@ -35,12 +35,21 @@ export function resolveImportsToAbsolute(imports, docFilePath) {
|
|
|
35
35
|
return imp;
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
/** Add bind:this to the
|
|
39
|
-
* its exported methods and state.
|
|
40
|
-
|
|
38
|
+
/** Add bind:this to the documented component in the snippet so the wrapper
|
|
39
|
+
* can reach its exported methods and state. Binds the first occurrence of
|
|
40
|
+
* the doc's component when named (so wrapped children like
|
|
41
|
+
* <Tabs><Tab/></Tabs> documenting Tab bind the right instance), otherwise
|
|
42
|
+
* the first capitalized tag. Skipped when the author already binds. */
|
|
43
|
+
function injectRootRef(snippetBody, componentName) {
|
|
41
44
|
if (snippetBody.includes('bind:this'))
|
|
42
45
|
return snippetBody;
|
|
43
|
-
|
|
46
|
+
let match = null;
|
|
47
|
+
if (componentName) {
|
|
48
|
+
const escaped = componentName.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
49
|
+
match = snippetBody.match(new RegExp(`<${escaped}(?=[\\s/>])`));
|
|
50
|
+
}
|
|
51
|
+
if (!match)
|
|
52
|
+
match = snippetBody.match(/<[A-Z][A-Za-z0-9_]*(?=[\s/>])/);
|
|
44
53
|
if (!match || match.index === undefined)
|
|
45
54
|
return snippetBody;
|
|
46
55
|
const insertAt = match.index + match[0].length;
|
|
@@ -49,7 +58,7 @@ function injectRootRef(snippetBody) {
|
|
|
49
58
|
/** Generate a virtual Svelte iframe wrapper component for a snippet.
|
|
50
59
|
* Includes $state for reactive prop updates via postMessage, invokes
|
|
51
60
|
* component methods on request, and broadcasts exported state values. */
|
|
52
|
-
export function generateIframeComponent(absoluteImports, snippetBody, stateNames = []) {
|
|
61
|
+
export function generateIframeComponent(absoluteImports, snippetBody, stateNames = [], componentName) {
|
|
53
62
|
const importBlock = absoluteImports.length > 0
|
|
54
63
|
? absoluteImports.join('\n') + '\n'
|
|
55
64
|
: '';
|
|
@@ -118,7 +127,7 @@ ${stateBroadcast}
|
|
|
118
127
|
|
|
119
128
|
<div id="sdocs-preview">
|
|
120
129
|
{#snippet SdocsPreview(args)}
|
|
121
|
-
${injectRootRef(snippetBody)}
|
|
130
|
+
${injectRootRef(snippetBody, componentName)}
|
|
122
131
|
{/snippet}
|
|
123
132
|
{@render SdocsPreview(args)}
|
|
124
133
|
</div>`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { generateIframeComponent } from './snippet-compiler.js';
|
|
3
|
+
describe('root ref injection', () => {
|
|
4
|
+
it('binds the documented component, not the wrapper', () => {
|
|
5
|
+
const out = generateIframeComponent([], '<Tabs>\n\t<Tab {...args} />\n</Tabs>', [], 'Tab');
|
|
6
|
+
expect(out).toContain('<Tab bind:this={__sdocsRef} {...args} />');
|
|
7
|
+
expect(out).not.toContain('<Tabs bind:this');
|
|
8
|
+
});
|
|
9
|
+
it('binds the first capitalized tag when no component is named', () => {
|
|
10
|
+
const out = generateIframeComponent([], '<Card><Button /></Card>', []);
|
|
11
|
+
expect(out).toContain('<Card bind:this={__sdocsRef}>');
|
|
12
|
+
});
|
|
13
|
+
it('falls back to the first capitalized tag when the named component is absent', () => {
|
|
14
|
+
const out = generateIframeComponent([], '<Tabs active={0}>text</Tabs>', [], 'Tab');
|
|
15
|
+
expect(out).toContain('<Tabs bind:this={__sdocsRef} active={0}>');
|
|
16
|
+
});
|
|
17
|
+
it('leaves snippets with an author bind:this untouched', () => {
|
|
18
|
+
const body = '<Tab bind:this={mine} />';
|
|
19
|
+
const out = generateIframeComponent([], body, [], 'Tab');
|
|
20
|
+
expect(out).toContain(body);
|
|
21
|
+
expect(out).not.toContain('bind:this={__sdocsRef}');
|
|
22
|
+
});
|
|
23
|
+
});
|
package/dist/vite.js
CHANGED
|
@@ -217,7 +217,8 @@ export function sdocsPlugin(userConfig) {
|
|
|
217
217
|
return null;
|
|
218
218
|
const absoluteImports = docImportsCache.get(parsed.docFilePath) ?? [];
|
|
219
219
|
const stateNames = (entry.componentData?.state ?? []).map((s) => s.name);
|
|
220
|
-
|
|
220
|
+
const componentName = entry.componentPath?.split('/').pop()?.replace('.svelte', '');
|
|
221
|
+
return generateIframeComponent(absoluteImports, snippet.body, stateNames, componentName);
|
|
221
222
|
}
|
|
222
223
|
// Virtual mount script for an emitted preview page
|
|
223
224
|
if (id.startsWith('\0' + MOUNT_PREFIX)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdocs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.41",
|
|
4
4
|
"description": "A lightweight documentation tool for Svelte 5 components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"types": "./dist/vite.d.ts",
|
|
22
22
|
"default": "./dist/vite.js"
|
|
23
23
|
},
|
|
24
|
+
"./language": {
|
|
25
|
+
"types": "./dist/language/index.d.ts",
|
|
26
|
+
"default": "./dist/language/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./grammar/sdoc.tmLanguage.json": "./dist/grammar/sdoc.tmLanguage.json",
|
|
24
29
|
"./explorer": {
|
|
25
30
|
"svelte": "./dist/explorer/Explorer.svelte"
|
|
26
31
|
},
|