Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte: Fix source with decorators always showing the SlotDecorator component #24800

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions code/e2e-tests/framework-svelte.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable jest/no-disabled-tests */
import { test, expect } from '@playwright/test';
import process from 'process';
import dedent from 'ts-dedent';
import { SbPage } from './util';

const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:6006';
Expand Down Expand Up @@ -37,4 +38,16 @@ test.describe('Svelte', () => {
const argsTable = root.locator('.docblock-argstable');
await expect(argsTable).toContainText('Rounds the button');
});

test('Decorators are excluded from generated source code', async ({ page }) => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('stories/renderers/svelte/slot-decorators', 'docs');
const root = sbPage.previewRoot();
const showCodeButton = (await root.locator('button', { hasText: 'Show Code' }).all())[0];
await showCodeButton.click();
const sourceCode = root.locator('pre.prismjs');
const expectedSource = '<ButtonJavaScript primary/>';
await expect(sourceCode.textContent()).resolves.toContain(expectedSource);
});
Comment on lines +42 to +52
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hoping to write framework-agnostic versions of this test soon, because I sense that this is an area where we're often seeing regressions.

});
4 changes: 2 additions & 2 deletions code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import MagicString from 'magic-string';
import path from 'path';
import fs from 'fs';
import svelteDoc from 'sveltedoc-parser';
import type { SvelteParserOptions } from 'sveltedoc-parser';
import type { SvelteComponentDoc, SvelteParserOptions } from 'sveltedoc-parser';
import { logger } from '@storybook/node-logger';
import { preprocess } from 'svelte/compiler';
import { createFilter } from 'vite';
Expand Down Expand Up @@ -120,7 +120,7 @@ export function svelteDocgen(svelteOptions: Record<string, any> = {}): PluginOpt

const s = new MagicString(src);

let componentDoc: any;
let componentDoc: SvelteComponentDoc & { keywords?: string[] };
try {
componentDoc = await svelteDoc.parse(options);
} catch (error: any) {
Expand Down
36 changes: 26 additions & 10 deletions code/renderers/svelte/src/docs/sourceDecorator.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
/* eslint-disable no-underscore-dangle */
import { addons, useEffect } from '@storybook/preview-api';
import { deprecate } from '@storybook/client-logger';
import type { ArgTypes, Args, StoryContext } from '@storybook/types';
import type {
ArgTypes,
Args,
ArgsStoryFn,
DecoratorFunction,
StoryContext,
} from '@storybook/types';

import { SourceType, SNIPPET_RENDERED } from '@storybook/docs-tools';
import type { SvelteRenderer } from '../types';
import type { SvelteComponentDoc } from 'sveltedoc-parser';
import type { SvelteRenderer, SvelteStoryResult } from '../types';

/**
* Check if the source-code should be generated.
Expand Down Expand Up @@ -140,19 +147,23 @@ export function generateSvelteSource(
*
* @param component Component
*/
function getWrapperProperties(component: any) {
function getWrapperProperties(
component?: SvelteStoryResult['Component'] & {
__docgen?: SvelteComponentDoc & { keywords?: string[] };
}
) {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { __docgen } = component;
const { __docgen } = component || {};
if (!__docgen) {
return { wrapper: false };
}

// the component should be declared as a wrapper
if (!__docgen.keywords.find((kw: any) => kw.name === 'wrapper')) {
if (!__docgen.keywords?.find((kw: any) => kw.name === 'wrapper')) {
return { wrapper: false };
}

const slotProp = __docgen.data.find((prop: any) =>
const slotProp = __docgen.data?.find((prop: any) =>
prop.keywords.find((kw: any) => kw.name === 'slot')
);
return { wrapper: true, slotProperty: slotProp?.name as string };
Expand All @@ -163,7 +174,7 @@ function getWrapperProperties(component: any) {
* @param storyFn Fn
* @param context StoryContext
*/
export const sourceDecorator = (storyFn: any, context: StoryContext<SvelteRenderer>) => {
export const sourceDecorator: DecoratorFunction<SvelteRenderer> = (storyFn, context) => {
const channel = addons.getChannel();
const skip = skipSourceRender(context);
const story = storyFn();
Expand All @@ -181,16 +192,21 @@ export const sourceDecorator = (storyFn: any, context: StoryContext<SvelteRender
return story;
}

const { parameters = {}, args = {}, component: ctxtComponent } = context || {};
let { Component: component = {} } = story;
const { parameters = {}, args = {}, component: ctxComponent } = context || {};

// excludeDecorators from source generation as they'll generate the wrong code
// instead get the component directly from the original story function instead
let { Component: component } = (context.originalStoryFn as ArgsStoryFn<SvelteRenderer>)(
args,
context
);
const { wrapper, slotProperty } = getWrapperProperties(component);
if (wrapper) {
if (parameters.component) {
deprecate('parameters.component is deprecated. Using context.component instead.');
}

component = ctxtComponent;
component = ctxComponent;
}

const generated = generateSvelteSource(component, args, context?.argTypes, slotProperty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default {
args: {
primary: true,
},
tags: ['autodocs'],
};

export const WithDefaultRedBorder = {};
Expand Down
Loading