Skip to content

Commit

Permalink
use function declarations to get storiesFunctionDeclarations instead …
Browse files Browse the repository at this point in the history
…of componentName
  • Loading branch information
JReinhold committed Jun 3, 2024
1 parent 765a067 commit 1550e08
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 45 deletions.
11 changes: 0 additions & 11 deletions src/compiler/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ 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 { moveSourceAttributeToParameters } from './transform/Story/source.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';
import { getComponentName } from '../utils/get-component-name.js';

export async function plugin(): Promise<Plugin> {
const [{ createFilter }, { loadSvelteConfig }] = await Promise.all([
Expand All @@ -45,14 +43,6 @@ export async function plugin(): Promise<Plugin> {
const compiledAST = this.parse(compiledCode);
let magicCompiledCode = new MagicString(compiledCode);

const componentName = getComponentName(id);

if (!componentName) {
// TODO: make error message more user friendly
// what happened, how to fix
throw new Error(`Failed to extract component name from filename: ${id}`);
}

let rawCode = fs.readFileSync(id).toString();

if (svelteConfig?.preprocess) {
Expand Down Expand Up @@ -116,7 +106,6 @@ export async function plugin(): Promise<Plugin> {
filename: id,
});
await createAppendix({
componentName,
code: magicCompiledCode,
nodes: {
compiled: compiledNodes,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { VariableDeclaration } from 'estree';
import type { FunctionDeclaration, VariableDeclaration } from 'estree';

import type { getMetaIdentifier } from '../../../parser/analyse/meta/identifier.js';

interface Params {
componentName: string;
storiesFunctionDeclaration: FunctionDeclaration;
metaIdentifier: ReturnType<typeof getMetaIdentifier>;
filename: string;
}

export function createVariableFromRuntimeStoriesCall(params: Params): VariableDeclaration {
const { componentName, metaIdentifier } = params;
const { storiesFunctionDeclaration, metaIdentifier } = params;

return {
type: 'VariableDeclaration',
Expand All @@ -32,7 +32,7 @@ export function createVariableFromRuntimeStoriesCall(params: Params): VariableDe
arguments: [
{
type: 'Identifier',
name: componentName,
name: storiesFunctionDeclaration.id.name,
},
metaIdentifier,
],
Expand Down
7 changes: 3 additions & 4 deletions src/compiler/transform/create-appendix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type { SvelteASTNodes } from '../../parser/extract/svelte/nodes.js';
import { getStoriesIdentifiers } from '../../parser/analyse/Story/attributes/identifiers.js';

interface Params {
componentName: string;
code: MagicString;
nodes: {
compiled: CompiledASTNodes;
Expand All @@ -23,17 +22,17 @@ interface Params {
}

export async function createAppendix(params: Params) {
const { componentName, code, nodes, filename } = params;
const { code, nodes, filename } = params;
const { compiled, svelte } = nodes;
const { defineMetaVariableDeclaration } = compiled;
const { defineMetaVariableDeclaration, storiesFunctionDeclaration } = compiled;

const storyIdentifiers = await getStoriesIdentifiers({ nodes: svelte, filename });
const metaIdentifier = getMetaIdentifier({
node: defineMetaVariableDeclaration,
filename,
});
const variableFromRuntimeStoriesCall = createVariableFromRuntimeStoriesCall({
componentName,
storiesFunctionDeclaration,
metaIdentifier,
filename,
});
Expand Down
48 changes: 22 additions & 26 deletions src/parser/extract/compiled/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ export async function extractCompiledASTNodes(params: Params): Promise<CompiledA
const { walk } = await import('zimmerframe');

const { ast, filename } = params;
const state: Partial<CompiledASTNodes> = {};
const state: Partial<CompiledASTNodes> & {
potentialStoriesFunctionDeclaration: FunctionDeclaration[];
} = { potentialStoriesFunctionDeclaration: [] };
const visitors: Visitors<Node | Comment, typeof state> = {
ImportDeclaration(node, { state, visit }) {
const { source, specifiers } = node;
Expand Down Expand Up @@ -106,27 +108,28 @@ export async function extractCompiledASTNodes(params: Params): Promise<CompiledA
}
},

FunctionDeclaration(node, { state }) {
state.potentialStoriesFunctionDeclaration.push(node);
},

ExportDefaultDeclaration(node, { state }) {
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 as FunctionDeclaration)
) {
if (node.declaration.type === 'FunctionDeclaration') {
/*
In production, Svelte will compile the component to:
export default COMPONENT_NAME () {...}
*/
state.storiesFunctionDeclaration = node.declaration as FunctionDeclaration;
}
},

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;
} else if (node.declaration.type === 'Identifier') {
/*
In development, Svelte will compile the component to:
function COMPONENT_NAME () {...}
export default COMPONENT_NAME;
*/
const { name } = node.declaration as Identifier;
state.storiesFunctionDeclaration = state.potentialStoriesFunctionDeclaration?.find(
(potential) => potential.id.name === name
);
}
},
};
Expand Down Expand Up @@ -179,10 +182,3 @@ export async function extractCompiledASTNodes(params: Params): Promise<CompiledA
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: FunctionDeclaration) =>
fnDeclaration.id?.name.endsWith('.stories');

0 comments on commit 1550e08

Please sign in to comment.