0
# Story Enhancement
1
2
Add metadata, source code information, and descriptions to CSF files for documentation and development tooling integration. This module provides utilities to enrich stories with additional context and information.
3
4
## Capabilities
5
6
### CSF Enhancement
7
8
Enhance CSF files with source code and description metadata for better documentation and tooling support.
9
10
```typescript { .api }
11
/**
12
* Enhance a CSF file with metadata from its source
13
* @param csf - Target CSF file to enhance
14
* @param csfSource - Source CSF file to extract metadata from
15
* @param options - Enhancement options
16
*/
17
function enrichCsf(
18
csf: CsfFile,
19
csfSource: CsfFile,
20
options?: EnrichCsfOptions
21
): void;
22
23
interface EnrichCsfOptions {
24
/** Skip adding source code information to stories */
25
disableSource?: boolean;
26
/** Skip adding description information from comments */
27
disableDescription?: boolean;
28
}
29
```
30
31
**Usage Examples:**
32
33
```typescript
34
import { loadCsf, enrichCsf } from "@storybook/csf-tools";
35
36
// Load source CSF file
37
const sourceCsf = loadCsf(sourceCode, {
38
fileName: 'Button.stories.ts',
39
makeTitle: (title) => title
40
}).parse();
41
42
// Load target CSF file (for enhancement)
43
const targetCsf = loadCsf(targetCode, {
44
fileName: 'Button.stories.ts',
45
makeTitle: (title) => title
46
}).parse();
47
48
// Enhance target with source metadata
49
enrichCsf(targetCsf, sourceCsf, {
50
disableSource: false,
51
disableDescription: false
52
});
53
```
54
55
### Story-Level Enhancement
56
57
Enhance individual stories with metadata and source information.
58
59
```typescript { .api }
60
/**
61
* Enhance a specific story with metadata from its source
62
* @param csf - Target CSF file containing the story
63
* @param csfSource - Source CSF file to extract metadata from
64
* @param key - Export name of the story to enhance
65
* @param options - Enhancement options
66
*/
67
function enrichCsfStory(
68
csf: CsfFile,
69
csfSource: CsfFile,
70
key: string,
71
options?: EnrichCsfOptions
72
): void;
73
```
74
75
**Usage Examples:**
76
77
```typescript
78
// Enhance only specific stories
79
enrichCsfStory(targetCsf, sourceCsf, 'Primary', {
80
disableSource: false,
81
disableDescription: false
82
});
83
84
enrichCsfStory(targetCsf, sourceCsf, 'Secondary');
85
```
86
87
### Meta Enhancement
88
89
Enhance the meta object (default export) with component-level metadata.
90
91
```typescript { .api }
92
/**
93
* Enhance the meta object with component-level metadata
94
* @param csf - Target CSF file containing the meta
95
* @param csfSource - Source CSF file to extract metadata from
96
* @param options - Enhancement options
97
*/
98
function enrichCsfMeta(
99
csf: CsfFile,
100
csfSource: CsfFile,
101
options?: EnrichCsfOptions
102
): void;
103
```
104
105
### Source Code Extraction
106
107
Extract source code from AST nodes for documentation purposes.
108
109
```typescript { .api }
110
/**
111
* Extract source code from an AST node
112
* @param node - AST node to extract source from
113
* @returns Generated source code string
114
*/
115
function extractSource(node: t.Node): string;
116
```
117
118
**Usage Examples:**
119
120
```typescript
121
import { extractSource } from "@storybook/csf-tools";
122
123
// Extract source from a story export
124
const storyExport = csfFile.getStoryExport('Primary');
125
const sourceCode = extractSource(storyExport);
126
console.log(sourceCode); // Generated source code for the story
127
```
128
129
### Description Extraction
130
131
Extract JSDoc-style descriptions from comment blocks in the source code.
132
133
```typescript { .api }
134
/**
135
* Extract description from JSDoc-style comments
136
* @param node - AST node with potential leading comments
137
* @returns Extracted description text or empty string
138
*/
139
function extractDescription(node?: t.Node): string;
140
```
141
142
**Usage Examples:**
143
144
```typescript
145
import { extractDescription } from "@storybook/csf-tools";
146
147
// Extract description from meta statement
148
const metaDescription = extractDescription(csfFile._metaStatement);
149
150
// Extract description from story
151
const storyDescription = extractDescription(
152
csfFile._storyStatements['Primary']
153
);
154
```
155
156
## Enhancement Patterns
157
158
### Full File Enhancement
159
160
Enhance an entire CSF file with all available metadata:
161
162
```typescript
163
import { readCsf, enrichCsf, writeCsf } from "@storybook/csf-tools";
164
165
// Read original source file
166
const sourceCsf = await readCsf('./src/Button.stories.ts', {
167
makeTitle: (title) => `Components/${title}`
168
});
169
170
// Read compiled/transformed file to enhance
171
const targetCsf = await readCsf('./dist/Button.stories.js', {
172
makeTitle: (title) => `Components/${title}`
173
});
174
175
// Enhance with all metadata
176
enrichCsf(targetCsf, sourceCsf);
177
178
// Write enhanced file
179
await writeCsf(targetCsf, './dist/Button.enhanced.stories.js');
180
```
181
182
### Selective Enhancement
183
184
Enhance only specific aspects or stories:
185
186
```typescript
187
// Enhance only descriptions, skip source code
188
enrichCsf(targetCsf, sourceCsf, {
189
disableSource: true,
190
disableDescription: false
191
});
192
193
// Enhance only the meta object
194
enrichCsfMeta(targetCsf, sourceCsf);
195
196
// Enhance specific stories
197
const storyNames = ['Primary', 'Secondary', 'Large'];
198
storyNames.forEach(name => {
199
enrichCsfStory(targetCsf, sourceCsf, name);
200
});
201
```
202
203
### Custom Enhancement Workflow
204
205
Build custom enhancement workflows with extracted metadata:
206
207
```typescript
208
import {
209
loadCsf,
210
extractSource,
211
extractDescription,
212
formatCsf
213
} from "@storybook/csf-tools";
214
215
const sourceCsf = loadCsf(sourceCode, options).parse();
216
217
// Extract metadata for custom processing
218
const storyData = Object.entries(sourceCsf._storyExports).map(([name, export]) => ({
219
name,
220
source: extractSource(export),
221
description: extractDescription(sourceCsf._storyStatements[name]),
222
parameters: sourceCsf._stories[name].parameters
223
}));
224
225
// Use extracted data for custom documentation generation
226
const documentationData = {
227
title: sourceCsf.meta?.title,
228
component: sourceCsf.meta?.component,
229
stories: storyData
230
};
231
232
console.log(JSON.stringify(documentationData, null, 2));
233
```
234
235
### Batch Processing
236
237
Process multiple CSF files for enhancement:
238
239
```typescript
240
import { glob } from 'glob';
241
import { readCsf, enrichCsf, writeCsf } from "@storybook/csf-tools";
242
243
async function enhanceAllStories(sourcePattern: string, targetDir: string) {
244
const sourceFiles = glob.sync(sourcePattern);
245
246
for (const sourceFile of sourceFiles) {
247
const sourceCsf = await readCsf(sourceFile, {
248
makeTitle: (title) => title
249
});
250
251
// Assume corresponding compiled file exists
252
const targetFile = sourceFile.replace('/src/', '/dist/');
253
const targetCsf = await readCsf(targetFile, {
254
makeTitle: (title) => title
255
});
256
257
// Enhance with metadata
258
enrichCsf(targetCsf, sourceCsf);
259
260
// Write enhanced version
261
const outputFile = targetFile.replace('.stories.js', '.enhanced.stories.js');
262
await writeCsf(targetCsf, outputFile);
263
264
console.log(`Enhanced: ${outputFile}`);
265
}
266
}
267
268
// Enhance all story files
269
await enhanceAllStories('./src/**/*.stories.ts', './dist/enhanced/');
270
```
271
272
## Metadata Types
273
274
The enhancement system works with several metadata structures:
275
276
### Story Parameters
277
278
Enhanced stories receive additional parameters:
279
280
```typescript
281
// Enhanced story parameters include:
282
{
283
__id: string; // Story ID
284
docs: {
285
source: {
286
originalSource: string; // Extracted source code
287
};
288
description: {
289
story: string; // Extracted description
290
};
291
};
292
// ... existing parameters
293
}
294
```
295
296
### Meta Parameters
297
298
Enhanced meta objects receive component-level descriptions:
299
300
```typescript
301
// Enhanced meta parameters include:
302
{
303
parameters: {
304
docs: {
305
description: {
306
component: string; // Component description from comments
307
};
308
};
309
};
310
// ... existing meta properties
311
}
312
```
313
314
## Comment Processing
315
316
The description extraction system processes various comment formats:
317
318
```typescript
319
/**
320
* This is a JSDoc-style comment that will be extracted
321
* as the component description.
322
*/
323
export default { title: 'Button' };
324
325
/**
326
* Primary story showing the default button state.
327
* This description will be extracted for the story.
328
*/
329
export const Primary = { args: { primary: true } };
330
```
331
332
Block comments are processed by:
333
1. Removing leading `*` characters and whitespace
334
2. Joining multiple comment blocks
335
3. Trimming the final result
336
4. Filtering out single-line comments (`//`)