0
# Component Property Extraction
1
2
Tools for extracting and processing component properties from various docgen sources including react-docgen, vue-docgen-api, and other component analysis tools.
3
4
## Capabilities
5
6
### Component Property Extraction
7
8
Main function for extracting structured property information from components using docgen metadata.
9
10
```typescript { .api }
11
/**
12
* Extracts component properties from docgen information
13
* @param component - Component with attached docgen metadata
14
* @param section - Docgen section to extract (e.g., 'props', 'events')
15
* @returns Array of extracted properties with metadata
16
*/
17
function extractComponentProps(
18
component: Component,
19
section: string
20
): ExtractedProp[];
21
22
interface ExtractedProp {
23
/** Property definition with all metadata */
24
propDef: PropDef;
25
/** Original docgen information */
26
docgenInfo: DocgenInfo;
27
/** Parsed JSDoc tags */
28
jsDocTags?: ExtractedJsDoc;
29
/** Detected type system */
30
typeSystem: TypeSystem;
31
}
32
33
type ExtractProps = (component: Component, section: string) => ExtractedProp[];
34
```
35
36
The extraction process handles both array and object-based docgen formats, automatically detecting the type system and processing JSDoc comments.
37
38
**Usage Examples:**
39
40
```typescript
41
import { extractComponentProps } from "@storybook/docs-tools";
42
43
// Extract props from React component
44
const reactComponent = {
45
__docgenInfo: {
46
props: {
47
name: {
48
type: { name: 'string' },
49
required: true,
50
description: 'User name @param name - The user identifier'
51
},
52
age: {
53
type: { name: 'number' },
54
required: false,
55
description: 'User age in years',
56
defaultValue: { value: '18' }
57
}
58
}
59
}
60
};
61
62
const props = extractComponentProps(reactComponent, 'props');
63
console.log(props);
64
// [
65
// {
66
// propDef: { name: 'name', type: { summary: 'string' }, required: true, ... },
67
// docgenInfo: { type: { name: 'string' }, required: true, ... },
68
// jsDocTags: { params: [{ name: 'name', description: 'The user identifier' }] },
69
// typeSystem: TypeSystem.JAVASCRIPT
70
// },
71
// { ... }
72
// ]
73
74
// Extract events from Vue component
75
const vueComponent = {
76
__docgenApi: [
77
{
78
name: 'click',
79
type: { names: ['CustomEvent'] },
80
description: 'Emitted when button is clicked'
81
}
82
]
83
};
84
85
const events = extractComponentProps(vueComponent, 'events');
86
87
// Framework-agnostic extraction
88
function extractAllComponentInfo(component: Component) {
89
const props = extractComponentProps(component, 'props');
90
const events = extractComponentProps(component, 'events');
91
const slots = extractComponentProps(component, 'slots');
92
93
return { props, events, slots };
94
}
95
```
96
97
### Component Description Extraction
98
99
Utility for extracting component-level descriptions from docgen metadata.
100
101
```typescript { .api }
102
/**
103
* Extracts component description from docgen metadata
104
* @param component - Component with docgen information
105
* @returns Component description string or empty string
106
*/
107
function extractComponentDescription(component?: Component): string;
108
```
109
110
**Usage Examples:**
111
112
```typescript
113
import { extractComponentDescription } from "@storybook/docs-tools";
114
115
// Extract description from various docgen formats
116
const componentWithDescription = {
117
__docgenInfo: {
118
description: 'A reusable button component with multiple variants'
119
}
120
};
121
122
const description = extractComponentDescription(componentWithDescription);
123
console.log(description); // "A reusable button component with multiple variants"
124
125
// Handle components without descriptions
126
const componentWithoutDescription = {};
127
const emptyDescription = extractComponentDescription(componentWithoutDescription);
128
console.log(emptyDescription); // ""
129
130
// Use in documentation generation
131
function generateComponentDocs(component: Component) {
132
const description = extractComponentDescription(component);
133
const props = extractComponentProps(component, 'props');
134
135
return {
136
name: component.displayName || component.name,
137
description,
138
properties: props.map(prop => prop.propDef)
139
};
140
}
141
```
142
143
### Section Processing Functions
144
145
Specialized functions for handling different docgen section formats.
146
147
```typescript { .api }
148
/**
149
* Processes docgen section when it's an array format (vue-docgen-api style)
150
* @param docgenSection - Array of docgen entries
151
* @returns Array of extracted properties
152
*/
153
function extractComponentSectionArray(docgenSection: any): ExtractedProp[];
154
155
/**
156
* Processes docgen section when it's an object format (react-docgen style)
157
* @param docgenSection - Object mapping prop names to docgen info
158
* @returns Array of extracted properties
159
*/
160
function extractComponentSectionObject(docgenSection: any): ExtractedProp[];
161
```
162
163
**Usage Examples:**
164
165
```typescript
166
// Handle array format (Vue docgen)
167
const vueDocgenArray = [
168
{
169
name: 'modelValue',
170
type: { names: ['string', 'number'] },
171
description: 'The input value'
172
},
173
{
174
name: 'placeholder',
175
type: { names: ['string'] },
176
description: 'Placeholder text'
177
}
178
];
179
180
const vueProps = extractComponentSectionArray(vueDocgenArray);
181
182
// Handle object format (React docgen)
183
const reactDocgenObject = {
184
value: {
185
type: { name: 'string' },
186
required: true,
187
description: 'Input value'
188
},
189
onChange: {
190
type: { name: 'func' },
191
required: true,
192
description: 'Change handler function'
193
}
194
};
195
196
const reactProps = extractComponentSectionObject(reactDocgenObject);
197
198
// Unified processing
199
function processDocgenSection(section: any): ExtractedProp[] {
200
if (Array.isArray(section)) {
201
return extractComponentSectionArray(section);
202
}
203
return extractComponentSectionObject(section);
204
}
205
```
206
207
### Property Definition Factory
208
209
The extraction system uses factory functions to create appropriate property definitions based on the detected type system.
210
211
```typescript { .api }
212
/**
213
* Factory function type for creating PropDef objects
214
*/
215
type PropDefFactory = (
216
propName: string,
217
docgenInfo: DocgenInfo,
218
jsDocParsingResult?: JsDocParsingResult
219
) => PropDef;
220
221
/**
222
* Gets appropriate PropDef factory for the detected type system
223
* @param typeSystem - Detected type system
224
* @returns Factory function for creating PropDef objects
225
*/
226
function getPropDefFactory(typeSystem: TypeSystem): PropDefFactory;
227
```
228
229
**Usage Examples:**
230
231
```typescript
232
import { getPropDefFactory, TypeSystem } from "@storybook/docs-tools";
233
234
// Create factory for TypeScript components
235
const tsFactory = getPropDefFactory(TypeSystem.TYPESCRIPT);
236
237
const tsPropDef = tsFactory('userName', {
238
type: { name: 'string' },
239
tsType: { name: 'string', raw: 'string' },
240
required: true,
241
description: 'The user name',
242
defaultValue: { value: '""' }
243
});
244
245
// Create factory for Flow components
246
const flowFactory = getPropDefFactory(TypeSystem.FLOW);
247
248
const flowPropDef = flowFactory('count', {
249
type: { name: 'number' },
250
flowType: { name: 'number', raw: 'number' },
251
required: false,
252
description: 'Item count',
253
defaultValue: { value: '0' }
254
});
255
256
// Framework integration
257
function createFrameworkExtractor(framework: string) {
258
return (component: Component, section: string) => {
259
const docgenSection = getDocgenSection(component, section);
260
261
if (!docgenSection) return [];
262
263
const typeSystem = detectTypeSystem(component, framework);
264
const factory = getPropDefFactory(typeSystem);
265
266
return processDocgenWithFactory(docgenSection, factory);
267
};
268
}
269
```
270
271
### Docgen Utility Functions
272
273
Lower-level utilities for working directly with docgen information attached to components.
274
275
```typescript { .api }
276
/**
277
* Checks if a component has docgen information attached
278
* @param component - Component to check
279
* @returns true if component has docgen info
280
*/
281
function hasDocgen<T>(component: Component): boolean;
282
283
/**
284
* Validates that a docgen section contains valid information
285
* @param docgenSection - Section to validate
286
* @returns true if section is valid
287
*/
288
function isValidDocgenSection(docgenSection: any): boolean;
289
290
/**
291
* Extracts a specific docgen section from a component
292
* @param component - Component with docgen information
293
* @param section - Section name to extract (e.g., 'props', 'events')
294
* @returns Docgen section data or undefined
295
*/
296
function getDocgenSection(component: Component, section: string): any;
297
298
/**
299
* Extracts component description from docgen information
300
* @param component - Component to extract description from
301
* @returns Component description string
302
*/
303
function getDocgenDescription(component: Component): string;
304
305
/**
306
* Safely converts objects to strings for display
307
* @param obj - Object to convert
308
* @returns String representation
309
*/
310
function str(obj: any): string;
311
312
/**
313
* Checks if a default value should be ignored in documentation
314
* @param value - Default value to check
315
* @returns true if value should be ignored
316
*/
317
function isDefaultValueBlacklisted(value: string): boolean;
318
```
319
320
**Usage Examples:**
321
322
```typescript
323
import {
324
hasDocgen,
325
isValidDocgenSection,
326
getDocgenSection,
327
getDocgenDescription,
328
str,
329
isDefaultValueBlacklisted
330
} from "@storybook/docs-tools";
331
332
// Check if component has docgen information
333
function processComponent(component: Component) {
334
if (!hasDocgen(component)) {
335
console.log('No docgen information found');
336
return null;
337
}
338
339
// Extract description
340
const description = getDocgenDescription(component);
341
console.log('Component description:', description);
342
343
// Get props section
344
const propsSection = getDocgenSection(component, 'props');
345
346
if (isValidDocgenSection(propsSection)) {
347
// Process props
348
Object.entries(propsSection).forEach(([propName, propInfo]) => {
349
const propData = propInfo as any;
350
351
// Convert to string safely
352
const typeString = str(propData.type);
353
354
// Check default value
355
if (propData.defaultValue && !isDefaultValueBlacklisted(propData.defaultValue.value)) {
356
console.log(`${propName}: ${typeString} = ${propData.defaultValue.value}`);
357
} else {
358
console.log(`${propName}: ${typeString}`);
359
}
360
});
361
}
362
}
363
364
// Framework-specific processing
365
function processReactComponent(component: any) {
366
const docgenInfo = component.__docgenInfo;
367
368
if (hasDocgen({ __docgenInfo: docgenInfo })) {
369
const description = getDocgenDescription({ __docgenInfo: docgenInfo });
370
const props = getDocgenSection({ __docgenInfo: docgenInfo }, 'props');
371
372
return {
373
description,
374
hasProps: isValidDocgenSection(props),
375
propsCount: props ? Object.keys(props).length : 0
376
};
377
}
378
379
return null;
380
}
381
382
// Safe value processing
383
function processDefaultValue(defaultValue: any) {
384
const valueString = str(defaultValue);
385
386
if (isDefaultValueBlacklisted(valueString)) {
387
return null; // Don't show blacklisted values
388
}
389
390
return valueString;
391
}
392
```
393
394
### Type System Detection
395
396
The extraction system automatically detects which type system is being used based on available docgen information.
397
398
```typescript
399
// Type system detection logic
400
function detectTypeSystem(docgenInfo: DocgenInfo): TypeSystem {
401
if (docgenInfo.type != null) {
402
return TypeSystem.JAVASCRIPT;
403
}
404
405
if (docgenInfo.flowType != null) {
406
return TypeSystem.FLOW;
407
}
408
409
if (docgenInfo.tsType != null) {
410
return TypeSystem.TYPESCRIPT;
411
}
412
413
return TypeSystem.UNKNOWN;
414
}
415
416
// Usage in extraction
417
const extractedProps = extractComponentProps(component, 'props');
418
extractedProps.forEach(prop => {
419
console.log(`${prop.propDef.name}: ${prop.typeSystem}`);
420
});
421
```