@storybook/addon-svelte-csf 5.1.4 → 5.1.5
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/dist/compiler/plugins.js +1 -1
- package/dist/compiler/plugins.test.js +16 -0
- package/dist/compiler/post-transform/appendix/create-runtime-story-variable-declaration.js +1 -1
- package/dist/compiler/post-transform/define-meta/insert-parameters.js +8 -8
- package/dist/compiler/post-transform/define-meta/insert-parameters.test.d.ts +1 -0
- package/dist/compiler/post-transform/define-meta/insert-parameters.test.js +41 -0
- package/dist/compiler/post-transform/index.test.js +41 -0
- package/dist/compiler/post-transform/story/insert-description.js +8 -8
- package/dist/compiler/post-transform/story/insert-svelte-csf.js +4 -4
- package/dist/parser/ast.d.ts +5 -0
- package/dist/parser/ast.js +7 -0
- package/package.json +1 -1
package/dist/compiler/plugins.js
CHANGED
|
@@ -48,7 +48,7 @@ export async function preTransformPlugin() {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
let magicCode = new MagicString(code);
|
|
51
|
-
magicCode.overwrite(0, code.length
|
|
51
|
+
magicCode.overwrite(0, code.length, print(transformedSvelteAST));
|
|
52
52
|
const stringifiedMagicCode = magicCode.toString();
|
|
53
53
|
return {
|
|
54
54
|
code: stringifiedMagicCode,
|
|
@@ -43,4 +43,20 @@ describe(preTransformPlugin.name, () => {
|
|
|
43
43
|
expect(result.code).toContain('defineMeta');
|
|
44
44
|
expect(result.meta._storybook_csf_pre_transform).toBe(result.code);
|
|
45
45
|
});
|
|
46
|
+
it('does not repeat the last character of a legacy file', async ({ expect }) => {
|
|
47
|
+
const code = dedent(`
|
|
48
|
+
<script context="module">
|
|
49
|
+
import { Story } from "${pkg.name}";
|
|
50
|
+
import Button from "./Button.svelte";
|
|
51
|
+
|
|
52
|
+
export const meta = { component: Button };
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<Story name="Default" />
|
|
56
|
+
foo
|
|
57
|
+
`);
|
|
58
|
+
const result = await runPreTransform(code);
|
|
59
|
+
expect(code.endsWith('foo')).toBe(true);
|
|
60
|
+
expect(result.code).toMatch(/[^o]foo$/);
|
|
61
|
+
});
|
|
46
62
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { STORYBOOK_INTERNAL_PREFIX, SVELTE_CSF_TAG_PREFIX, SVELTE_CSF_V5_TAG, } from '../../../constants.js';
|
|
2
2
|
import { createASTArrayExpression, createASTIdentifier, createASTObjectExpression, createASTProperty, } from '../../../parser/ast.js';
|
|
3
3
|
export function createRuntimeStoryVariableDeclaration(params) {
|
|
4
|
-
const tags = createASTArrayExpression(params.nodes.tags?.elements);
|
|
4
|
+
const tags = createASTArrayExpression([...(params.nodes.tags?.elements ?? [])]);
|
|
5
5
|
// In legacy stories, the pre-transform will add a SVELTE_CSF_V4_TAG tag.
|
|
6
6
|
// if it is not present, we add the SVELTE_CSF_V5_TAG tag.
|
|
7
7
|
const hasSvelteCsfTag = tags.elements.some((element) => element?.type === 'Literal' && element.value?.toString().startsWith(SVELTE_CSF_TAG_PREFIX));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { findASTPropertyIndex, findPropertyDescriptionIndex, findPropertyDocsIndex, findPropertyParametersIndex, getDescriptionPropertyValue, getDocsPropertyValue, getParametersPropertyValue, } from '../shared/parameters.js';
|
|
2
|
-
import { createASTObjectExpression, createASTProperty } from '../../../parser/ast.js';
|
|
2
|
+
import { appendASTProperty, createASTObjectExpression, createASTProperty, } from '../../../parser/ast.js';
|
|
3
3
|
import { getDefineMetaFirstArgumentObjectExpression } from '../../../parser/extract/svelte/define-meta.js';
|
|
4
4
|
/**
|
|
5
5
|
* This function inserts parameters to `defineMeta()`.
|
|
@@ -37,25 +37,25 @@ export function insertDefineMetaParameters(params) {
|
|
|
37
37
|
filename,
|
|
38
38
|
node: defineMetaFirstArgumentObjectExpression,
|
|
39
39
|
}) === -1) {
|
|
40
|
-
defineMetaFirstArgumentObjectExpression
|
|
40
|
+
appendASTProperty(defineMetaFirstArgumentObjectExpression, createASTProperty('parameters', createASTObjectExpression()));
|
|
41
41
|
}
|
|
42
42
|
if (findPropertyDocsIndex({
|
|
43
43
|
filename,
|
|
44
44
|
node: defineMetaFirstArgumentObjectExpression,
|
|
45
45
|
}) === -1) {
|
|
46
|
-
getParametersPropertyValue({
|
|
46
|
+
appendASTProperty(getParametersPropertyValue({
|
|
47
47
|
filename,
|
|
48
48
|
node: defineMetaFirstArgumentObjectExpression,
|
|
49
|
-
})
|
|
49
|
+
}), createASTProperty('docs', createASTObjectExpression()));
|
|
50
50
|
}
|
|
51
51
|
if (findPropertyDescriptionIndex({
|
|
52
52
|
filename,
|
|
53
53
|
node: defineMetaFirstArgumentObjectExpression,
|
|
54
54
|
}) === -1) {
|
|
55
|
-
getDocsPropertyValue({
|
|
55
|
+
appendASTProperty(getDocsPropertyValue({
|
|
56
56
|
filename,
|
|
57
57
|
node: defineMetaFirstArgumentObjectExpression,
|
|
58
|
-
})
|
|
58
|
+
}), createASTProperty('description', createASTObjectExpression()));
|
|
59
59
|
}
|
|
60
60
|
if (findASTPropertyIndex({
|
|
61
61
|
name: 'component',
|
|
@@ -70,10 +70,10 @@ export function insertDefineMetaParameters(params) {
|
|
|
70
70
|
${filename}`);
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
|
-
getDescriptionPropertyValue({
|
|
73
|
+
appendASTProperty(getDescriptionPropertyValue({
|
|
74
74
|
filename,
|
|
75
75
|
node: defineMetaFirstArgumentObjectExpression,
|
|
76
|
-
})
|
|
76
|
+
}), createASTProperty('component', {
|
|
77
77
|
type: 'Literal',
|
|
78
78
|
value: extractDescription(nodes.svelte.defineMetaVariableDeclaration.leadingComments),
|
|
79
79
|
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import pkg from '@storybook/addon-svelte-csf/package.json' with { type: 'json' };
|
|
2
|
+
import dedent from 'dedent';
|
|
3
|
+
import { print } from 'esrap';
|
|
4
|
+
import { parseAst } from 'rollup/parseAst';
|
|
5
|
+
import { compile } from 'svelte/compiler';
|
|
6
|
+
import { describe, it } from 'vitest';
|
|
7
|
+
import { insertDefineMetaParameters } from './insert-parameters.js';
|
|
8
|
+
import { getSvelteAST } from '../../../parser/ast.js';
|
|
9
|
+
import { extractCompiledASTNodes } from '../../../parser/extract/compiled/nodes.js';
|
|
10
|
+
import { extractSvelteASTNodes } from '../../../parser/extract/svelte/nodes.js';
|
|
11
|
+
import { getDefineMetaFirstArgumentObjectExpression } from '../../../parser/extract/svelte/define-meta.js';
|
|
12
|
+
describe(insertDefineMetaParameters.name, () => {
|
|
13
|
+
it('works when defineMeta gets an empty object', async ({ expect }) => {
|
|
14
|
+
const code = dedent `
|
|
15
|
+
<script module>
|
|
16
|
+
import { defineMeta } from "${pkg.name}";
|
|
17
|
+
|
|
18
|
+
/** Description of the component */
|
|
19
|
+
const { Story } = defineMeta({});
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<Story name="Default" />
|
|
23
|
+
`;
|
|
24
|
+
const svelteNodes = await extractSvelteASTNodes({ ast: getSvelteAST({ code }) });
|
|
25
|
+
// NOTE: Rollup's parser returns a frozen array for the properties of an empty object literal
|
|
26
|
+
const compiledNodes = await extractCompiledASTNodes({
|
|
27
|
+
ast: parseAst(compile(code, { filename: 'Test.stories.svelte' }).js.code),
|
|
28
|
+
});
|
|
29
|
+
insertDefineMetaParameters({ nodes: { svelte: svelteNodes, compiled: compiledNodes } });
|
|
30
|
+
const objectExpression = getDefineMetaFirstArgumentObjectExpression({ nodes: compiledNodes });
|
|
31
|
+
expect(print(objectExpression).code).toMatchInlineSnapshot(`
|
|
32
|
+
"{
|
|
33
|
+
parameters: {
|
|
34
|
+
docs: {
|
|
35
|
+
description: { component: "Description of the component" }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}"
|
|
39
|
+
`);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import url from 'node:url';
|
|
4
|
+
import pkg from '@storybook/addon-svelte-csf/package.json' with { type: 'json' };
|
|
5
|
+
import dedent from 'dedent';
|
|
4
6
|
import MagicString from 'magic-string';
|
|
5
7
|
import { parseAst } from 'rollup/parseAst';
|
|
8
|
+
import { compile } from 'svelte/compiler';
|
|
6
9
|
import { describe, it } from 'vitest';
|
|
7
10
|
import { transformStoriesCode } from './index.js';
|
|
8
11
|
import { getSvelteAST } from '../../parser/ast.js';
|
|
@@ -276,4 +279,42 @@ describe(transformStoriesCode.name, () => {
|
|
|
276
279
|
};"
|
|
277
280
|
`);
|
|
278
281
|
});
|
|
282
|
+
it('works with empty object and array literals', async ({ expect }) => {
|
|
283
|
+
const filename = 'Empty.stories.svelte';
|
|
284
|
+
const originalCode = dedent `
|
|
285
|
+
<script module>
|
|
286
|
+
import { defineMeta } from "${pkg.name}";
|
|
287
|
+
|
|
288
|
+
/** Description of the component */
|
|
289
|
+
const { Story } = defineMeta({});
|
|
290
|
+
</script>
|
|
291
|
+
|
|
292
|
+
<!-- Description of the story -->
|
|
293
|
+
<Story name="Default" parameters={{}} tags={[]} />
|
|
294
|
+
`;
|
|
295
|
+
const compiledCode = compile(originalCode, { filename, dev: true }).js.code;
|
|
296
|
+
const svelteASTNodes = await extractSvelteASTNodes({
|
|
297
|
+
ast: getSvelteAST({ code: originalCode, filename }),
|
|
298
|
+
filename,
|
|
299
|
+
});
|
|
300
|
+
// NOTE: Rollup's parser returns frozen arrays for empty object and array literals
|
|
301
|
+
const compiledASTNodes = await extractCompiledASTNodes({
|
|
302
|
+
ast: parseAst(compiledCode),
|
|
303
|
+
filename,
|
|
304
|
+
});
|
|
305
|
+
const code = new MagicString(compiledCode);
|
|
306
|
+
await transformStoriesCode({
|
|
307
|
+
code,
|
|
308
|
+
nodes: {
|
|
309
|
+
svelte: svelteASTNodes,
|
|
310
|
+
compiled: compiledASTNodes,
|
|
311
|
+
},
|
|
312
|
+
filename,
|
|
313
|
+
originalCode,
|
|
314
|
+
});
|
|
315
|
+
const output = code.toString();
|
|
316
|
+
expect(output).toContain('component: "Description of the component"');
|
|
317
|
+
expect(output).toContain('story: "Description of the story"');
|
|
318
|
+
expect(output).toContain('__svelteCsf');
|
|
319
|
+
});
|
|
279
320
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import dedent from 'dedent';
|
|
2
2
|
import { findASTPropertyIndex, findPropertyDescriptionIndex, findPropertyDocsIndex, findPropertyParametersIndex, getParametersPropertyValue, getDocsPropertyValue, getDescriptionPropertyValue, } from '../shared/parameters.js';
|
|
3
|
-
import { createASTObjectExpression, createASTProperty } from '../../../parser/ast.js';
|
|
3
|
+
import { appendASTProperty, createASTObjectExpression, createASTProperty, } from '../../../parser/ast.js';
|
|
4
4
|
import { getStoryPropsObjectExpression } from '../../../parser/extract/compiled/story.js';
|
|
5
5
|
/**
|
|
6
6
|
* Attempt to insert HTML comment above the `<Story />` component as a description **into the compiled code**.
|
|
@@ -22,29 +22,29 @@ export function insertStoryHTMLCommentAsDescription(params) {
|
|
|
22
22
|
component,
|
|
23
23
|
node: storyPropsObjectExpression,
|
|
24
24
|
}) === -1) {
|
|
25
|
-
storyPropsObjectExpression
|
|
25
|
+
appendASTProperty(storyPropsObjectExpression, createASTProperty('parameters', createASTObjectExpression()));
|
|
26
26
|
}
|
|
27
27
|
if (findPropertyDocsIndex({
|
|
28
28
|
filename,
|
|
29
29
|
component,
|
|
30
30
|
node: storyPropsObjectExpression,
|
|
31
31
|
}) === -1) {
|
|
32
|
-
getParametersPropertyValue({
|
|
32
|
+
appendASTProperty(getParametersPropertyValue({
|
|
33
33
|
filename,
|
|
34
34
|
component,
|
|
35
35
|
node: storyPropsObjectExpression,
|
|
36
|
-
})
|
|
36
|
+
}), createASTProperty('docs', createASTObjectExpression()));
|
|
37
37
|
}
|
|
38
38
|
if (findPropertyDescriptionIndex({
|
|
39
39
|
filename,
|
|
40
40
|
component,
|
|
41
41
|
node: storyPropsObjectExpression,
|
|
42
42
|
}) === -1) {
|
|
43
|
-
getDocsPropertyValue({
|
|
43
|
+
appendASTProperty(getDocsPropertyValue({
|
|
44
44
|
filename,
|
|
45
45
|
component,
|
|
46
46
|
node: storyPropsObjectExpression,
|
|
47
|
-
})
|
|
47
|
+
}), createASTProperty('description', createASTObjectExpression()));
|
|
48
48
|
}
|
|
49
49
|
if (findASTPropertyIndex({
|
|
50
50
|
filename,
|
|
@@ -67,11 +67,11 @@ export function insertStoryHTMLCommentAsDescription(params) {
|
|
|
67
67
|
${filename}`);
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
getDescriptionPropertyValue({
|
|
70
|
+
appendASTProperty(getDescriptionPropertyValue({
|
|
71
71
|
filename,
|
|
72
72
|
component,
|
|
73
73
|
node: storyPropsObjectExpression,
|
|
74
|
-
})
|
|
74
|
+
}), createASTProperty('story', {
|
|
75
75
|
type: 'Literal',
|
|
76
76
|
value: dedent(comment.data),
|
|
77
77
|
}));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { findPropertyParametersIndex, getParametersPropertyValue, } from '../shared/parameters.js';
|
|
2
2
|
import { getStoryPropsObjectExpression } from '../../../parser/extract/compiled/story.js';
|
|
3
3
|
import { getStoryContentRawCode } from '../../../parser/analyse/story/content.js';
|
|
4
|
-
import { createASTObjectExpression, createASTProperty } from '../../../parser/ast.js';
|
|
4
|
+
import { appendASTProperty, createASTObjectExpression, createASTProperty, } from '../../../parser/ast.js';
|
|
5
5
|
/**
|
|
6
6
|
* Insert addon's internal object `__svelteCsf`
|
|
7
7
|
* to `parameters` of every `<Story />` component **into the compiled code**.
|
|
@@ -18,7 +18,7 @@ export function insertSvelteCSFToStoryParameters(params) {
|
|
|
18
18
|
component: component.svelte.component,
|
|
19
19
|
node: storyPropsObjectExpression,
|
|
20
20
|
}) === -1) {
|
|
21
|
-
storyPropsObjectExpression
|
|
21
|
+
appendASTProperty(storyPropsObjectExpression, createASTProperty('parameters', createASTObjectExpression()));
|
|
22
22
|
}
|
|
23
23
|
const rawCode = getStoryContentRawCode({
|
|
24
24
|
nodes: {
|
|
@@ -27,11 +27,11 @@ export function insertSvelteCSFToStoryParameters(params) {
|
|
|
27
27
|
},
|
|
28
28
|
originalCode,
|
|
29
29
|
});
|
|
30
|
-
getParametersPropertyValue({
|
|
30
|
+
appendASTProperty(getParametersPropertyValue({
|
|
31
31
|
filename,
|
|
32
32
|
component: component.svelte.component,
|
|
33
33
|
node: storyPropsObjectExpression,
|
|
34
|
-
})
|
|
34
|
+
}), createASTProperty('__svelteCsf', createASTObjectExpression([
|
|
35
35
|
createASTProperty('rawCode', {
|
|
36
36
|
type: 'Literal',
|
|
37
37
|
value: rawCode,
|
package/dist/parser/ast.d.ts
CHANGED
|
@@ -29,6 +29,11 @@ export declare function createASTArrayExpression(elements?: ESTreeAST.ArrayExpre
|
|
|
29
29
|
* By default it will create an empty object.
|
|
30
30
|
*/
|
|
31
31
|
export declare function createASTObjectExpression(properties?: ESTreeAST.ObjectExpression['properties']): ESTreeAST.ObjectExpression;
|
|
32
|
+
/**
|
|
33
|
+
* Append a property to an {@link ESTreeAST.ObjectExpression}.
|
|
34
|
+
* It replaces the array instead of using `push`, because Rollup's parser returns a frozen array for an empty object literal.
|
|
35
|
+
*/
|
|
36
|
+
export declare function appendASTProperty(node: ESTreeAST.ObjectExpression, property: ESTreeAST.ObjectExpression['properties'][number]): void;
|
|
32
37
|
interface ASTScriptOptions {
|
|
33
38
|
module?: boolean;
|
|
34
39
|
content: SvelteAST.Script['content'];
|
package/dist/parser/ast.js
CHANGED
|
@@ -66,6 +66,13 @@ export function createASTObjectExpression(properties = []) {
|
|
|
66
66
|
properties,
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Append a property to an {@link ESTreeAST.ObjectExpression}.
|
|
71
|
+
* It replaces the array instead of using `push`, because Rollup's parser returns a frozen array for an empty object literal.
|
|
72
|
+
*/
|
|
73
|
+
export function appendASTProperty(node, property) {
|
|
74
|
+
node.properties = [...node.properties, property];
|
|
75
|
+
}
|
|
69
76
|
export function createASTScript(options) {
|
|
70
77
|
const { content, module = false } = options;
|
|
71
78
|
const attributes = [];
|