Skip to content

Commit

Permalink
refactor transform parser
Browse files Browse the repository at this point in the history
  • Loading branch information
xeho91 committed Nov 10, 2024
1 parent 688b73d commit a0b0a96
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 106 deletions.
10 changes: 5 additions & 5 deletions examples/Templating.stories.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
-->
<Story
name="Template snippet"
args={{ text: 'This story uses a children snippet' }}
args={{ text: 'This story uses a template snippet' }}
play={async (context) => {
const { args, canvasElement } = context;
const canvas = within(canvasElement);
Expand All @@ -85,7 +85,7 @@
}}
>
{#snippet template(args)}
<h2 data-testid="heading">Children snippet</h2>
<h2 data-testid="heading">Template snippet</h2>
<p>{args?.text}</p>
{/snippet}
</Story>
Expand All @@ -97,7 +97,7 @@

<!--
If you want to share the template between multiple stories,
you can define the snippet at the root and pass it in as the `children` **prop** to the `<Story>` component.
you can define the snippet at the root and pass it in as the `template` **prop** to the `<Story>` component.
Example:
Expand All @@ -108,14 +108,14 @@
</SomeComponent>
{/snippet}
<Story name="Explicit snippet" children={template} />
<Story name="Explicit snippet" {template} />
```
-->
<Story
name="Shared template"
template={sharedTemplate}
args={{
text: 'This story uses a shared snippet, which is explicitly set as the `children` prop to the <Story> component',
text: 'This story uses a shared snippet, which is explicitly set as the `template` prop to the <Story> component',
}}
play={async (context) => {
const { args, canvasElement } = context;
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/post-transform/story/insert-svelte-csf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import type { extractStoriesNodesFromExportDefaultFn } from '#parser/extract/compiled/stories';
import { getStoryPropsObjectExpression } from '#parser/extract/compiled/story';
import type { SvelteASTNodes, extractSvelteASTNodes } from '#parser/extract/svelte/nodes';
import { getStoryChildrenRawCode } from '#parser/analyse/story/children';
import { getStoryContentRawCode } from '#parser/analyse/story/content';
import { createASTObjectExpression, createASTProperty } from '#parser/ast';

interface Params {
Expand Down Expand Up @@ -46,7 +46,7 @@ export function insertSvelteCSFToStoryParameters(params: Params) {
);
}

const rawCode = getStoryChildrenRawCode({
const rawCode = getStoryContentRawCode({
nodes: {
component: component.svelte.component,
svelte,
Expand Down
6 changes: 2 additions & 4 deletions src/compiler/pre-transform/codemods/legacy-story.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ describe(transformLegacyStory.name, () => {
state: { componentIdentifierName: {} },
})
)
).toMatchInlineSnapshot(`"<Story name="Default" children={someTemplate} />"`);
).toMatchInlineSnapshot(`"<Story name="Default" template={someTemplate} />"`);
});

it("when directive 'let:args' is used then it wraps Story fragment with 'children' snippet block", async ({
Expand Down Expand Up @@ -280,9 +280,7 @@ describe(transformLegacyStory.name, () => {
`);
});

it("leaves existing Story parameters untouched", async ({
expect,
}) => {
it('leaves existing Story parameters untouched', async ({ expect }) => {
const code = `
<script context="module">
import { Story } from "@storybook/addon-svelte-csf";
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/pre-transform/codemods/legacy-story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ function templateToChildren(

return {
...rest,
name: 'children',
name: 'template',
value: [
createASTExpressionTag({
type: 'Identifier',
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/pre-transform/codemods/template-to-snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface Params {
* @example 1. without provided `id` prop _(attribute)_
* ```diff
* - <Template let:args let:context>
* + {#snippet children(args, context)}
* + {#snippet template(args, context)}
* <!-- fragment -> body -->
* + {/snippet}
* - </Template>
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/pre-transform/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ describe(codemodLegacyNodes.name, () => {
<p>{context.id}</p>
<Button {...args} />
{/snippet} <Story name="Default" children={sample} tags={["autodocs"]} parameters={{
{/snippet} <Story name="Default" template={sample} tags={["autodocs"]} parameters={{
docs: { source: { code: "<Button {...args} />" } }
}}>
{#snippet children(args, context)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { describe, it } from 'vitest';

import { getStoryChildrenRawCode } from './children';
import { getStoryContentRawCode } from './content';

import { getSvelteAST } from '#parser/ast';
import { extractSvelteASTNodes } from '#parser/extract/svelte/nodes';

describe(getStoryChildrenRawCode.name, () => {
describe(getStoryContentRawCode.name, () => {
describe('When a `<Story />` is a self-closing tag...', () => {
it('works when `children` attribute was provided with a reference to snippet at the root of fragment', async ({
it('works when `template` attribute was provided with a reference to snippet at the root of fragment', async ({
expect,
}) => {
const code = `
Expand All @@ -25,13 +25,13 @@ describe(getStoryChildrenRawCode.name, () => {
<SomeComponent {...args} />
{/snippet}
<Story name="Default" children={template} />
<Story name="Default" {template} />
`;
const ast = getSvelteAST({ code });
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
Expand Down Expand Up @@ -68,7 +68,7 @@ describe(getStoryChildrenRawCode.name, () => {
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
Expand All @@ -79,7 +79,7 @@ describe(getStoryChildrenRawCode.name, () => {
expect(rawSource).toBe('<SomeComponent {...args} />');
});

it('works implicit `children` attribute takes precedence over `setTemplate`', async ({
it('works implicit `template` attribute takes precedence over `setTemplate`', async ({
expect,
}) => {
const code = `
Expand All @@ -105,13 +105,13 @@ describe(getStoryChildrenRawCode.name, () => {
<SomeComponent wins="childrenAttribute" {...args} />
{/snippet}
<Story name="Default" children={templateForChildren} />
<Story name="Default" template={templateForChildren} />
`;
const ast = getSvelteAST({ code });
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
Expand All @@ -122,7 +122,7 @@ describe(getStoryChildrenRawCode.name, () => {
expect(rawSource).toBe(`<SomeComponent wins="childrenAttribute" {...args} />`);
});

it('works when no `setTemplate`, no `children` attribute, just a story', async ({ expect }) => {
it('works when no `setTemplate`, no `template` attribute, just a story', async ({ expect }) => {
const code = `
<script module>
import { defineMeta } from "@storybook/addon-svelte-csf";
Expand All @@ -140,7 +140,7 @@ describe(getStoryChildrenRawCode.name, () => {
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
Expand All @@ -166,25 +166,25 @@ describe(getStoryChildrenRawCode.name, () => {
</script>
<Story name="Default">
<SomeComponent foo="bar" />
<h1>Static content</h1>
</Story>
`;
const ast = getSvelteAST({ code });
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
},
originalCode: code,
});

expect(rawSource).toBe(`<SomeComponent foo="bar" />`);
expect(rawSource).toBe(`<h1>Static content</h1>`);
});

it("works when a `children` svelte's snippet block used inside", async ({ expect }) => {
it("works when a `template` svelte's snippet block used inside", async ({ expect }) => {
const code = `
<script module>
import { defineMeta } from "@storybook/addon-svelte-csf";
Expand All @@ -197,7 +197,7 @@ describe(getStoryChildrenRawCode.name, () => {
</script>
<Story name="Default">
{#snippet children(args)}
{#snippet template(args)}
<SomeComponent {...args} />
{/snippet}
</Story>
Expand All @@ -206,7 +206,7 @@ describe(getStoryChildrenRawCode.name, () => {
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
Expand All @@ -217,7 +217,7 @@ describe(getStoryChildrenRawCode.name, () => {
expect(rawSource).toBe(`<SomeComponent {...args} />`);
});

it("inner `<Story>`'s children content takes precedence over `setTemplate`", async ({
it("inner `<Story>`'s template content takes precedence over `setTemplate`", async ({
expect,
}) => {
const code = `
Expand All @@ -240,24 +240,24 @@ describe(getStoryChildrenRawCode.name, () => {
{/snippet}
<Story name="Default">
{#snippet children(args)}
<SomeComponent wins="children" {...args} />
{#snippet template(args)}
<SomeComponent wins="inner-template" {...args} />
{/snippet}
</Story>
`;
const ast = getSvelteAST({ code });
const svelteASTNodes = await extractSvelteASTNodes({ ast });
const { storyComponents } = svelteASTNodes;
const component = storyComponents[0].component;
const rawSource = getStoryChildrenRawCode({
const rawSource = getStoryContentRawCode({
nodes: {
component,
svelte: svelteASTNodes,
},
originalCode: code,
});

expect(rawSource).toBe(`<SomeComponent wins="children" {...args} />`);
expect(rawSource).toBe(`<SomeComponent wins="inner-template" {...args} />`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import dedent from 'dedent';
import { getDefineMetaComponentValue } from '#parser/analyse/define-meta/component-identifier';
import type { SvelteAST } from '#parser/ast';
import type { extractSvelteASTNodes } from '#parser/extract/svelte/nodes';
import { extractStoryChildrenSnippetBlock } from '#parser/extract/svelte/story/children';
import { extractStoryTemplateSnippetBlock } from '#parser/extract/svelte/story/template';
import {
findSetTemplateSnippetBlock,
findStoryAttributeChildrenSnippetBlock,
findStoryAttributeTemplateSnippetBlock,
} from '#parser/extract/svelte/snippet-block';

interface Params {
Expand All @@ -19,17 +19,17 @@ interface Params {
}

/**
* Extract the source code of the `<Story />` component children.
* Extract the source code of the `<Story />` component content (children or template snippet).
* Reference: Step 2 from the comment: https://github.com/storybookjs/addon-svelte-csf/pull/181#issuecomment-2143539873
*/
export function getStoryChildrenRawCode(params: Params): string {
export function getStoryContentRawCode(params: Params): string {
const { nodes, originalCode, filename } = params;
const { component, svelte } = nodes;

// `<Story />` component is self-closing...
if (component.fragment.nodes.length === 0) {
/**
* Case - "explicit template" - `children` attribute references to a snippet block at the root level of fragment.
* Case - "explicit template" - `template` attribute references to a snippet block at the root level of fragment.
*
* Example:
*
Expand All @@ -38,17 +38,17 @@ export function getStoryChildrenRawCode(params: Params): string {
* <SomeComponent {...args} />
* {/snippet}
*
* <Story name="Default" children={template1} />
* <Story name="Default" template={template1} />
* ```
*/
const storyAttributeChildrenSnippetBlock = findStoryAttributeChildrenSnippetBlock({
const storyAttributTemplateSnippetBlock = findStoryAttributeTemplateSnippetBlock({
component,
nodes: svelte,
filename,
});

if (storyAttributeChildrenSnippetBlock) {
return getSnippetBlockBodyRawCode(originalCode, storyAttributeChildrenSnippetBlock);
if (storyAttributTemplateSnippetBlock) {
return getSnippetBlockBodyRawCode(originalCode, storyAttributTemplateSnippetBlock);
}

/**
Expand Down Expand Up @@ -88,19 +88,19 @@ export function getStoryChildrenRawCode(params: Params): string {
}

/**
* Case - Story with children - and with a snippet block `children` inside
* Case - Story with children - and with a snippet block `template` inside
*
* Example:
*
* ```svelte
* <Story name="Default">
* {#snippet children(args)}
* {#snippet template(args)}
* <SomeComponent {...args} />
* {/snippet}
* </Story>
* ```
*/
const storyChildrenSnippetBlock = extractStoryChildrenSnippetBlock(component);
const storyChildrenSnippetBlock = extractStoryTemplateSnippetBlock(component);

if (storyChildrenSnippetBlock) {
return getSnippetBlockBodyRawCode(originalCode, storyChildrenSnippetBlock);
Expand Down Expand Up @@ -132,7 +132,7 @@ export function getStoryChildrenRawCode(params: Params): string {
* For example, from the following case:
*
* ```svelte
* {#snippet children(args)}
* {#snippet template(args)}
* <!-- Some comment... -->
* "Static text"
* <Component {...args } />
Expand Down
Loading

0 comments on commit a0b0a96

Please sign in to comment.