CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-storybook--csf-tools

Parse and manipulate CSF and Storybook config files

Pending
Overview
Eval results
Files

story-enhancement.mddocs/

Story Enhancement

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.

Capabilities

CSF Enhancement

Enhance CSF files with source code and description metadata for better documentation and tooling support.

/**
 * Enhance a CSF file with metadata from its source
 * @param csf - Target CSF file to enhance
 * @param csfSource - Source CSF file to extract metadata from
 * @param options - Enhancement options
 */
function enrichCsf(
  csf: CsfFile,
  csfSource: CsfFile,
  options?: EnrichCsfOptions
): void;

interface EnrichCsfOptions {
  /** Skip adding source code information to stories */
  disableSource?: boolean;
  /** Skip adding description information from comments */
  disableDescription?: boolean;
}

Usage Examples:

import { loadCsf, enrichCsf } from "@storybook/csf-tools";

// Load source CSF file
const sourceCsf = loadCsf(sourceCode, { 
  fileName: 'Button.stories.ts',
  makeTitle: (title) => title 
}).parse();

// Load target CSF file (for enhancement)
const targetCsf = loadCsf(targetCode, {
  fileName: 'Button.stories.ts',
  makeTitle: (title) => title
}).parse();

// Enhance target with source metadata
enrichCsf(targetCsf, sourceCsf, {
  disableSource: false,
  disableDescription: false
});

Story-Level Enhancement

Enhance individual stories with metadata and source information.

/**
 * Enhance a specific story with metadata from its source
 * @param csf - Target CSF file containing the story
 * @param csfSource - Source CSF file to extract metadata from
 * @param key - Export name of the story to enhance
 * @param options - Enhancement options
 */
function enrichCsfStory(
  csf: CsfFile,
  csfSource: CsfFile,
  key: string,
  options?: EnrichCsfOptions
): void;

Usage Examples:

// Enhance only specific stories
enrichCsfStory(targetCsf, sourceCsf, 'Primary', {
  disableSource: false,
  disableDescription: false
});

enrichCsfStory(targetCsf, sourceCsf, 'Secondary');

Meta Enhancement

Enhance the meta object (default export) with component-level metadata.

/**
 * Enhance the meta object with component-level metadata
 * @param csf - Target CSF file containing the meta
 * @param csfSource - Source CSF file to extract metadata from
 * @param options - Enhancement options
 */
function enrichCsfMeta(
  csf: CsfFile,
  csfSource: CsfFile,
  options?: EnrichCsfOptions
): void;

Source Code Extraction

Extract source code from AST nodes for documentation purposes.

/**
 * Extract source code from an AST node
 * @param node - AST node to extract source from
 * @returns Generated source code string
 */
function extractSource(node: t.Node): string;

Usage Examples:

import { extractSource } from "@storybook/csf-tools";

// Extract source from a story export
const storyExport = csfFile.getStoryExport('Primary');
const sourceCode = extractSource(storyExport);
console.log(sourceCode); // Generated source code for the story

Description Extraction

Extract JSDoc-style descriptions from comment blocks in the source code.

/**
 * Extract description from JSDoc-style comments
 * @param node - AST node with potential leading comments
 * @returns Extracted description text or empty string
 */
function extractDescription(node?: t.Node): string;

Usage Examples:

import { extractDescription } from "@storybook/csf-tools";

// Extract description from meta statement
const metaDescription = extractDescription(csfFile._metaStatement);

// Extract description from story
const storyDescription = extractDescription(
  csfFile._storyStatements['Primary']
);

Enhancement Patterns

Full File Enhancement

Enhance an entire CSF file with all available metadata:

import { readCsf, enrichCsf, writeCsf } from "@storybook/csf-tools";

// Read original source file
const sourceCsf = await readCsf('./src/Button.stories.ts', {
  makeTitle: (title) => `Components/${title}`
});

// Read compiled/transformed file to enhance
const targetCsf = await readCsf('./dist/Button.stories.js', {
  makeTitle: (title) => `Components/${title}`
});

// Enhance with all metadata
enrichCsf(targetCsf, sourceCsf);

// Write enhanced file
await writeCsf(targetCsf, './dist/Button.enhanced.stories.js');

Selective Enhancement

Enhance only specific aspects or stories:

// Enhance only descriptions, skip source code
enrichCsf(targetCsf, sourceCsf, {
  disableSource: true,
  disableDescription: false
});

// Enhance only the meta object
enrichCsfMeta(targetCsf, sourceCsf);

// Enhance specific stories
const storyNames = ['Primary', 'Secondary', 'Large'];
storyNames.forEach(name => {
  enrichCsfStory(targetCsf, sourceCsf, name);
});

Custom Enhancement Workflow

Build custom enhancement workflows with extracted metadata:

import { 
  loadCsf, 
  extractSource, 
  extractDescription, 
  formatCsf 
} from "@storybook/csf-tools";

const sourceCsf = loadCsf(sourceCode, options).parse();

// Extract metadata for custom processing
const storyData = Object.entries(sourceCsf._storyExports).map(([name, export]) => ({
  name,
  source: extractSource(export),
  description: extractDescription(sourceCsf._storyStatements[name]),
  parameters: sourceCsf._stories[name].parameters
}));

// Use extracted data for custom documentation generation
const documentationData = {
  title: sourceCsf.meta?.title,
  component: sourceCsf.meta?.component,
  stories: storyData
};

console.log(JSON.stringify(documentationData, null, 2));

Batch Processing

Process multiple CSF files for enhancement:

import { glob } from 'glob';
import { readCsf, enrichCsf, writeCsf } from "@storybook/csf-tools";

async function enhanceAllStories(sourcePattern: string, targetDir: string) {
  const sourceFiles = glob.sync(sourcePattern);
  
  for (const sourceFile of sourceFiles) {
    const sourceCsf = await readCsf(sourceFile, {
      makeTitle: (title) => title
    });
    
    // Assume corresponding compiled file exists
    const targetFile = sourceFile.replace('/src/', '/dist/');
    const targetCsf = await readCsf(targetFile, {
      makeTitle: (title) => title  
    });
    
    // Enhance with metadata
    enrichCsf(targetCsf, sourceCsf);
    
    // Write enhanced version
    const outputFile = targetFile.replace('.stories.js', '.enhanced.stories.js');
    await writeCsf(targetCsf, outputFile);
    
    console.log(`Enhanced: ${outputFile}`);
  }
}

// Enhance all story files
await enhanceAllStories('./src/**/*.stories.ts', './dist/enhanced/');

Metadata Types

The enhancement system works with several metadata structures:

Story Parameters

Enhanced stories receive additional parameters:

// Enhanced story parameters include:
{
  __id: string;              // Story ID
  docs: {
    source: {
      originalSource: string; // Extracted source code
    };
    description: {
      story: string;          // Extracted description
    };
  };
  // ... existing parameters
}

Meta Parameters

Enhanced meta objects receive component-level descriptions:

// Enhanced meta parameters include:
{
  parameters: {
    docs: {
      description: {
        component: string;      // Component description from comments
      };
    };
  };
  // ... existing meta properties
}

Comment Processing

The description extraction system processes various comment formats:

/**
 * This is a JSDoc-style comment that will be extracted
 * as the component description.
 */
export default { title: 'Button' };

/**
 * Primary story showing the default button state.
 * This description will be extracted for the story.
 */
export const Primary = { args: { primary: true } };

Block comments are processed by:

  1. Removing leading * characters and whitespace
  2. Joining multiple comment blocks
  3. Trimming the final result
  4. Filtering out single-line comments (//)

Install with Tessl CLI

npx tessl i tessl/npm-storybook--csf-tools

docs

config-management.md

csf-processing.md

index.md

story-enhancement.md

testing-integration.md

tile.json