@storybook/addon-svelte-csf
Advanced tools
Comparing version 5.0.0--canary.181.030a862.0 to 5.0.0--canary.181.0a3e376.0
@@ -13,3 +13,4 @@ /** | ||
import { preprocess } from 'svelte/compiler'; | ||
import { createAppendix } from './transform/compiled/create-appendix.js'; | ||
import { createAppendix } from './transform/create-appendix.js'; | ||
import { removeExportDefault } from './transform/remove-export-default.js'; | ||
import { insertDefineMetaJSDocCommentAsDescription } from './transform/define-meta/description.js'; | ||
@@ -70,4 +71,4 @@ import { destructureMetaFromDefineMeta } from './transform/define-meta/destructure-meta.js'; | ||
// Hence the reason why reversing both arrays with stories _(svelte and compiled)_. | ||
const svelteStories = svelteNodes.storyComponents.toReversed(); | ||
const compiledStories = extractedCompiledStoriesNodes.toReversed(); | ||
const svelteStories = [...svelteNodes.storyComponents].reverse(); | ||
const compiledStories = [...extractedCompiledStoriesNodes].reverse(); | ||
for (const [index, compiled] of Object.entries(compiledStories)) { | ||
@@ -93,2 +94,7 @@ insertStoryHTMLCommentAsDescription({ | ||
}); | ||
removeExportDefault({ | ||
code, | ||
nodes: compiledNodes, | ||
filename, | ||
}); | ||
await createAppendix({ | ||
@@ -95,0 +101,0 @@ componentName, |
import type MagicString from 'magic-string'; | ||
import type { SvelteASTNodes } from '../../../utils/parser/extract/svelte/nodes.js'; | ||
import type { CompiledASTNodes } from '../../../utils/parser/extract/compiled/nodes.js'; | ||
import type { SvelteASTNodes } from '../../../parser/extract/svelte/nodes.js'; | ||
import type { CompiledASTNodes } from '../../../parser/extract/compiled/nodes.js'; | ||
interface Params { | ||
@@ -5,0 +5,0 @@ code: MagicString; |
import type MagicString from 'magic-string'; | ||
import type { CompiledASTNodes } from '../../../utils/parser/extract/compiled/nodes.js'; | ||
import type { CompiledASTNodes } from '../../../parser/extract/compiled/nodes.js'; | ||
interface Params { | ||
@@ -4,0 +4,0 @@ code: MagicString; |
@@ -7,5 +7,2 @@ import { logger } from '@storybook/client-logger'; | ||
const { svelte, compiled } = nodes; | ||
if (!svelte) { | ||
throw new Error('svelte was undefined!' + filename); | ||
} | ||
const { component, comment } = svelte; | ||
@@ -12,0 +9,0 @@ if (!comment) { |
@@ -7,5 +7,7 @@ import fs from 'node:fs/promises'; | ||
import { extractMetaPropertiesNodes } from '../parser/extract/meta-properties.js'; | ||
import { getMetaIdValue, getMetaTagsValue, getMetaTitleValue, } from '../parser/analyse/meta-properties.js'; | ||
import { extractStoryAttributesNodes } from '../parser/extract/svelte/Story-attributes.js'; | ||
import { getNameFromStoryAttribute, getTagsFromStoryAttribute, } from '../parser/analyse/Story-attributes.js'; | ||
import { extractStoryAttributesNodes } from '../parser/extract/svelte/Story/attributes.js'; | ||
import { getMetaIdValue, getMetaTagsValue, getMetaTitleValue, } from '../parser/analyse/meta/properties.js'; | ||
import { getNameFromStoryAttribute } from '../parser/analyse/Story/attributes/name.js'; | ||
import { getTagsFromStoryAttribute } from '../parser/analyse/Story/attributes/tags.js'; | ||
import { storyNameToExportName } from '../utils/identifiers.js'; | ||
export const indexer = { | ||
@@ -26,16 +28,12 @@ test: /\.svelte$/, | ||
const nodes = await extractSvelteASTNodes({ ast: svelteAST, filename }); | ||
const [metaPropertiesNodes, storiesAttributesNodes] = await Promise.all([ | ||
extractMetaPropertiesNodes({ | ||
nodes, | ||
filename, | ||
properties: ['id', 'title', 'tags'], | ||
}), | ||
Promise.all(nodes.storyComponents.map(({ component }) => { | ||
return extractStoryAttributesNodes({ | ||
component: component, | ||
filename, | ||
attributes: ['name', 'tags'], | ||
}); | ||
})), | ||
]); | ||
const metaPropertiesNodes = extractMetaPropertiesNodes({ | ||
nodes, | ||
filename, | ||
properties: ['id', 'title', 'tags'], | ||
}); | ||
const storiesAttributesNodes = nodes.storyComponents.map(({ component }) => extractStoryAttributesNodes({ | ||
component, | ||
filename, | ||
attributes: ['name', 'tags'], | ||
})); | ||
const metaTitle = metaPropertiesNodes.title | ||
@@ -51,3 +49,3 @@ ? makeTitle(getMetaTitleValue({ node: metaPropertiesNodes.title, filename })) | ||
return storiesAttributesNodes.map((attributeNode) => { | ||
const exportName = getNameFromStoryAttribute({ | ||
const name = getNameFromStoryAttribute({ | ||
node: attributeNode.name, | ||
@@ -59,8 +57,6 @@ filename, | ||
importPath: filename, | ||
exportName, | ||
// TODO: Ask if this is important to set. If yes, then from what? Story attribute? That's `exportName`. | ||
// name: ... | ||
exportName: storyNameToExportName(name), | ||
name, | ||
title: metaTitle, | ||
tags: combineTags(...metaTags, ...getTagsFromStoryAttribute({ node: attributeNode.tags, filename })), | ||
__id: metaId, | ||
}; | ||
@@ -67,0 +63,0 @@ }); |
@@ -1,2 +0,2 @@ | ||
import type { FunctionDeclaration, Identifier, ImportSpecifier, Program, VariableDeclaration } from 'estree'; | ||
import type { ExportDefaultDeclaration, FunctionDeclaration, Identifier, ImportSpecifier, Program, VariableDeclaration } from 'estree'; | ||
export interface CompiledASTNodes { | ||
@@ -14,2 +14,7 @@ /** | ||
/** | ||
* Store the `export default declaration`, we will need to remove it later. | ||
* Why? Storybook expects `export default meta`, instead of what `@sveltejs/vite-plugin-svelte` will produce. | ||
*/ | ||
exportDefault: ExportDefaultDeclaration; | ||
/** | ||
* An identifier for the addon's component `<Story />`. | ||
@@ -20,3 +25,3 @@ * It could be destructured with rename - e.g. `const { Story: S } = defineMeta({ ... })` | ||
/** | ||
* | ||
* A function declaration for the main Svelte component which is the `*.stories.svelte` file. | ||
*/ | ||
@@ -23,0 +28,0 @@ storiesFunctionDeclaration: FunctionDeclaration; |
@@ -51,20 +51,18 @@ import pkg from '@storybook/addon-svelte-csf/package.json' with { type: 'json' }; | ||
ExportDefaultDeclaration(node, { state }) { | ||
// NOTE: This may be confusing. | ||
// In the dev mode the export default is different (Identifier to FunctionDeclaration) | ||
if (process.env['NODE_ENV'] !== 'development') { | ||
if (node.declaration.type !== 'FunctionDeclaration') { | ||
throw new Error(`Expected FunctionDeclaration as the default export in the compiled code for stories file: ${filename}`); | ||
} | ||
state.exportDefault = node; | ||
// WARN: This may be confusing. | ||
// In the `NODE_ENV="production"` the export default is different. | ||
// Identifier to a FunctionDeclaration. | ||
if (process.env.NODE_ENV === 'production' && | ||
node.declaration.type === 'FunctionDeclaration' && | ||
isStoriesComponentFn(node.declaration)) { | ||
state.storiesFunctionDeclaration = node.declaration; | ||
} | ||
}, | ||
FunctionDeclaration(node, { state, stop }) { | ||
if (process.env['NODE_ENV'] === 'development') { | ||
if (node.id.name.endsWith('stories')) { | ||
// NOTE: | ||
// Is an `export default function <Component>_stories` - we want this one. | ||
// We will remove the `export default` later | ||
state.storiesFunctionDeclaration = node; | ||
stop(); | ||
} | ||
FunctionDeclaration(node, { state }) { | ||
// WARN: This may be confusing. | ||
// In the `NODE_ENV="development"` the export default is different. | ||
// A `FunctionDeclaration` | ||
if (isStoriesComponentFn(node)) { | ||
state.storiesFunctionDeclaration = node; | ||
} | ||
@@ -74,14 +72,17 @@ }, | ||
walk(ast, state, visitors); | ||
const { defineMetaImport, defineMetaVariableDeclaration, storyIdentifier, storiesFunctionDeclaration, } = state; | ||
const { defineMetaImport, defineMetaVariableDeclaration, exportDefault, storyIdentifier, storiesFunctionDeclaration, } = state; | ||
if (!defineMetaImport) { | ||
throw new Error(`Could not find '${AST_NODES_NAMES.defineMeta}' imported from the "${pkg.name}" in the stories file: ${filename}`); | ||
throw new Error(`Could not find '${AST_NODES_NAMES.defineMeta}' imported from the "${pkg.name}" in the compiled output of stories file: ${filename}`); | ||
} | ||
if (!defineMetaVariableDeclaration) { | ||
throw new Error(`Could not find '${defineMetaImport.local.name}({ ... })' call in the module tag ('<script context="module">') of the stories file: ${filename}`); | ||
throw new Error(`Could not find '${defineMetaImport.local.name}({ ... })' in the compiled output of the stories file: ${filename}`); | ||
} | ||
if (!exportDefault) { | ||
throw new Error(`Could not find 'export default' in the compiled output of the stories file: ${filename}`); | ||
} | ||
if (!storyIdentifier) { | ||
throw new Error(`No story identifier found.`); | ||
throw new Error(`Could not find 'Story' identifier in the compiled output of the stories file: ${filename}`); | ||
} | ||
if (!storiesFunctionDeclaration) { | ||
throw new Error(`No stories function declaration found.`); | ||
throw new Error(`Could not find the stories component '*.stories.svelte' function in the compiled output of the stories file: ${filename}`); | ||
} | ||
@@ -91,2 +92,3 @@ return { | ||
defineMetaVariableDeclaration, | ||
exportDefault, | ||
storyIdentifier, | ||
@@ -96,1 +98,6 @@ storiesFunctionDeclaration, | ||
} | ||
/** | ||
*:The main component function of those stories file _(`*.stories.svelte`)_ will always end up with `_stories`. | ||
* @see {@link "file://./../../../utils/get-component-name.ts"} | ||
*/ | ||
const isStoriesComponentFn = (fnDeclaration) => fnDeclaration.id?.name.endsWith('_stories'); |
@@ -7,4 +7,4 @@ import type { Meta } from '@storybook/svelte'; | ||
nodes: SvelteASTNodes | CompiledASTNodes; | ||
filename: string; | ||
properties: Properties; | ||
filename?: string; | ||
} | ||
@@ -14,3 +14,3 @@ type Result<Properties extends Array<keyof Meta>> = Partial<{ | ||
}>; | ||
export declare function extractMetaPropertiesNodes<const Properties extends Array<keyof Meta>>(options: Options<Properties>): Promise<Result<Properties>>; | ||
export declare function extractMetaPropertiesNodes<const Properties extends Array<keyof Meta>>(options: Options<Properties>): Result<Properties>; | ||
export {}; |
@@ -1,16 +0,13 @@ | ||
export async function extractMetaPropertiesNodes(options) { | ||
const { walk } = await import('zimmerframe'); | ||
export function extractMetaPropertiesNodes(options) { | ||
const { properties } = options; | ||
const objectExpression = getFirstArgumentObjectExpression(options); | ||
const state = {}; | ||
const visitors = { | ||
Property(node, { state }) { | ||
if (node.key.type === 'Identifier' && | ||
properties.includes(node.key.name)) { | ||
state[node.key.name] = node; | ||
} | ||
}, | ||
}; | ||
walk(objectExpression, state, visitors); | ||
return state; | ||
const results = {}; | ||
for (const property of objectExpression.properties) { | ||
if (property.type === 'Property' && | ||
property.key.type === 'Identifier' && | ||
properties.includes(property.key.name)) { | ||
results[property.key.name] = property; | ||
} | ||
} | ||
return results; | ||
} | ||
@@ -17,0 +14,0 @@ function getFirstArgumentObjectExpression(options) { |
/// <reference types="svelte" /> | ||
import type { Comment, Component, Fragment } from 'svelte/compiler'; | ||
import type { extractModuleNodes } from './module-nodes.js'; | ||
interface SvelteASTNodesFragment { | ||
/** | ||
*/ | ||
interface Result { | ||
storyComponents: Array<{ | ||
@@ -22,3 +20,3 @@ comment?: Comment; | ||
*/ | ||
export declare function extractFragmentNodes(params: Params): Promise<SvelteASTNodesFragment>; | ||
export declare function extractFragmentNodes(params: Params): Promise<Result>; | ||
export {}; |
/// <reference types="svelte" /> | ||
import type { Identifier, ImportSpecifier, VariableDeclaration } from 'estree'; | ||
import type { Script } from 'svelte/compiler'; | ||
interface SvelteASTNodesModule { | ||
import type { Root } from 'svelte/compiler'; | ||
interface Result { | ||
/** | ||
@@ -21,4 +21,4 @@ * Import specifier for `defineMeta` imported from this addon package. | ||
} | ||
interface ExtractModuleNodesOptions { | ||
module: Script; | ||
interface Params { | ||
module: Root['module']; | ||
filename?: string; | ||
@@ -31,3 +31,3 @@ } | ||
*/ | ||
export declare function extractModuleNodes(options: ExtractModuleNodesOptions): Promise<SvelteASTNodesModule>; | ||
export declare function extractModuleNodes(options: Params): Promise<Result>; | ||
export {}; |
@@ -13,2 +13,7 @@ import pkg from '@storybook/addon-svelte-csf/package.json' with { type: 'json' }; | ||
const { module, filename } = options; | ||
// TODO: Perhaps we can use some better way to insert error messages? | ||
// String interpolations doesn't feel right if we want to provide a whole example (code snippet). | ||
if (!module) { | ||
throw new Error(`Couldn't find a module tag. Add (<script context="module">) to the stories file: ${filename}`); | ||
} | ||
const { walk } = await import('zimmerframe'); | ||
@@ -15,0 +20,0 @@ const state = {}; |
@@ -10,3 +10,3 @@ /// <reference types="svelte" /> | ||
export type SvelteASTNodes = Awaited<ReturnType<typeof extractModuleNodes>> & Awaited<ReturnType<typeof extractFragmentNodes>>; | ||
interface ExtractSvelteASTNodesOptions { | ||
interface Params { | ||
ast: Root; | ||
@@ -18,3 +18,3 @@ filename?: string; | ||
*/ | ||
export declare function extractSvelteASTNodes(options: ExtractSvelteASTNodesOptions): Promise<SvelteASTNodes>; | ||
export declare function extractSvelteASTNodes(params: Params): Promise<SvelteASTNodes>; | ||
export {}; |
@@ -6,10 +6,5 @@ import { extractModuleNodes } from './module-nodes.js'; | ||
*/ | ||
export async function extractSvelteASTNodes(options) { | ||
const { ast, filename } = options; | ||
export async function extractSvelteASTNodes(params) { | ||
const { ast, filename } = params; | ||
const { module, fragment } = ast; | ||
// TODO: Perhaps we can use some better way to insert error messages? | ||
// String interpolations doesn't feel right if we want to provide a whole example (code snippet). | ||
if (!module) { | ||
throw new Error(`Couldn't find a module tag. Add (<script context="module">) to the stories file: ${filename}`); | ||
} | ||
const moduleNodes = await extractModuleNodes({ module, filename }); | ||
@@ -16,0 +11,0 @@ const fragmentNodes = await extractFragmentNodes({ |
@@ -1,57 +0,29 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
import { describe, it } from 'vitest'; | ||
import { extractSvelteASTNodes } from './nodes.js'; | ||
import { getSvelteAST } from '../../../parser/ast.js'; | ||
describe(extractSvelteASTNodes.name, () => { | ||
it('fails when module tag not found', () => { | ||
it('works with a simple example', ({ expect }) => { | ||
const ast = getSvelteAST({ | ||
source: `<script></script>`, | ||
}); | ||
expect(extractSvelteASTNodes({ ast })).rejects.toThrow(); | ||
}); | ||
it("fails when 'defineMeta' not imported", () => { | ||
const ast = getSvelteAST({ | ||
source: `<script context="module"></script>`, | ||
}); | ||
expect(extractSvelteASTNodes({ ast })).rejects.toThrow(); | ||
}); | ||
it("fails when 'defineMeta' not used", () => { | ||
const ast = getSvelteAST({ | ||
source: ` | ||
<script context="module"> | ||
import { defineMeta } from "@storybook/addon-svelte-csf"; | ||
import { defineMeta } from "@storybook/addon-svelte-csf" | ||
import Button from "./Button.svelte"; | ||
const { Story, meta } = defineMeta({ | ||
component: Button, | ||
}); | ||
</script> | ||
<Story name="Default" /> | ||
<Story name="Playground"> | ||
{#snippet children(args)} | ||
<Button {...args} /> | ||
{/snippet} | ||
</Story> | ||
`, | ||
}); | ||
expect(extractSvelteASTNodes({ ast })).rejects.toThrow(); | ||
}); | ||
it("fails when 'Story' not destructured", () => { | ||
const ast = getSvelteAST({ | ||
source: ` | ||
<script context="module"> | ||
import { defineMeta } from "@storybook/addon-svelte-csf" | ||
defineMeta(); | ||
</script>`, | ||
}); | ||
expect(extractSvelteASTNodes({ ast })).rejects.toThrow(); | ||
}); | ||
it('works when it has valid required snippet', () => { | ||
const ast = getSvelteAST({ | ||
source: ` | ||
<script context="module"> | ||
import { defineMeta } from "@storybook/addon-svelte-csf" | ||
const { Story } = defineMeta(); | ||
</script>`, | ||
}); | ||
expect(extractSvelteASTNodes({ ast })).resolves.not.toThrow(); | ||
}); | ||
it('works on renamed identifiers', () => { | ||
const ast = getSvelteAST({ | ||
source: ` | ||
<script context="module"> | ||
import { defineMeta as dm } from "@storybook/addon-svelte-csf" | ||
const { Story: S, meta: m } = dm(); | ||
</script>`, | ||
}); | ||
expect(extractSvelteASTNodes({ ast })).resolves.not.toThrow(); | ||
}); | ||
}); |
{ | ||
"name": "@storybook/addon-svelte-csf", | ||
"version": "5.0.0--canary.181.030a862.0", | ||
"version": "5.0.0--canary.181.0a3e376.0", | ||
"description": "Allows to write stories in Svelte syntax", | ||
@@ -16,2 +16,3 @@ "keywords": [ | ||
"type": "module", | ||
"packageManager": "pnpm@9.1.3+sha512.7c2ea089e1a6af306409c4fc8c4f0897bdac32b772016196c469d9428f1fe2d5a21daf8ad6512762654ac645b5d9136bb210ec9a00afa8dbc4677843ba362ecd", | ||
"exports": { | ||
@@ -27,2 +28,6 @@ ".": { | ||
}, | ||
"./internal/create-runtime-stories": { | ||
"types": "./dist/runtime/create-runtime-stories.d.ts", | ||
"default": "./dist/runtime/create-runtime-stories.js" | ||
}, | ||
"./package.json": "./package.json" | ||
@@ -35,3 +40,3 @@ }, | ||
"scripts": { | ||
"clean": "rimraf ./dist", | ||
"clean": "rimraf ./dist ./node_modules/.cache ./storybook-static ./svelte-kit ./.vite-inspect", | ||
"build": "svelte-package --input ./src --types", | ||
@@ -74,2 +79,3 @@ "prepublish": "pnpm run clean && pnpm run build", | ||
"@types/node": "^20.12.12", | ||
"@vitest/ui": "^1.6.0", | ||
"auto": "^11.1.1", | ||
@@ -76,0 +82,0 @@ "chromatic": "^6.19.9", |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
102033
91
2248
1
0
34