@scrymore/scry-sbcov 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +410 -0
- package/bin/scry-sbcov.js +3 -0
- package/dist/analyzers/git-analyzer.d.ts +49 -0
- package/dist/analyzers/git-analyzer.d.ts.map +1 -0
- package/dist/analyzers/git-analyzer.js +265 -0
- package/dist/analyzers/git-analyzer.js.map +1 -0
- package/dist/cli/config.d.ts +12 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +197 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +164 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/analyzer.d.ts +19 -0
- package/dist/core/analyzer.d.ts.map +1 -0
- package/dist/core/analyzer.js +117 -0
- package/dist/core/analyzer.js.map +1 -0
- package/dist/core/coverage-calculator.d.ts +38 -0
- package/dist/core/coverage-calculator.d.ts.map +1 -0
- package/dist/core/coverage-calculator.js +335 -0
- package/dist/core/coverage-calculator.js.map +1 -0
- package/dist/core/report-generator.d.ts +10 -0
- package/dist/core/report-generator.d.ts.map +1 -0
- package/dist/core/report-generator.js +477 -0
- package/dist/core/report-generator.js.map +1 -0
- package/dist/core/story-executor.d.ts +22 -0
- package/dist/core/story-executor.d.ts.map +1 -0
- package/dist/core/story-executor.js +379 -0
- package/dist/core/story-executor.js.map +1 -0
- package/dist/detectors/component-detector.d.ts +15 -0
- package/dist/detectors/component-detector.d.ts.map +1 -0
- package/dist/detectors/component-detector.js +632 -0
- package/dist/detectors/component-detector.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/story-parser.d.ts +18 -0
- package/dist/parsers/story-parser.d.ts.map +1 -0
- package/dist/parsers/story-parser.js +353 -0
- package/dist/parsers/story-parser.js.map +1 -0
- package/dist/types/index.d.ts +502 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACzG,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAChH,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACxH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,YAAY,EAEV,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EAGZ,UAAU,EACV,eAAe,EACf,UAAU,EAGV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scry-sbcov - Storybook Story Coverage Analyzer
|
|
3
|
+
*
|
|
4
|
+
* A CLI tool that analyzes React component libraries to identify gaps
|
|
5
|
+
* in Storybook story coverage.
|
|
6
|
+
*/
|
|
7
|
+
// Main analyzer
|
|
8
|
+
export { analyze, analyzeQuick, analyzeFiles } from './core/analyzer.js';
|
|
9
|
+
// Individual modules for advanced usage
|
|
10
|
+
export { detectComponents } from './detectors/component-detector.js';
|
|
11
|
+
export { parseStoryFiles, matchStoryToComponent, getExpectedStoryPath } from './parsers/story-parser.js';
|
|
12
|
+
export { analyzeGitChanges, isFileNew, isFileModified, getFileChangeStatus } from './analyzers/git-analyzer.js';
|
|
13
|
+
export { calculateCoverage, calculateAggregateCoverage, calculateNewCodeCoverage } from './core/coverage-calculator.js';
|
|
14
|
+
export { executeStories, isPlaywrightAvailable } from './core/story-executor.js';
|
|
15
|
+
export { generateReport } from './core/report-generator.js';
|
|
16
|
+
// Configuration
|
|
17
|
+
export { loadConfig, DEFAULT_CONFIG } from './cli/config.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gBAAgB;AAChB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEzE,wCAAwC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACzG,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAChH,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACxH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,gBAAgB;AAChB,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story Parser
|
|
3
|
+
* Parses Storybook story files to extract which components and prop combinations are covered
|
|
4
|
+
*/
|
|
5
|
+
import type { ParsedStoryFile, DetectedComponent, ScryConfig } from '../types/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parse all story files in the project
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseStoryFiles(projectPath: string, config: ScryConfig, verbose?: boolean): Promise<ParsedStoryFile[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Match a story file to a component
|
|
12
|
+
*/
|
|
13
|
+
export declare function matchStoryToComponent(story: ParsedStoryFile, components: DetectedComponent[]): DetectedComponent | null;
|
|
14
|
+
/**
|
|
15
|
+
* Get expected story file path for a component
|
|
16
|
+
*/
|
|
17
|
+
export declare function getExpectedStoryPath(componentPath: string): string;
|
|
18
|
+
//# sourceMappingURL=story-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/story-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,eAAe,EAEf,iBAAiB,EACjB,UAAU,EACX,MAAM,mBAAmB,CAAC;AAa3B;;GAEG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,UAAU,EAClB,OAAO,UAAQ,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CAwB5B;AAyTD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,iBAAiB,EAAE,GAC9B,iBAAiB,GAAG,IAAI,CAuC1B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAIlE"}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story Parser
|
|
3
|
+
* Parses Storybook story files to extract which components and prop combinations are covered
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { glob } from 'glob';
|
|
8
|
+
// Regular expressions for parsing story files
|
|
9
|
+
const META_REGEX = /export\s+default\s+({[\s\S]*?})\s*(?:as\s+\w+)?;?|const\s+meta\s*(?::\s*Meta(?:<[^>]+>)?)?\s*=\s*({[\s\S]*?})\s*(?:satisfies\s+\w+)?;?/;
|
|
10
|
+
const STORY_EXPORT_REGEX = /export\s+(?:const|let)\s+(\w+)\s*(?::\s*\w+(?:<[^>]+>)?)?\s*=\s*({[\s\S]*?});?|export\s+(?:const|let)\s+(\w+)\s*(?::\s*\w+(?:<[^>]+>)?)?\s*=\s*(\([^)]*\)\s*=>\s*(?:<[\s\S]*?>|[\s\S]*?));?/g;
|
|
11
|
+
const TITLE_REGEX = /title:\s*['"`]([^'"`]+)['"`]/;
|
|
12
|
+
const COMPONENT_REGEX = /component:\s*(\w+)/;
|
|
13
|
+
const COMPONENT_PATH_REGEX = /import\s+(?:{[^}]+}|\*\s+as\s+\w+|\w+)?\s*,?\s*(?:{[^}]+})?\s*from\s+['"`]([^'"`]+)['"`]/g;
|
|
14
|
+
const ARGS_REGEX = /args:\s*({[\s\S]*?})/;
|
|
15
|
+
const PLAY_FUNCTION_REGEX = /play:\s*(?:async\s*)?\(/;
|
|
16
|
+
const TAGS_REGEX = /tags:\s*\[([^\]]*)\]/;
|
|
17
|
+
const NAME_REGEX = /name:\s*['"`]([^'"`]+)['"`]/;
|
|
18
|
+
/**
|
|
19
|
+
* Parse all story files in the project
|
|
20
|
+
*/
|
|
21
|
+
export async function parseStoryFiles(projectPath, config, verbose = false) {
|
|
22
|
+
const storyFiles = [];
|
|
23
|
+
// Find all story files
|
|
24
|
+
const files = await findStoryFiles(projectPath, config.storyPatterns, config.exclude);
|
|
25
|
+
if (verbose) {
|
|
26
|
+
console.log(`Found ${files.length} story files`);
|
|
27
|
+
}
|
|
28
|
+
for (const filePath of files) {
|
|
29
|
+
try {
|
|
30
|
+
const parsed = await parseStoryFile(filePath, projectPath);
|
|
31
|
+
if (parsed) {
|
|
32
|
+
storyFiles.push(parsed);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (verbose) {
|
|
37
|
+
console.warn(`Warning: Failed to parse story file ${filePath}:`, error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return storyFiles;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Find story files matching patterns
|
|
45
|
+
*/
|
|
46
|
+
async function findStoryFiles(projectPath, storyPatterns, excludePatterns) {
|
|
47
|
+
const allFiles = [];
|
|
48
|
+
// Filter out story file patterns from exclude list - we don't want to exclude
|
|
49
|
+
// the very files we're searching for
|
|
50
|
+
const filteredExcludes = excludePatterns.filter(pattern => !pattern.includes('.stories.'));
|
|
51
|
+
for (const pattern of storyPatterns) {
|
|
52
|
+
try {
|
|
53
|
+
const matches = await glob(pattern, {
|
|
54
|
+
cwd: projectPath,
|
|
55
|
+
absolute: true,
|
|
56
|
+
ignore: filteredExcludes,
|
|
57
|
+
});
|
|
58
|
+
allFiles.push(...matches);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
// Glob errors should not prevent other patterns from being processed
|
|
62
|
+
console.warn(`Warning: Failed to glob pattern ${pattern}:`, error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return [...new Set(allFiles)];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Parse a single story file
|
|
69
|
+
*/
|
|
70
|
+
async function parseStoryFile(filePath, projectPath) {
|
|
71
|
+
const code = fs.readFileSync(filePath, 'utf-8');
|
|
72
|
+
const relativePath = path.relative(projectPath, filePath);
|
|
73
|
+
// Extract meta information
|
|
74
|
+
const meta = extractMeta(code, filePath);
|
|
75
|
+
// Extract stories
|
|
76
|
+
const stories = extractStories(code, meta.title);
|
|
77
|
+
if (stories.length === 0) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
filePath,
|
|
82
|
+
relativePath,
|
|
83
|
+
meta,
|
|
84
|
+
stories,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract meta information from story file
|
|
89
|
+
*/
|
|
90
|
+
function extractMeta(code, filePath) {
|
|
91
|
+
let title = null;
|
|
92
|
+
let componentName = null;
|
|
93
|
+
let componentPath = null;
|
|
94
|
+
// Try to find meta object
|
|
95
|
+
const metaMatch = code.match(META_REGEX);
|
|
96
|
+
if (metaMatch) {
|
|
97
|
+
const metaObject = metaMatch[1] || metaMatch[2];
|
|
98
|
+
// Extract title
|
|
99
|
+
const titleMatch = metaObject.match(TITLE_REGEX);
|
|
100
|
+
if (titleMatch) {
|
|
101
|
+
title = titleMatch[1];
|
|
102
|
+
}
|
|
103
|
+
// Extract component name
|
|
104
|
+
const componentMatch = metaObject.match(COMPONENT_REGEX);
|
|
105
|
+
if (componentMatch) {
|
|
106
|
+
componentName = componentMatch[1];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// If no title, derive from file path
|
|
110
|
+
if (!title) {
|
|
111
|
+
title = deriveStoryTitle(filePath);
|
|
112
|
+
}
|
|
113
|
+
// If no component name, derive from title
|
|
114
|
+
if (!componentName && title) {
|
|
115
|
+
const parts = title.split('/');
|
|
116
|
+
componentName = parts[parts.length - 1];
|
|
117
|
+
}
|
|
118
|
+
// Try to find component import path
|
|
119
|
+
const imports = code.matchAll(COMPONENT_PATH_REGEX);
|
|
120
|
+
for (const match of imports) {
|
|
121
|
+
const importPath = match[1]; // Capture group 1 contains the import path
|
|
122
|
+
// Skip if no import path found
|
|
123
|
+
if (!importPath)
|
|
124
|
+
continue;
|
|
125
|
+
// Skip node_modules and storybook imports
|
|
126
|
+
if (!importPath.startsWith('.') && !importPath.startsWith('/'))
|
|
127
|
+
continue;
|
|
128
|
+
if (importPath.includes('@storybook'))
|
|
129
|
+
continue;
|
|
130
|
+
// Check if this might be a component import
|
|
131
|
+
if (componentName && match[0].includes(componentName)) {
|
|
132
|
+
componentPath = importPath;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { title, componentName, componentPath };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Extract stories from story file code
|
|
140
|
+
*/
|
|
141
|
+
function extractStories(code, title) {
|
|
142
|
+
const stories = [];
|
|
143
|
+
const seenExports = new Set();
|
|
144
|
+
// Reset regex lastIndex
|
|
145
|
+
STORY_EXPORT_REGEX.lastIndex = 0;
|
|
146
|
+
let match;
|
|
147
|
+
while ((match = STORY_EXPORT_REGEX.exec(code)) !== null) {
|
|
148
|
+
const exportName = match[1] || match[3];
|
|
149
|
+
// Skip non-story exports
|
|
150
|
+
if (!exportName || exportName === 'default' || exportName === 'meta')
|
|
151
|
+
continue;
|
|
152
|
+
if (seenExports.has(exportName))
|
|
153
|
+
continue;
|
|
154
|
+
seenExports.add(exportName);
|
|
155
|
+
const storyObject = match[2] || match[4];
|
|
156
|
+
// Parse story details
|
|
157
|
+
const story = parseStory(exportName, storyObject, title);
|
|
158
|
+
stories.push(story);
|
|
159
|
+
}
|
|
160
|
+
return stories;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Parse a single story
|
|
164
|
+
*/
|
|
165
|
+
function parseStory(exportName, storyObject, title) {
|
|
166
|
+
// Extract story name (from name property or export name)
|
|
167
|
+
let storyName = exportName;
|
|
168
|
+
const nameMatch = storyObject.match(NAME_REGEX);
|
|
169
|
+
if (nameMatch) {
|
|
170
|
+
storyName = nameMatch[1];
|
|
171
|
+
}
|
|
172
|
+
// Generate story ID
|
|
173
|
+
const storyId = generateStoryId(title, exportName);
|
|
174
|
+
// Extract args
|
|
175
|
+
const args = extractArgs(storyObject);
|
|
176
|
+
// Check for play function
|
|
177
|
+
const hasPlayFunction = PLAY_FUNCTION_REGEX.test(storyObject);
|
|
178
|
+
// Extract tags
|
|
179
|
+
const tags = extractTags(storyObject);
|
|
180
|
+
return {
|
|
181
|
+
exportName,
|
|
182
|
+
storyName,
|
|
183
|
+
storyId,
|
|
184
|
+
args,
|
|
185
|
+
argTypes: {},
|
|
186
|
+
hasPlayFunction,
|
|
187
|
+
tags,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Extract args from story object
|
|
192
|
+
*/
|
|
193
|
+
function extractArgs(storyObject) {
|
|
194
|
+
const argsMatch = storyObject.match(ARGS_REGEX);
|
|
195
|
+
if (!argsMatch)
|
|
196
|
+
return {};
|
|
197
|
+
try {
|
|
198
|
+
// Parse the args object
|
|
199
|
+
const argsStr = argsMatch[1];
|
|
200
|
+
return parseObjectLiteral(argsStr);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return {};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Parse a JavaScript object literal string
|
|
208
|
+
*/
|
|
209
|
+
function parseObjectLiteral(str) {
|
|
210
|
+
const result = {};
|
|
211
|
+
// Remove outer braces and whitespace
|
|
212
|
+
const inner = str.trim().slice(1, -1).trim();
|
|
213
|
+
if (!inner)
|
|
214
|
+
return result;
|
|
215
|
+
// Simple key-value parsing
|
|
216
|
+
const keyValueRegex = /(\w+)\s*:\s*(?:(['"`])([^'"`]*)\2|(\d+(?:\.\d+)?)|(\[[\s\S]*?\])|({[\s\S]*?})|(true|false|null|undefined)|(\w+))/g;
|
|
217
|
+
let match;
|
|
218
|
+
while ((match = keyValueRegex.exec(inner)) !== null) {
|
|
219
|
+
const key = match[1];
|
|
220
|
+
const stringValue = match[3];
|
|
221
|
+
const numericValue = match[4];
|
|
222
|
+
const arrayValue = match[5];
|
|
223
|
+
const objectValue = match[6];
|
|
224
|
+
const literalValue = match[7];
|
|
225
|
+
const identifierValue = match[8];
|
|
226
|
+
if (stringValue !== undefined) {
|
|
227
|
+
result[key] = stringValue;
|
|
228
|
+
}
|
|
229
|
+
else if (numericValue !== undefined) {
|
|
230
|
+
result[key] = parseFloat(numericValue);
|
|
231
|
+
}
|
|
232
|
+
else if (arrayValue !== undefined) {
|
|
233
|
+
try {
|
|
234
|
+
result[key] = JSON.parse(arrayValue.replace(/'/g, '"'));
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
result[key] = arrayValue;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else if (objectValue !== undefined) {
|
|
241
|
+
result[key] = parseObjectLiteral(objectValue);
|
|
242
|
+
}
|
|
243
|
+
else if (literalValue !== undefined) {
|
|
244
|
+
if (literalValue === 'true')
|
|
245
|
+
result[key] = true;
|
|
246
|
+
else if (literalValue === 'false')
|
|
247
|
+
result[key] = false;
|
|
248
|
+
else if (literalValue === 'null')
|
|
249
|
+
result[key] = null;
|
|
250
|
+
else
|
|
251
|
+
result[key] = undefined;
|
|
252
|
+
}
|
|
253
|
+
else if (identifierValue !== undefined) {
|
|
254
|
+
// Reference to another variable - keep as string
|
|
255
|
+
result[key] = `[${identifierValue}]`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Extract tags from story object
|
|
262
|
+
*/
|
|
263
|
+
function extractTags(storyObject) {
|
|
264
|
+
const tagsMatch = storyObject.match(TAGS_REGEX);
|
|
265
|
+
if (!tagsMatch)
|
|
266
|
+
return [];
|
|
267
|
+
try {
|
|
268
|
+
const tagsStr = tagsMatch[1];
|
|
269
|
+
const tags = [];
|
|
270
|
+
const tagRegex = /['"`]([^'"`]+)['"`]/g;
|
|
271
|
+
let match;
|
|
272
|
+
while ((match = tagRegex.exec(tagsStr)) !== null) {
|
|
273
|
+
tags.push(match[1]);
|
|
274
|
+
}
|
|
275
|
+
return tags;
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Generate story ID from title and export name
|
|
283
|
+
*/
|
|
284
|
+
function generateStoryId(title, exportName) {
|
|
285
|
+
const titlePart = title
|
|
286
|
+
? title.toLowerCase().replace(/\s+/g, '-').replace(/\//g, '-')
|
|
287
|
+
: 'stories';
|
|
288
|
+
const namePart = exportName
|
|
289
|
+
.replace(/([A-Z])/g, (_, letter, index) => (index > 0 ? '-' : '') + letter.toLowerCase())
|
|
290
|
+
.replace(/^-/, '');
|
|
291
|
+
return `${titlePart}--${namePart}`;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Derive story title from file path
|
|
295
|
+
*/
|
|
296
|
+
function deriveStoryTitle(filePath) {
|
|
297
|
+
const basename = path.basename(filePath)
|
|
298
|
+
.replace(/\.stories\.(tsx?|jsx?|mdx?)$/, '')
|
|
299
|
+
.replace(/([A-Z])/g, ' $1')
|
|
300
|
+
.trim();
|
|
301
|
+
const dirname = path.dirname(filePath);
|
|
302
|
+
const parentDir = path.basename(dirname);
|
|
303
|
+
if (parentDir && parentDir !== 'src' && parentDir !== 'components') {
|
|
304
|
+
return `${parentDir}/${basename}`;
|
|
305
|
+
}
|
|
306
|
+
return basename;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Match a story file to a component
|
|
310
|
+
*/
|
|
311
|
+
export function matchStoryToComponent(story, components) {
|
|
312
|
+
// Strategy 1: Direct component name match
|
|
313
|
+
if (story.meta.componentName) {
|
|
314
|
+
const byName = components.find(c => c.componentName === story.meta.componentName);
|
|
315
|
+
if (byName)
|
|
316
|
+
return byName;
|
|
317
|
+
}
|
|
318
|
+
// Strategy 2: File naming convention
|
|
319
|
+
const storyBaseName = path.basename(story.filePath)
|
|
320
|
+
.replace(/\.stories\.(tsx?|jsx?|mdx?)$/, '');
|
|
321
|
+
const byFileName = components.find(c => {
|
|
322
|
+
const componentBaseName = path.basename(c.filePath).replace(/\.(tsx?|jsx?)$/, '');
|
|
323
|
+
return componentBaseName === storyBaseName;
|
|
324
|
+
});
|
|
325
|
+
if (byFileName)
|
|
326
|
+
return byFileName;
|
|
327
|
+
// Strategy 3: Title convention
|
|
328
|
+
if (story.meta.title) {
|
|
329
|
+
const titleParts = story.meta.title.split('/');
|
|
330
|
+
const titleComponentName = titleParts[titleParts.length - 1];
|
|
331
|
+
const byTitle = components.find(c => c.componentName === titleComponentName);
|
|
332
|
+
if (byTitle)
|
|
333
|
+
return byTitle;
|
|
334
|
+
}
|
|
335
|
+
// Strategy 4: Directory proximity
|
|
336
|
+
const storyDir = path.dirname(story.filePath);
|
|
337
|
+
const sameDir = components.find(c => {
|
|
338
|
+
const componentDir = path.dirname(c.filePath);
|
|
339
|
+
return componentDir === storyDir;
|
|
340
|
+
});
|
|
341
|
+
if (sameDir)
|
|
342
|
+
return sameDir;
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Get expected story file path for a component
|
|
347
|
+
*/
|
|
348
|
+
export function getExpectedStoryPath(componentPath) {
|
|
349
|
+
const ext = path.extname(componentPath);
|
|
350
|
+
const base = componentPath.slice(0, -ext.length);
|
|
351
|
+
return `${base}.stories${ext}`;
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=story-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story-parser.js","sourceRoot":"","sources":["../../src/parsers/story-parser.ts"],"names":[],"mappings":"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"}
|