From 52fcd77b9b3baf376acea71e0e5119a24474a9a4 Mon Sep 17 00:00:00 2001 From: j3rem1e Date: Wed, 30 Aug 2023 22:52:17 +0200 Subject: [PATCH] Supports for tags in --- src/index.d.ts | 19 ++++- src/parser/extract-stories.test.ts | 118 +++++++++++++++++++++++++++++ src/parser/extract-stories.ts | 56 ++++++++++++++ src/preset/indexer.ts | 2 +- stories/button.stories.svelte | 2 +- 5 files changed, 194 insertions(+), 3 deletions(-) diff --git a/src/index.d.ts b/src/index.d.ts index 141b790..d35ec43 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -54,7 +54,24 @@ interface Slots { /** * Meta. */ -export class Meta extends SvelteComponent & BaseAnnotations> { } +export class Meta extends SvelteComponent< + BaseMeta & BaseAnnotations & { + /** + * Enable the tag 'autodocs'. + * + * @see [Automatic documentation](https://storybook.js.org/docs/svelte/writing-docs/autodocs) + */ + autodocs?: boolean; + /** + * List of tags to add to the stories. + * + * It should be a static array of strings. + * + * @example + * tags={['autodocs']} + */ + tags?: string[]; + }> { } /** * Story. */ diff --git a/src/parser/extract-stories.test.ts b/src/parser/extract-stories.test.ts index fb265a8..494f44c 100644 --- a/src/parser/extract-stories.test.ts +++ b/src/parser/extract-stories.test.ts @@ -229,6 +229,124 @@ describe('extractSource', () => { } `); }); + test('Add tags autodocs', () => { + expect( + extractStories(` + + + + + +
story 1
+
+ `) + ).toMatchInlineSnapshot(` + { + "allocatedIds": [ + "default", + "Story", + "Meta", + ], + "meta": { + "id": undefined, + "tags": [ + "autodocs", + ], + "title": "test", + }, + "stories": { + "Story1": { + "hasArgs": false, + "name": "Story1", + "source": "
story 1
", + "storyId": "test--story-1", + "template": false, + }, + }, + } + `); + }); + test('Add tags', () => { + expect( + extractStories(` + + + + + +
story 1
+
+ `) + ).toMatchInlineSnapshot(` + { + "allocatedIds": [ + "default", + "Story", + "Meta", + ], + "meta": { + "id": undefined, + "tags": [ + "a", + "b", + ], + "title": "test", + }, + "stories": { + "Story1": { + "hasArgs": false, + "name": "Story1", + "source": "
story 1
", + "storyId": "test--story-1", + "template": false, + }, + }, + } + `); + }); + test('Add Only one tag', () => { + expect( + extractStories(` + + + + + +
story 1
+
+ `) + ).toMatchInlineSnapshot(` + { + "allocatedIds": [ + "default", + "Story", + "Meta", + ], + "meta": { + "id": undefined, + "tags": [ + "a", + ], + "title": "test", + }, + "stories": { + "Story1": { + "hasArgs": false, + "name": "Story1", + "source": "
story 1
", + "storyId": "test--story-1", + "template": false, + }, + }, + } + `); + }); test('Duplicate Id', () => { expect( extractStories(` diff --git a/src/parser/extract-stories.ts b/src/parser/extract-stories.ts index 9f7c57f..3b82a5b 100644 --- a/src/parser/extract-stories.ts +++ b/src/parser/extract-stories.ts @@ -17,6 +17,7 @@ interface StoryDef { interface MetaDef { title?: string; id?: string; + tags?: string[]; } interface StoriesDef { @@ -44,6 +45,57 @@ function getStaticAttribute(name: string, node: any): string | undefined { throw new Error(`Attribute ${name} is not static`); } +function getStaticBooleanAttribute(name: string, node: any): boolean | undefined { + // extract the attribute + const attribute = node.attributes.find( + (att: any) => att.type === 'Attribute' && att.name === name + ); + + if (!attribute) { + return undefined; + } + + const { value } = attribute; + + // expect the attribute to be static and a boolean + if (typeof value === 'boolean') { + return value; + } + + throw new Error(`Attribute ${name} is not a static boolean`); +} + +function getMetaTags(node: any): string[] { + + const finalTags = getStaticBooleanAttribute('autodocs', node) ? ["autodocs"] : []; + + const tags = node.attributes.find((att: any) => att.type === 'Attribute' && att.name === 'tags'); + if (tags) { + let valid = false; + + const { value } = tags; + if (value && value.length === 1 ) { + const { type, expression, data } = value[0]; + if (type === 'Text') { + // tags="autodocs" + finalTags.push(data); + valid = true; + } else if (type === 'MustacheTag' && expression.type === 'ArrayExpression') { + // tags={["autodocs"]} + const { elements } = expression; + elements.forEach((e : any) => finalTags.push(e.value)); + valid = true; + } + } + + if (!valid) { + throw new Error('Attribute tags should be a static string array or a string'); + } + } + + return finalTags; +} + /** * Parse a Svelte component and extract stories. * @param component Component Source @@ -143,6 +195,10 @@ export function extractStories(component: string): StoriesDef { meta.title = getStaticAttribute('title', node); meta.id = getStaticAttribute('id', node); + const tags = getMetaTags(node); + if (tags.length > 0) { + meta.tags = tags; + } } }, }); diff --git a/src/preset/indexer.ts b/src/preset/indexer.ts index 4dcdc4b..7026ac9 100644 --- a/src/preset/indexer.ts +++ b/src/preset/indexer.ts @@ -15,7 +15,7 @@ export async function svelteIndexer(fileName, { makeTitle }) { const defs = extractStories(code); return { - meta: { title: makeTitle(defs.meta.title) }, + meta: { title: makeTitle(defs.meta.title), tags: defs.meta.tags }, stories: Object.entries(defs.stories) .filter(([id, story]) => !story.template) .map(([id, story]) => ({ diff --git a/stories/button.stories.svelte b/stories/button.stories.svelte index bf204bd..45bf20f 100644 --- a/stories/button.stories.svelte +++ b/stories/button.stories.svelte @@ -9,7 +9,7 @@ } - +