or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argtypes-enhancement.mdcomponent-extraction.mdconstants.mdindex.mdjsdoc-processing.mdtype-conversion.mdutilities.md

component-extraction.mddocs/

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

```