Shared utility functions for frameworks to implement docs in Storybook
—
Comprehensive JSDoc parsing system that extracts structured information from component documentation comments, supporting parameter descriptions, return types, deprecation notices, and type information.
The main parsing function that processes JSDoc comments and extracts structured documentation information.
/**
* Parses JSDoc comments and extracts structured information
* @param value - JSDoc comment string or null
* @param options - Parsing configuration options
* @returns Structured parsing result with extracted information
*/
function parseJsDoc(
value: string | null,
options?: JsDocParsingOptions
): JsDocParsingResult;
interface JsDocParsingOptions {
/** JSDoc tags to extract (defaults to common tags) */
tags?: string[];
}
interface JsDocParsingResult {
/** Whether the input contained JSDoc formatting */
includesJsDoc: boolean;
/** Whether the component should be ignored (@ignore tag) */
ignore: boolean;
/** Cleaned description text with JSDoc removed */
description?: string;
/** Extracted JSDoc tag information */
extractedTags?: ExtractedJsDoc;
}The parser supports standard JSDoc tags including @param, @arg, @argument, @returns, @ignore, and @deprecated.
Usage Examples:
import { parseJsDoc } from "@storybook/docs-tools";
// Basic JSDoc parsing
const jsDocString = `
Main component description here.
@param name - The user's name
@param age - The user's age in years
@param options - Configuration options
@returns JSX element representing the user
@deprecated Use UserCardV2 instead
`;
const result = parseJsDoc(jsDocString);
console.log(result);
// {
// includesJsDoc: true,
// ignore: false,
// description: "Main component description here.",
// extractedTags: {
// params: [
// { name: "name", description: "The user's name", ... },
// { name: "age", description: "The user's age in years", ... },
// { name: "options", description: "Configuration options", ... }
// ],
// returns: { description: "JSX element representing the user", ... },
// deprecated: "Use UserCardV2 instead"
// }
// }
// Custom tag filtering
const customResult = parseJsDoc(jsDocString, {
tags: ['param', 'returns'] // Only extract param and returns tags
});
// Handling ignored components
const ignoredJsDoc = `
This component is internal only.
@ignore
`;
const ignoredResult = parseJsDoc(ignoredJsDoc);
console.log(ignoredResult.ignore); // trueDetailed interfaces for the structured information extracted from JSDoc comments.
interface ExtractedJsDoc {
/** Parameter information from @param, @arg, @argument tags */
params?: ExtractedJsDocParam[] | null;
/** Deprecation notice from @deprecated tag */
deprecated?: string | null;
/** Return information from @returns tag */
returns?: ExtractedJsDocReturns | null;
/** Whether component should be ignored (@ignore tag) */
ignore: boolean;
}
interface ExtractedJsDocParam extends JsDocParam {
/** Parsed type information */
type?: any;
/** Gets clean parameter name without trailing punctuation */
getPrettyName: () => string | undefined;
/** Gets formatted type name string */
getTypeName: () => string | null;
}
interface ExtractedJsDocReturns extends JsDocReturns {
/** Parsed return type information */
type?: any;
/** Gets formatted return type name string */
getTypeName: () => string | null;
}Usage Examples:
// Working with extracted parameters
const processParams = (extractedTags: ExtractedJsDoc) => {
if (extractedTags.params) {
extractedTags.params.forEach(param => {
const name = param.getPrettyName();
const type = param.getTypeName();
const description = param.description;
console.log(`${name}: ${type} - ${description}`);
});
}
};
// Processing return type information
const processReturns = (extractedTags: ExtractedJsDoc) => {
if (extractedTags.returns) {
const returnType = extractedTags.returns.getTypeName();
const description = extractedTags.returns.description;
console.log(`Returns: ${returnType} - ${description}`);
}
};
// Handling deprecation
const checkDeprecation = (extractedTags: ExtractedJsDoc) => {
if (extractedTags.deprecated) {
console.warn(`Deprecated: ${extractedTags.deprecated}`);
}
};Core interfaces that define the structure of JSDoc information.
interface JsDocParam {
/** Parameter name */
name: string | undefined | null;
/** Parameter description */
description?: string | null;
}
interface JsDocReturns {
/** Return value description */
description?: string | null;
}
interface JsDocTags {
/** Collection of parameter information */
params?: JsDocParam[] | null;
/** Return value information */
returns?: JsDocReturns | null;
}The JSDoc parser includes sophisticated type parsing capabilities for TypeScript-style type annotations.
// Example JSDoc with type information
const typedJsDoc = `
Process user data with validation.
@param {string} name - User's full name
@param {number|undefined} age - User's age, optional
@param {{email: string, phone?: string}} contact - Contact information
@returns {Promise<User>} Processed user object
`;
const typedResult = parseJsDoc(typedJsDoc);
// Access type information
const nameParam = typedResult.extractedTags?.params?.[0];
if (nameParam) {
console.log(nameParam.getTypeName()); // "string"
}
const returnsInfo = typedResult.extractedTags?.returns;
if (returnsInfo) {
console.log(returnsInfo.getTypeName()); // "Promise<User>"
}Common patterns for integrating JSDoc parsing with component documentation systems.
import { parseJsDoc } from "@storybook/docs-tools";
// Process component docgen information
function processComponentDocs(component: any) {
const docgenInfo = component.__docgenInfo;
if (docgenInfo?.description) {
const jsDocResult = parseJsDoc(docgenInfo.description);
if (jsDocResult.ignore) {
return null; // Skip ignored components
}
return {
component,
description: jsDocResult.description,
jsDocTags: jsDocResult.extractedTags,
deprecated: jsDocResult.extractedTags?.deprecated
};
}
return { component };
}
// Enhance prop documentation with JSDoc
function enhancePropDocs(propName: string, propInfo: any) {
const jsDocResult = parseJsDoc(propInfo.description);
return {
name: propName,
...propInfo,
description: jsDocResult.description,
jsDocTags: jsDocResult.extractedTags,
ignore: jsDocResult.ignore
};
}Install with Tessl CLI
npx tessl i tessl/npm-storybook--docs-tools