Skip to content

Commit

Permalink
Move parsing of instance to module & experiment with defineMeta
Browse files Browse the repository at this point in the history
  • Loading branch information
xeho91 committed May 20, 2024
1 parent 3186d77 commit 20c926f
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 198 deletions.
6 changes: 4 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ if (module?.hot?.decline) {
module.hot.decline();
}

// TODO: Consult if these are correct types
export type Template<M extends Meta> = {
args: StoryObj<M>['args'];
args: M['args'] & StoryObj<M>['args'];
context: StoryContext<M['args']>;
};

export function defineComponent<const M extends Meta>(meta: M) {
export function defineMeta<const M extends Meta>(meta: M) {
return {
Story: Story as typeof Story<M>,
meta,
};
}
19 changes: 10 additions & 9 deletions src/parser/collect-stories.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/* eslint-env browser */
import { combineTags } from '@storybook/csf';
import { logger } from '@storybook/client-logger';
import { combineArgs, combineParameters } from '@storybook/preview-api';
import type { Meta, StoryFn } from '@storybook/svelte';
import { type ComponentProps, type SvelteComponent, mount, unmount } from 'svelte';
import { type SvelteComponent, mount, unmount } from 'svelte';

import type { StoriesFileMeta } from './types.js';
import type { StoriesRepository } from '../components/context.svelte.js';

import StoriesExtractor from '../components/StoriesExtractor.svelte';
import StoryRenderer from '../components/StoryRenderer.svelte';
import { combineTags } from '@storybook/csf';

const createFragment = document.createDocumentFragment
? () => document.createDocumentFragment()
Expand All @@ -27,12 +27,12 @@ const createFragment = document.createDocumentFragment
* instantiate the main Stories component: Every Story but
* the one selected is disabled.
*/
export default <Component extends SvelteComponent>(
Stories: Component,
export default <M extends Meta>(
Stories: SvelteComponent,
storiesFileMeta: StoriesFileMeta,
meta: Meta<Component>
meta: M
) => {
if (!meta.parameters?.docs?.description?.component) {
if (!meta.parameters?.docs?.description?.component && storiesFileMeta.module.description) {
meta.parameters = combineParameters(meta.parameters, {
docs: {
description: {
Expand All @@ -42,7 +42,7 @@ export default <Component extends SvelteComponent>(
});
}

const repository: StoriesRepository<Component> = {
const repository: StoriesRepository<M> = {
stories: new Map(),
};

Expand All @@ -52,7 +52,7 @@ export default <Component extends SvelteComponent>(
props: {
Stories,
repository: () => repository,
} satisfies ComponentProps<StoriesExtractor>,
},
});

unmount(context);
Expand All @@ -74,7 +74,7 @@ export default <Component extends SvelteComponent>(
Stories,
storyContext,
args,
} satisfies ComponentProps<StoryRenderer>,
},
};
};
storyFn.storyName = story.name;
Expand All @@ -91,6 +91,7 @@ export default <Component extends SvelteComponent>(
},
}
: undefined
// TODO: Wait for the response on this case
// storyMeta.rawSource
// ? {
// docs: {
Expand Down
35 changes: 16 additions & 19 deletions src/parser/extract-stories.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import { compile, type Root } from 'svelte/compiler';
import { compile, type Root } from "svelte/compiler";

import type { StoriesFileMeta } from './types.js';
import { walkOnModule } from './walkers/module.js';
import { walkOnInstance } from './walkers/instance.js';
import { walkOnFragment } from './walkers/fragment.js';
import type { StoriesFileMeta } from "./types.js";
import { walkOnModule } from "./walkers/module.js";
import { walkOnFragment } from "./walkers/fragment.js";

/**
* Parse raw stories file component in Svelte format,
* and extract the most stories file meta,
* which are required to generate `StoryFn's` for `@storybook/svelte` components.
*/
export function extractStories(rawSource: string): StoriesFileMeta {
const { ast }: { ast: Root } = compile(rawSource, { modernAst: true });
const { module, instance, fragment } = ast;
const { ast }: { ast: Root } = compile(rawSource, { modernAst: true });
const { module, fragment } = ast;

const moduleMeta = walkOnModule(module);
const instanceMeta = walkOnInstance(instance);
const fragmentMeta = walkOnFragment({
fragment,
rawSource,
addonComponentName: instanceMeta.addonComponentName,
});
const moduleMeta = walkOnModule(module);
const fragmentMeta = walkOnFragment({
fragment,
rawSource,
addonComponentName: moduleMeta.addonComponentName,
});

return {
module: moduleMeta,
instance: instanceMeta,
fragment: fragmentMeta,
};
return {
module: moduleMeta,
fragment: fragmentMeta,
};
}
64 changes: 32 additions & 32 deletions src/parser/types.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
import type { Meta } from '@storybook/svelte';
import type { Meta } from "@storybook/svelte";

export const ADDON_COMPONENT_NAME = 'Story';
import type { defineMeta } from "../index.js";

export const ADDON_FN_NAME = "defineMeta";
export const ADDON_COMPONENT_NAME = "Story";
export const ADDON_META_VAR_NAME = "meta";

/**
* Data extracted from the static analytic of a single stories file - `*.stories.svelte`.
*/
export interface StoriesFileMeta {
module: ModuleMeta;
instance: InstanceMeta;
fragment: FragmentMeta;
}

/**
* Meta extracted from static analysis of the instance tag _(`<script>`)_
* from the single stories file - `*.stories.svelte`.
*/
export interface InstanceMeta extends Pick<Meta, 'id' | 'title' | 'tags'> {
// Can be overriden with `import { Story as S } ...`
addonComponentName: typeof ADDON_COMPONENT_NAME | (string & {});
module: ModuleMeta;
fragment: FragmentMeta;
}

/**
* Meta extracted from static analysis of the module tag _(`<script context="module">`)_
* from the single stories file - `*.stories.svelte`.
*/
export interface ModuleMeta extends Pick<Meta, 'id' | 'title' | 'tags'> {
description?: string;
export interface ModuleMeta extends Pick<Meta, "tags"> {
description?: string;
// NOTE: Why? It could be overriden with `import { defineMeta as d } ...`
addonFnName: typeof defineMeta.name | (string & {});
// NOTE: Why? It could be overriden with `const { Story: S } ...`
addonComponentName: typeof ADDON_COMPONENT_NAME | (string & {});
// NOTE: Why? It could be overriden with `const { meta: m } ...`
addonMetaVarName: typeof ADDON_META_VAR_NAME | (string & {});
}

/**
* Meta extracted from static analysis of the `Fragment` _(html-like code)_
* from the single stories file - `*.stories.svelte`.
*/
export interface FragmentMeta {
stories: Record<StoryMeta['id'], StoryMeta>;
stories: Record<StoryMeta["id"], StoryMeta>;
}

/**
* Meta extracted from static analysis of the single <Story /> component
* in the stories file - `*.stories.svelte`.
*/
export interface StoryMeta {
/**
* Id of the story. By default is hashed, otherwise can be overriden.
*/
id: string;
/**
* Name of the story.
* @default "Default"
*/
name: string;
/**
* Description of the story, will display above the sample in docs mode.
*/
description?: string;
/** Raw source for children _(what is inside the <Story>...</Story> tags)_ */
rawSource?: string;
/**
* Id of the story. By default is hashed, otherwise can be overriden.
*/
id: string;
/**
* Name of the story.
* @default "Default"
*/
name: string;
/**
* Description of the story, will display above the sample in docs mode.
*/
description?: string;
/** Raw source for children _(what is inside the <Story>...</Story> tags)_ */
rawSource?: string;
}
53 changes: 0 additions & 53 deletions src/parser/walkers/instance.ts

This file was deleted.

Loading

0 comments on commit 20c926f

Please sign in to comment.