diff --git a/ERRORS.md b/ERRORS.md
new file mode 100644
index 00000000..1c6d7bf0
--- /dev/null
+++ b/ERRORS.md
@@ -0,0 +1,125 @@
+# Errors
+
+List of errors that can be thrown by this addon.
+
+## `PARSER_EXTRACT_SVELTE`
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_1`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_2`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_3`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_4`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_5`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_6`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_7`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_SVELTE_8`
+
+
+
+## `PARSER_EXTRACT_COMPILED`
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_COMPILED_1`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_COMPILED_2`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_COMPILED_3`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_COMPILED_4`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_COMPILED_5`
+
+
+
+### `SB_SVELTE_CSF_PARSER_EXTRACT_COMPILED_6`
+
+## `PARSER_ANALYSE_DEFINE_META`
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_DEFINE_META_1`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_DEFINE_META_2`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_DEFINE_META_3`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_DEFINE_META_4`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_DEFINE_META_5`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_DEFINE_META_6`
+
+## `PARSER_ANALYSE_STORY`
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_STORY_1`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_STORY_2`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_STORY_3`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_STORY_4`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_STORY_5`
+
+
+
+### `SB_SVELTE_CSF_PARSER_ANALYSE_STORY_6`
+
+
+
+## `COMPILER`
+
+### `SB_SVELTE_CSF_COMPILER_1`
+
+
+
+### `SB_SVELTE_CSF_COMPILER_2`
+
+
+
+### `SB_SVELTE_CSF_COMPILER_3`
+
+
diff --git a/src/indexer/index.ts b/src/indexer/index.ts
index 509f5b22..9d151737 100644
--- a/src/indexer/index.ts
+++ b/src/indexer/index.ts
@@ -70,6 +70,7 @@ export const indexer: Indexer = {
attributes: ['exportName', 'name', 'tags'],
});
const { exportName, name } = getStoryIdentifiers({
+ component,
nameNode: attributeNode.name,
exportNameNode: attributeNode.exportName,
filename,
diff --git a/src/parser/analyse/story/attributes/identifiers.test.ts b/src/parser/analyse/story/attributes/identifiers.test.ts
index 5172c2c5..2106af34 100644
--- a/src/parser/analyse/story/attributes/identifiers.test.ts
+++ b/src/parser/analyse/story/attributes/identifiers.test.ts
@@ -77,7 +77,10 @@ describe(getStoryIdentifiers.name, () => {
filename: 'invalid.stories.svelte',
})
).toThrowErrorMatchingInlineSnapshot(
- `[Error: Missing 'name' or 'exportName' prop in a definition in the 'invalid.stories.svelte' file. All stories must either have a 'name' or an 'exportName' prop.]`
+ `
+ [SB_SVELTE_CSF_PARSER_ANALYSE_STORY_0004 (NoStoryIdentifierError): Missing 'name' or 'exportName' attribute (prop) in a '' definition in the stories file: 'file:///Users/xeho91/Nextcloud/Projects/oss/addon-svelte-csf/invalid.stories.svelte'.
+ All stories must either have a 'name' or an 'exportName' prop.]
+ `
);
});
@@ -177,9 +180,11 @@ describe(getStoryIdentifiers.name, () => {
})
).toThrowErrorMatchingInlineSnapshot(
`
- [Error: Invalid exportName 'default' found in component in 'invalid.stories.svelte'.
- exportName must be a valid JavaScript variable name. It must start with a letter, $ or _, followed by letters, numbers, $ or _.
- Reserved words like 'default' are also not allowed (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words)]
+ [SB_SVELTE_CSF_PARSER_ANALYSE_STORY_0005 (InvalidStoryExportNameError): Invalid attribute 'exportName' value 'default' found in '' component inside stories file: file:///Users/xeho91/Nextcloud/Projects/oss/addon-svelte-csf/invalid.stories.svelte
+
+ 'exportName' alue must be a valid JavaScript variable name.
+ It must start with a letter, $ or _, followed by letters, numbers, $ or _.
+ Reserved words like 'default' are also not allowed (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words)]
`
);
});
@@ -244,11 +249,13 @@ describe(getStoriesIdentifiers.name, () => {
})
).toThrowErrorMatchingInlineSnapshot(
`
- [Error: Duplicate exportNames found between two definitions in 'duplicate-identifiers.stories.svelte':
+ [SB_SVELTE_CSF_PARSER_ANALYSE_STORY_0006 (DuplicateStoryIdentifiersError): Duplicate exportNames found between two '' definitions in stories file: file:///Users/xeho91/Nextcloud/Projects/oss/addon-svelte-csf/duplicate-identifiers.stories.svelte
+
First instance:
Second instance:
- This can happen when 'exportName' is implicitly derived by 'name'. Complex names will be simplified to a PascalCased, valid JavaScript variable name,
+ This can happen when 'exportName' is implicitly derived by 'name'.
+ Complex names will be simplified to a PascalCased, valid JavaScript variable name,
eg. 'Some story name!!' will be converted to 'SomeStoryName'.
You can fix this collision by providing a unique 'exportName' prop with .]
`
@@ -275,11 +282,13 @@ describe(getStoriesIdentifiers.name, () => {
})
).toThrowErrorMatchingInlineSnapshot(
`
- [Error: Duplicate exportNames found between two definitions in 'duplicate-identifiers.stories.svelte':
+ [SB_SVELTE_CSF_PARSER_ANALYSE_STORY_0006 (DuplicateStoryIdentifiersError): Duplicate exportNames found between two '' definitions in stories file: file:///Users/xeho91/Nextcloud/Projects/oss/addon-svelte-csf/duplicate-identifiers.stories.svelte
+
First instance:
Second instance:
- This can happen when 'exportName' is implicitly derived by 'name'. Complex names will be simplified to a PascalCased, valid JavaScript variable name,
+ This can happen when 'exportName' is implicitly derived by 'name'.
+ Complex names will be simplified to a PascalCased, valid JavaScript variable name,
eg. 'Some story name!!' will be converted to 'SomeStoryName'.
You can fix this collision by providing a unique 'exportName' prop with .]
`
diff --git a/src/parser/analyse/story/attributes/identifiers.ts b/src/parser/analyse/story/attributes/identifiers.ts
index 3196f5fc..0028993c 100644
--- a/src/parser/analyse/story/attributes/identifiers.ts
+++ b/src/parser/analyse/story/attributes/identifiers.ts
@@ -1,11 +1,15 @@
-import dedent from 'dedent';
-import type { Attribute } from 'svelte/compiler';
+import type { Attribute, Component } from 'svelte/compiler';
import { getStringValueFromAttribute } from '../attributes';
import type { SvelteASTNodes } from '#parser/extract/svelte/nodes';
import { extractStoryAttributesNodes } from '#parser/extract/svelte/story/attributes';
import { isValidVariableName, storyNameToExportName } from '#utils/identifier-utils';
+import {
+ DuplicateStoryIdentifiersError,
+ InvalidStoryExportNameError,
+ NoStoryIdentifierError,
+} from '#utils/error/parser/analyse/story';
type StoryIdentifiers = {
exportName: string;
@@ -16,31 +20,39 @@ interface GetIdentifiersParams {
nameNode?: Attribute | undefined;
exportNameNode?: Attribute | undefined;
filename?: string;
+ component: Component;
}
export function getStoryIdentifiers(options: GetIdentifiersParams): StoryIdentifiers {
- const { nameNode, exportNameNode, filename } = options;
+ const { nameNode, exportNameNode, filename, component } = options;
let exportName = getStringValueFromAttribute({
node: exportNameNode,
filename,
+ component,
+ });
+ const name = getStringValueFromAttribute({
+ node: nameNode,
+ filename,
+ component,
});
- const name = getStringValueFromAttribute({ node: nameNode, filename });
if (!exportName) {
if (!name) {
- throw new Error(
- `Missing 'name' or 'exportName' prop in a definition in the '${filename}' file. All stories must either have a 'name' or an 'exportName' prop.`
- );
+ throw new NoStoryIdentifierError({
+ component,
+ filename,
+ });
}
exportName = storyNameToExportName(name);
}
if (!isValidVariableName(exportName)) {
- throw new Error(dedent`Invalid exportName '${exportName}' found in component in '${filename}'.
- exportName must be a valid JavaScript variable name. It must start with a letter, $ or _, followed by letters, numbers, $ or _.
- Reserved words like 'default' are also not allowed (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words)
- `);
+ throw new InvalidStoryExportNameError({
+ filename,
+ component,
+ value: exportName,
+ });
}
return {
@@ -70,6 +82,7 @@ export function getStoriesIdentifiers(params: GetStoriesIdentifiersParams): Stor
exportNameNode: exportName,
nameNode: name,
filename,
+ component: story.component,
});
const duplicateIdentifiers = allIdentifiers.find(
@@ -77,14 +90,11 @@ export function getStoriesIdentifiers(params: GetStoriesIdentifiersParams): Stor
);
if (duplicateIdentifiers) {
- throw new Error(dedent`Duplicate exportNames found between two definitions in '${filename}':
- First instance:
- Second instance:
-
- This can happen when 'exportName' is implicitly derived by 'name'. Complex names will be simplified to a PascalCased, valid JavaScript variable name,
- eg. 'Some story name!!' will be converted to 'SomeStoryName'.
- You can fix this collision by providing a unique 'exportName' prop with .
- `);
+ throw new DuplicateStoryIdentifiersError({
+ filename,
+ identifiers,
+ duplicateIdentifiers,
+ });
}
allIdentifiers.push(identifiers);
diff --git a/src/utils/error/parser/analyse/define-meta.ts b/src/utils/error/parser/analyse/define-meta.ts
index 329b8148..dbe09c30 100644
--- a/src/utils/error/parser/analyse/define-meta.ts
+++ b/src/utils/error/parser/analyse/define-meta.ts
@@ -12,7 +12,7 @@ export class InvalidComponentValueError extends StorybookSvelteCSFError {
filename,
componentProperty,
}: {
- filename: StorybookSvelteCSFError['storiesFilename'];
+ filename: StorybookSvelteCSFError['filename'];
componentProperty: InvalidComponentValueError['componentProperty'];
}) {
super({ filename });
@@ -41,7 +41,7 @@ export class NoDestructuredDefineMetaCallError extends StorybookSvelteCSFError {
filename,
defineMetaVariableDeclarator,
}: {
- filename: StorybookSvelteCSFError['storiesFilename'];
+ filename: StorybookSvelteCSFError['filename'];
defineMetaVariableDeclarator: NoDestructuredDefineMetaCallError['defineMetaVariableDeclarator'];
}) {
super({ filename });
@@ -68,7 +68,7 @@ export class NoMetaIdentifierFoundError extends StorybookSvelteCSFError {
readonly category = StorybookSvelteCSFError.CATEGORY.parserAnalyseDefineMeta;
readonly code = 3;
- constructor(filename: StorybookSvelteCSFError['storiesFilename']) {
+ constructor(filename: StorybookSvelteCSFError['filename']) {
super({ filename });
}
@@ -97,7 +97,7 @@ export class NoStringLiteralError extends StorybookSvelteCSFError {
filename,
property,
}: {
- filename: StorybookSvelteCSFError['storiesFilename'];
+ filename: StorybookSvelteCSFError['filename'];
property: NoStringLiteralError['property'];
}) {
super({ filename });
@@ -126,7 +126,7 @@ export class NoArrayExpressionError extends StorybookSvelteCSFError {
filename,
property,
}: {
- filename: StorybookSvelteCSFError['storiesFilename'];
+ filename: StorybookSvelteCSFError['filename'];
property: NoArrayExpressionError['property'];
}) {
super({ filename });
@@ -157,7 +157,7 @@ export class ArrayElementNotStringError extends StorybookSvelteCSFError {
property,
element,
}: {
- filename: StorybookSvelteCSFError['storiesFilename'];
+ filename: StorybookSvelteCSFError['filename'];
property: ArrayElementNotStringError['property'];
element: ArrayElementNotStringError['element'];
}) {
diff --git a/src/utils/error/parser/analyse/story.ts b/src/utils/error/parser/analyse/story.ts
index 63b9dc63..dbc16b2b 100644
--- a/src/utils/error/parser/analyse/story.ts
+++ b/src/utils/error/parser/analyse/story.ts
@@ -3,6 +3,7 @@ import type { Attribute } from 'svelte/compiler';
import { StorybookSvelteCSFError } from '#utils/error';
import type { ArrayExpression, Literal } from 'estree';
+import type { getStoryIdentifiers } from '#parser/analyse/story/attributes/identifiers';
export class AttributeNotStringError extends StorybookSvelteCSFError {
readonly category = StorybookSvelteCSFError.CATEGORY.parserAnalyseStory;
@@ -123,3 +124,91 @@ export class AttributeNotArrayOfStringsError extends StorybookSvelteCSFError {
`;
}
}
+
+export class NoStoryIdentifierError extends StorybookSvelteCSFError {
+ readonly category = StorybookSvelteCSFError.CATEGORY.parserAnalyseStory;
+ readonly code = 4;
+
+ constructor({
+ filename,
+ component,
+ }: {
+ filename: StorybookSvelteCSFError['filename'];
+ component: NonNullable;
+ }) {
+ super({ component, filename });
+ }
+
+ template(): string {
+ return dedent`
+ Missing 'name' or 'exportName' attribute (prop) in a '' definition in the stories file: '${this.filepathURL}'.
+ All stories must either have a 'name' or an 'exportName' prop.
+ `;
+ }
+}
+
+export class InvalidStoryExportNameError extends StorybookSvelteCSFError {
+ readonly category = StorybookSvelteCSFError.CATEGORY.parserAnalyseStory;
+ readonly code = 5;
+
+ public value: string;
+
+ constructor({
+ filename,
+ component,
+ value,
+ }: {
+ filename: StorybookSvelteCSFError['filename'];
+ component: NonNullable;
+ value: InvalidStoryExportNameError['value'];
+ }) {
+ super({ component, filename });
+ this.value = value;
+ }
+
+ template(): string {
+ return dedent`
+ Invalid attribute 'exportName' value '${this.value}' found in '' component inside stories file: ${this.filepathURL}
+
+ 'exportName' alue must be a valid JavaScript variable name.
+ It must start with a letter, $ or _, followed by letters, numbers, $ or _.
+ Reserved words like 'default' are also not allowed (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words)
+ `;
+ }
+}
+
+export class DuplicateStoryIdentifiersError extends StorybookSvelteCSFError {
+ readonly category = StorybookSvelteCSFError.CATEGORY.parserAnalyseStory;
+ readonly code = 6;
+
+ public identifiers: ReturnType;
+ public duplicateIdentifiers: NonNullable>;
+
+ constructor({
+ filename,
+ identifiers,
+ duplicateIdentifiers,
+ }: {
+ filename: StorybookSvelteCSFError['filename'];
+ identifiers: DuplicateStoryIdentifiersError['identifiers'];
+ duplicateIdentifiers: DuplicateStoryIdentifiersError['duplicateIdentifiers'];
+ }) {
+ super({ filename });
+ this.identifiers = identifiers;
+ this.duplicateIdentifiers = duplicateIdentifiers;
+ }
+
+ template(): string {
+ return dedent`
+ Duplicate exportNames found between two '' definitions in stories file: ${this.filepathURL}
+
+ First instance:
+ Second instance:
+
+ This can happen when 'exportName' is implicitly derived by 'name'.
+ Complex names will be simplified to a PascalCased, valid JavaScript variable name,
+ eg. 'Some story name!!' will be converted to 'SomeStoryName'.
+ You can fix this collision by providing a unique 'exportName' prop with .
+ `;
+ }
+}