Socket
Socket
Sign inDemoInstall

@storybook/addon-svelte-csf

Package Overview
Dependencies
Maintainers
11
Versions
279
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@storybook/addon-svelte-csf - npm Package Compare versions

Comparing version 5.0.0--canary.181.f05a689.0 to 5.0.0--canary.181.f484f87.0

dist/compiler/transform/appendix/create-code-by-story-map.d.ts

104

dist/compiler/plugin.js

@@ -13,11 +13,11 @@ /**

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';
import { destructureMetaFromDefineMeta } from './transform/define-meta/destructure-meta.js';
import { insertStoryHTMLCommentAsDescription } from './transform/Story/description.js';
import { getNameFromFilename } from '../utils/get-component-name.js';
import { getSvelteAST } from '../utils/parser/ast.js';
import { extractStoriesNodesFromExportDefaultFn } from '../utils/parser/extract/compiled/stories.js';
import { extractCompiledASTNodes } from '../utils/parser/extract/compiled/nodes.js';
import { extractSvelteASTNodes } from '../utils/parser/extract/svelte/nodes.js';
import { updateCompiledStoryProps } from './transform/compiled-story-props.js';
import { getSvelteAST } from '../parser/ast.js';
import { extractStoriesNodesFromExportDefaultFn } from '../parser/extract/compiled/stories.js';
import { extractCompiledASTNodes } from '../parser/extract/compiled/nodes.js';
import { extractSvelteASTNodes } from '../parser/extract/svelte/nodes.js';
export async function plugin() {

@@ -34,72 +34,74 @@ const [{ createFilter }, { loadSvelteConfig }] = await Promise.all([

enforce: 'post',
async transform(code_, filename) {
if (!filter(filename))
async transform(compiledCode, id) {
if (!filter(id))
return undefined;
const compiledAST = this.parse(code_);
let code = new MagicString(code_);
const componentName = getNameFromFilename(filename);
if (!componentName) {
// TODO: make error message more user friendly
// what happened, how to fix
throw new Error(`Failed to extract component name from filename: ${filename}`);
}
let source = fs.readFileSync(filename).toString();
const compiledAST = this.parse(compiledCode);
let magicCompiledCode = new MagicString(compiledCode);
// @ts-expect-error FIXME: `this.originalCode` exists at runtime.
// Need to research if its documented somewhere
let rawCode = this.originalCode ?? fs.readFileSync(id).toString();
if (svelteConfig?.preprocess) {
const processed = await preprocess(source.toString(), svelteConfig.preprocess, {
filename: filename,
const processed = await preprocess(rawCode, svelteConfig.preprocess, {
filename: id,
});
source = processed.code;
rawCode = processed.code;
}
const svelteAST = getSvelteAST({ source, filename });
const svelteNodes = await extractSvelteASTNodes({
const svelteAST = getSvelteAST({ code: rawCode, filename: id });
const svelteASTNodes = await extractSvelteASTNodes({
ast: svelteAST,
filename,
filename: id,
});
const compiledNodes = await extractCompiledASTNodes({
ast: compiledAST,
filename,
filename: id,
});
const extractedCompiledStoriesNodes = await extractStoriesNodesFromExportDefaultFn({
nodes: compiledNodes,
filename,
filename: id,
});
// WARN:
// IMPORTANT! The plugins starts updating the compiled ouput code from the bottom.
// Why? Because once we start updating nodes in the stringified output from the top,
// then other nodes `start` and `end` numbers will not be correct anymore.
// Hence the reason why reversing both arrays with stories _(svelte and compiled)_.
const svelteStories = svelteNodes.storyComponents.toReversed();
const compiledStories = extractedCompiledStoriesNodes.toReversed();
for (const [index, compiled] of Object.entries(compiledStories)) {
insertStoryHTMLCommentAsDescription({
code,
nodes: { svelte: svelteStories[index], compiled },
filename,
});
}
/*
* WARN:
* IMPORTANT! The plugins starts updating the compiled output code from the bottom.
* Why? Because once we start updating nodes in the stringified output from the top,
* then other nodes' `start` and `end` numbers will not be correct anymore.
* Hence the reason why reversing both arrays with stories _(svelte and compiled)_.
*/
const svelteStories = [...svelteASTNodes.storyComponents].reverse();
const compiledStories = [...extractedCompiledStoriesNodes].reverse();
await Promise.all(compiledStories.map((compiled, index) => updateCompiledStoryProps({
code: magicCompiledCode,
componentASTNodes: { svelte: svelteStories[index], compiled },
svelteASTNodes,
filename: id,
originalCode: rawCode,
})));
await destructureMetaFromDefineMeta({
code,
code: magicCompiledCode,
nodes: compiledNodes,
filename,
filename: id,
});
insertDefineMetaJSDocCommentAsDescription({
code,
code: magicCompiledCode,
nodes: {
compiled: compiledNodes,
svelte: svelteNodes,
svelte: svelteASTNodes,
},
filename,
filename: id,
});
removeExportDefault({
code: magicCompiledCode,
nodes: compiledNodes,
filename: id,
});
await createAppendix({
componentName,
code,
code: magicCompiledCode,
nodes: {
compiled: compiledNodes,
svelte: svelteNodes,
svelte: svelteASTNodes,
},
filename,
filename: id,
});
return {
code: code.toString(),
map: code.generateMap({ hires: true, source: filename }),
code: magicCompiledCode.toString(),
map: magicCompiledCode.generateMap({ hires: true, source: id }),
};

@@ -106,0 +108,0 @@ },

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;

import type { Meta, StoryContext as BaseStoryContext, StoryObj } from '@storybook/svelte';
import Story from './renderer/Story.svelte';
import type { ComponentType } from 'svelte';
import Story from './runtime/Story.svelte';
export type { Story };

@@ -9,3 +10,3 @@ export { setTemplate } from './runtime/contexts/template.svelte.js';

};
export type Args<TStory extends ReturnType<typeof defineMeta>['Story']> = TStory extends typeof Story<infer TMeta extends Meta> ? StoryObj<TMeta>['args'] : never;
export type StoryContext<TStory extends ReturnType<typeof defineMeta>['Story']> = TStory extends typeof Story<infer TMeta extends Meta> ? BaseStoryContext<StoryObj<TMeta>['args']> : never;
export type Args<TStory extends ComponentType> = TStory extends typeof Story<infer TMeta extends Meta> ? StoryObj<TMeta>['args'] : never;
export type StoryContext<TStory extends ComponentType> = TStory extends typeof Story<infer TMeta extends Meta> ? BaseStoryContext<StoryObj<TMeta>['args']> : never;

@@ -1,2 +0,2 @@

import Story from './renderer/Story.svelte';
import Story from './runtime/Story.svelte';
export { setTemplate } from './runtime/contexts/template.svelte.js';

@@ -3,0 +3,0 @@ export function defineMeta(meta) {

import fs from 'node:fs/promises';
import { combineTags } from '@storybook/csf';
import { preprocess } from 'svelte/compiler';
import { getSvelteAST } from '../utils/parser/ast.js';
import { extractSvelteASTNodes } from '../utils/parser/extract/svelte/nodes.js';
import { extractMetaPropertiesNodes } from '../utils/parser/extract/meta-properties.js';
import { getMetaIdValue, getMetaTagsValue, getMetaTitleValue, } from '../utils/parser/analyse/meta-properties.js';
import { extractStoryAttributesNodes } from '../utils/parser/extract/svelte/Story-attributes.js';
import { getNameFromStoryAttribute, getTagsFromStoryAttribute, } from '../utils/parser/analyse/Story-attributes.js';
import { getSvelteAST } from '../parser/ast.js';
import { extractSvelteASTNodes } from '../parser/extract/svelte/nodes.js';
import { extractMetaPropertiesNodes } from '../parser/extract/meta-properties.js';
import { extractStoryAttributesNodes } from '../parser/extract/svelte/Story/attributes.js';
import { getMetaIdValue, getMetaTagsValue, getMetaTitleValue, } from '../parser/analyse/meta/properties.js';
import { getTagsFromStoryAttribute } from '../parser/analyse/Story/attributes/tags.js';
import { getStoryIdentifiers } from '../parser/analyse/Story/attributes/identifiers.js';
export const indexer = {
test: /\.svelte$/,
createIndex: async (filename, { makeTitle }) => {
let [source, { loadSvelteConfig }] = await Promise.all([
let [code, { loadSvelteConfig }] = await Promise.all([
fs.readFile(filename, { encoding: 'utf8' }),

@@ -19,22 +20,18 @@ import('@sveltejs/vite-plugin-svelte'),

if (svelteConfig?.preprocess) {
source = (await preprocess(source, svelteConfig.preprocess, {
code = (await preprocess(code, svelteConfig.preprocess, {
filename: filename,
})).code;
}
const svelteAST = getSvelteAST({ source, filename });
const svelteAST = getSvelteAST({ code, filename });
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: ['exportName', 'name', 'tags'],
}));
const metaTitle = metaPropertiesNodes.title

@@ -50,4 +47,5 @@ ? makeTitle(getMetaTitleValue({ node: metaPropertiesNodes.title, filename }))

return storiesAttributesNodes.map((attributeNode) => {
const exportName = getNameFromStoryAttribute({
node: attributeNode.name,
const { exportName, name } = getStoryIdentifiers({
nameNode: attributeNode.name,
exportNameNode: attributeNode.exportName,
filename,

@@ -59,7 +57,5 @@ });

exportName,
// TODO: Ask if this is important to set. If yes, then from what? Story attribute? That's `exportName`.
// name: ...
name,
title: metaTitle,
tags: combineTags(...metaTags, ...getTagsFromStoryAttribute({ node: attributeNode.tags, filename })),
__id: metaId,
};

@@ -66,0 +62,0 @@ });

import type { Meta, StoryObj } from '@storybook/svelte';
import type { StoryName } from '@storybook/types';
export interface StoriesExtractorContextProps<TMeta extends Meta> {
isExtracting: boolean;
register: (story: StoryObj<TMeta>) => void;
register: (story: StoryObj<TMeta> & {
exportName?: string;
}) => void;
}
declare function buildContext<TMeta extends Meta>(props: StoriesExtractorContextProps<TMeta>): {
readonly isExtracting: boolean;
readonly register: (story: StoryObj<TMeta>) => void;
readonly register: (story: StoryObj<TMeta> & {
exportName?: string | undefined;
}) => void;
};
export type StoriesExtractorContext<TMeta extends Meta> = ReturnType<typeof buildContext<TMeta>>;
export type StoriesRepository<TMeta extends Meta> = {
stories: Map<StoryName, StoryObj<TMeta>>;
stories: Map<string, StoryObj<TMeta>>;
};

@@ -18,4 +21,6 @@ export declare function createStoriesExtractorContext<TMeta extends Meta>(repository: StoriesRepository<TMeta>): void;

readonly isExtracting: boolean;
readonly register: (story: StoryObj<TMeta>) => void;
readonly register: (story: StoryObj<TMeta> & {
exportName?: string | undefined;
}) => void;
};
export {};
// WARN: Temporary location. Feel free to move if needed.
// It is likely this file will be removed if we successfully get rid of `StoriesExtractor`.
import { getContext, hasContext, setContext } from 'svelte';
import { storyNameToExportName } from '../../utils/identifier-utils.js';
const CONTEXT_KEY = 'storybook-stories-extractor-context';

@@ -22,3 +23,3 @@ function buildContext(props) {

register: (s) => {
stories.set(s.name, s);
stories.set(s.exportName ?? storyNameToExportName(s.name), s);
},

@@ -25,0 +26,0 @@ });

import type { Meta, StoryObj, StoryContext } from '@storybook/svelte';
import type { StoryName } from '@storybook/types';
interface StoryRendererContextProps<TMeta extends Meta> {
currentStoryName: StoryName | undefined;
currentStoryExportName: string | undefined;
args: StoryObj<TMeta>['args'];

@@ -11,3 +10,3 @@ storyContext: StoryContext<StoryObj<TMeta>['args']>;

readonly storyContext: StoryContext<StoryObj<TMeta>["args"]>;
readonly currentStoryName: string | undefined;
readonly currentStoryExportName: string | undefined;
set: (props: StoryRendererContextProps<TMeta>) => void;

@@ -19,5 +18,5 @@ };

readonly storyContext: StoryContext<StoryObj<TMeta>["args"]>;
readonly currentStoryName: string | undefined;
readonly currentStoryExportName: string | undefined;
set: (props: StoryRendererContextProps<TMeta>) => void;
};
export {};
import { getContext, hasContext, setContext } from 'svelte';
const CONTEXT_KEY = 'storybook-story-renderer-context';
function buildContext(props) {
let currentStoryName = $state(props.currentStoryName);
let currentStoryExportName = $state(props.currentStoryExportName);
let args = $state(props.args);
let storyContext = $state(props.storyContext);
function set(props) {
currentStoryName = props.currentStoryName;
currentStoryExportName = props.currentStoryExportName;
args = props.args;

@@ -19,4 +19,4 @@ storyContext = props.storyContext;

},
get currentStoryName() {
return currentStoryName;
get currentStoryExportName() {
return currentStoryExportName;
},

@@ -28,3 +28,3 @@ set,

const ctx = buildContext({
currentStoryName: undefined,
currentStoryExportName: undefined,
args: {},

@@ -31,0 +31,0 @@ // @ts-expect-error FIXME: I don't know how to satisfy this one

@@ -16,11 +16,15 @@ import { SvelteComponent } from "svelte";

/**
* Id of the story.
*
* Optional, auto-generated from name if not specified.
* Name of the story. Can be omitted if `exportName` is provided.
*/
id?: string | undefined;
name?: string | undefined;
/**
* Name of the story.
* exportName of the story.
* If not provided, it will be generated from the 'name', by converting it to a valid, PascalCased JS variable name.
* eg. 'My story!' -> 'MyStory'
*
* Use this prop to explicitly set the export name of the story. This is useful if you have multiple stories with the names
* that result in duplicate export names like "My story" and "My story!".
* It's also useful for explicitly defining the export that can be imported in MDX docs.
*/
name: string;
exportName?: string | undefined;
/**

@@ -32,2 +36,4 @@ * @deprecrated

/**
* @deprecated
* Is recommended to use `parameters={{ docs: { source: { code: "..." } } }}` instead, to follow Regular CSF.
* WARNING: This is under consideration to be revamped.

@@ -39,2 +45,7 @@ * Ref: https://github.com/storybookjs/addon-svelte-csf/pull/181#issuecomment-2130744977

* By default, sources for an args story are auto-generated.
*
* TODO:
* I am still confused on what is exactly supposed to happen/output when it's a boolean?
* For now this is not implemented, and I've created a warning when it happens.
*
* If source is true, then the source of the story will be used instead.

@@ -41,0 +52,0 @@ * If source is a string, it replaces the source of the story.

@@ -7,3 +7,4 @@ import { SvelteComponent } from "svelte";

Stories: ComponentType;
storyName: string;
exportName: string;
code: string;
args: StoryObj<TMeta>["args"];

@@ -10,0 +11,0 @@ storyContext: StoryContext<TMeta["args"]>;

@@ -1,1 +0,1 @@

export declare function getNameFromFilename(filename: string): string | null;
export declare function getComponentName(filename: string): string;

@@ -1,28 +0,12 @@

// From https://github.com/sveltejs/svelte/blob/8db3e8d0297e052556f0b6dde310ef6e197b8d18/src/compiler/compile/utils/get_name_from_filename.ts
// Copied because it is not exported from the compiler
export function getNameFromFilename(filename) {
if (!filename)
return null;
const parts = filename.split(/[/\\]/).map(encodeURI);
if (parts.length > 1) {
const indexMatch = parts[parts.length - 1].match(/^index(\.\w+)/);
if (indexMatch) {
parts.pop();
parts[parts.length - 1] += indexMatch[1];
}
// FIXME: Unused module. Verify if it can be freely removed
// Copied from https://github.com/sveltejs/svelte/blob/14ddb87c311ff3280dde0ae44b0a0d864ec26353/packages/svelte/src/compiler/phases/2-analyze/index.js#L57-L69
export function getComponentName(filename) {
const parts = filename.split(/[/\\]/);
const basename = parts.pop();
const last_dir = parts.at(-1);
let name = basename.replace(".svelte", "");
if (name === "index" && last_dir && last_dir !== "src") {
name = last_dir;
}
if (!parts)
return null;
const base = parts
.pop()
?.replace(/%/g, 'u')
.replace(/\.[^.]+$/, '')
.replace(/[^a-zA-Z_$0-9]+/g, '_')
.replace(/^_/, '')
.replace(/_$/, '')
.replace(/^(\d)/, '_$1');
if (!base) {
throw new Error(`Could not derive component name from file ${filename}`);
}
return base[0].toUpperCase() + base.slice(1);
return name[0].toUpperCase() + name.slice(1);
}
{
"name": "@storybook/addon-svelte-csf",
"version": "5.0.0--canary.181.f05a689.0",
"version": "5.0.0--canary.181.f484f87.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,6 +40,7 @@ },

"scripts": {
"clean": "rimraf ./dist",
"clean": "rimraf ./dist ./node_modules/.cache ./storybook-static ./svelte-kit ./.vite-inspect",
"build": "svelte-package --input ./src --types",
"prepublish": "pnpm run clean && pnpm run build",
"test": "vitest run",
"test:watch": "vitest watch",
"chromatic": "chromatic --exit-zero-on-changes",

@@ -53,2 +59,4 @@ "coverage": "vitest run --coverage",

"magic-string": "^0.30.1",
"prettier": "^3.3.1",
"prettier-plugin-svelte": "^3.2.4",
"zimmerframe": "^1.1.2"

@@ -58,14 +66,15 @@ },

"@auto-it/released": "^10.32.6",
"@storybook/addon-actions": "^8.1.0",
"@storybook/addon-essentials": "^8.1.0",
"@storybook/addon-interactions": "^8.1.0",
"@storybook/client-logger": "^8.1.0",
"@storybook/csf": "^0.1.5",
"@storybook/addon-actions": "^8.1.6",
"@storybook/addon-essentials": "^8.1.6",
"@storybook/addon-interactions": "^8.1.6",
"@storybook/client-logger": "^8.1.6",
"@storybook/csf": "^0.1.8",
"@storybook/docs-tools": "^8.1.6",
"@storybook/eslint-config-storybook": "^3.1.2",
"@storybook/node-logger": "^8.1.0",
"@storybook/preview-api": "^8.1.0",
"@storybook/svelte": "^8.1.0",
"@storybook/svelte-vite": "^8.1.0",
"@storybook/test": "^8.1.0",
"@storybook/types": "^8.1.0",
"@storybook/node-logger": "^8.1.6",
"@storybook/preview-api": "^8.1.6",
"@storybook/svelte": "^8.1.6",
"@storybook/svelte-vite": "^8.1.6",
"@storybook/test": "^8.1.6",
"@storybook/types": "^8.1.6",
"@sveltejs/package": "^2.2.0",

@@ -75,3 +84,4 @@ "@sveltejs/vite-plugin-svelte": "4.0.0-next.1",

"@types/estree": "^1.0.5",
"@types/node": "^20.12.12",
"@types/node": "^20.14.2",
"@vitest/ui": "^1.6.0",
"auto": "^11.1.1",

@@ -82,6 +92,8 @@ "chromatic": "^6.19.9",

"eslint-plugin-storybook": "^0.6.12",
"jsdom": "^24.0.0",
"prettier": "^3.0.0",
"jsdom": "^24.1.0",
"lodash-es": "^4.17.21",
"prettier": "^3.3.1",
"rimraf": "^5.0.7",
"storybook": "^8.1.0",
"rollup": "^4.18.0",
"storybook": "^8.1.6",
"svelte": "5.0.0-next.136",

@@ -92,2 +104,3 @@ "svelte-check": "^3.5.0",

"vite-plugin-inspect": "^0.8.4",
"vite-plugin-virtual": "^0.3.0",
"vitest": "^1.5.2"

@@ -94,0 +107,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc