CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-storybook--docs-tools

Shared utility functions for frameworks to implement docs in Storybook

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions

Helper functions for string manipulation, value summarization, length validation, and formatting within the Storybook documentation system.

Capabilities

Summary Value Creation

Core utility for creating structured summary objects with optional detailed information.

/**
 * Creates a structured summary value with optional detail
 * @param summary - Brief summary text
 * @param detail - Optional detailed information
 * @returns PropSummaryValue object with summary and optional detail
 */
function createSummaryValue(summary?: string, detail?: string): PropSummaryValue;

interface PropSummaryValue {
  /** Brief summary text */
  summary?: string;
  /** Optional detailed information */
  detail?: string;
}

This function handles the common pattern of providing both brief and detailed representations of type information.

Usage Examples:

import { createSummaryValue } from "@storybook/docs-tools";

// Create simple summary
const basicSummary = createSummaryValue('string');
console.log(basicSummary);
// { summary: 'string' }

// Create summary with detail
const detailedSummary = createSummaryValue('union', 'string | number | boolean');
console.log(detailedSummary);
// { summary: 'union', detail: 'string | number | boolean' }

// Handle identical summary and detail
const identicalSummary = createSummaryValue('CustomType', 'CustomType');
console.log(identicalSummary);
// { summary: 'CustomType' } - detail omitted when identical

// Use in type processing
function processTypeInfo(typeData: any) {
  const { name, raw } = typeData;
  
  if (raw && raw !== name) {
    return createSummaryValue(name, raw);
  }
  
  return createSummaryValue(name);
}

// Create summary for complex types
const complexType = createSummaryValue(
  'Array<T>',
  'Array<{ id: string; name: string; active: boolean }>'
);

Length Validation Functions

Utilities for checking whether strings exceed recommended display length limits.

/**
 * Maximum recommended length for type summaries
 */
const MAX_TYPE_SUMMARY_LENGTH: 90;

/**
 * Maximum recommended length for default value summaries
 */
const MAX_DEFAULT_VALUE_SUMMARY_LENGTH: 50;

/**
 * Checks if a value exceeds the type summary length limit
 * @param value - String to check
 * @returns true if value is too long for type summary display
 */
function isTooLongForTypeSummary(value: string): boolean;

/**
 * Checks if a value exceeds the default value summary length limit
 * @param value - String to check
 * @returns true if value is too long for default value display
 */
function isTooLongForDefaultValueSummary(value: string): boolean;

These functions help determine when to truncate or show detailed views of type and value information.

Usage Examples:

import { 
  isTooLongForTypeSummary, 
  isTooLongForDefaultValueSummary,
  MAX_TYPE_SUMMARY_LENGTH,
  MAX_DEFAULT_VALUE_SUMMARY_LENGTH
} from "@storybook/docs-tools";

// Check type summary length
const longType = 'Array<{ id: string; name: string; description: string; tags: string[]; metadata: Record<string, any> }>';

if (isTooLongForTypeSummary(longType)) {
  console.log('Type summary too long, showing truncated version');
  const truncated = longType.substring(0, MAX_TYPE_SUMMARY_LENGTH) + '...';
  console.log(truncated);
}

// Check default value length
const longDefaultValue = '{ name: "John Doe", email: "john.doe@example.com", preferences: { theme: "dark", notifications: true } }';

if (isTooLongForDefaultValueSummary(longDefaultValue)) {
  console.log('Default value too long for inline display');
  // Show in collapsible detail section instead
}

// Smart display logic
function formatForDisplay(value: string, type: 'type' | 'defaultValue') {
  const isTooLong = type === 'type' 
    ? isTooLongForTypeSummary(value)
    : isTooLongForDefaultValueSummary(value);
  
  if (isTooLong) {
    const maxLength = type === 'type' 
      ? MAX_TYPE_SUMMARY_LENGTH 
      : MAX_DEFAULT_VALUE_SUMMARY_LENGTH;
    
    return {
      summary: value.substring(0, maxLength) + '...',
      detail: value,
      truncated: true
    };
  }
  
  return {
    summary: value,
    truncated: false
  };
}

// Usage in UI components
function TypeDisplay({ typeString }: { typeString: string }) {
  const formatted = formatForDisplay(typeString, 'type');
  
  return (
    <span title={formatted.truncated ? formatted.detail : undefined}>
      {formatted.summary}
    </span>
  );
}

String Normalization

Utility for normalizing newline characters in strings for consistent display.

/**
 * Normalizes newline characters by converting \r\n to \n
 * @param string - Input string with potentially mixed newlines
 * @returns String with normalized newline characters
 */
function normalizeNewlines(string: string): string;

Usage Examples:

import { normalizeNewlines } from "@storybook/docs-tools";

// Normalize Windows-style newlines
const windowsText = 'First line\r\nSecond line\r\nThird line';
const normalized = normalizeNewlines(windowsText);
console.log(normalized);
// 'First line\nSecond line\nThird line'

// Handle mixed newline formats
const mixedText = 'Line 1\nLine 2\r\nLine 3\rLine 4';
const cleanText = normalizeNewlines(mixedText);

// Use in text processing
function processDescription(description: string): string {
  // Normalize newlines first
  let processed = normalizeNewlines(description);
  
  // Additional processing
  processed = processed.trim();
  processed = processed.replace(/\n\s*\n/g, '\n\n'); // Normalize paragraph breaks
  
  return processed;
}

// File content processing
function processFileContent(content: string): string {
  const normalized = normalizeNewlines(content);
  
  return normalized
    .split('\n')
    .map(line => line.trim())
    .filter(line => line.length > 0)
    .join('\n');
}

Advanced String Utilities

Additional string processing functions that complement the core utilities.

/**
 * Removes surrounding quotes from strings
 * @param str - String that may have quotes
 * @returns String with quotes removed
 */
function trimQuotes(str: string): string;

/**
 * Checks if a string contains quotes
 * @param str - String to check
 * @returns true if string includes quotes
 */
function includesQuotes(str: string): boolean;

/**
 * Parses literal values from strings, converting to appropriate types
 * @param str - String representation of a literal value
 * @returns Parsed value as string or number
 */
function parseLiteral(str: string): string | number;

Usage Examples:

import { trimQuotes, includesQuotes, parseLiteral } from "@storybook/docs-tools";

// Handle quoted strings from docgen
const quotedValue = '"default value"';
if (includesQuotes(quotedValue)) {
  const cleaned = trimQuotes(quotedValue);
  console.log(cleaned); // "default value"
}

// Parse different literal types
const numberValue = parseLiteral("42");
console.log(numberValue, typeof numberValue); // 42, "number"

const stringValue = parseLiteral("'hello world'");
console.log(stringValue); // "hello world"

// Use in default value processing
function processDefaultValue(rawValue: string) {
  let processed = rawValue;
  
  // Remove quotes if present
  if (includesQuotes(processed)) {
    processed = trimQuotes(processed);
  }
  
  // Try to parse as literal
  const parsed = parseLiteral(processed);
  
  return {
    raw: rawValue,
    processed,
    parsed,
    type: typeof parsed
  };
}

// Example with various input types
const examples = [
  '"string value"',
  "'another string'",
  "123",
  "true",
  "null"
];

examples.forEach(example => {
  const result = processDefaultValue(example);
  console.log(`${example} -> ${JSON.stringify(result)}`);
});

Common Usage Patterns

These utilities are commonly used together in documentation processing workflows.

import { 
  createSummaryValue, 
  isTooLongForTypeSummary, 
  normalizeNewlines 
} from "@storybook/docs-tools";

// Complete type processing workflow
function processTypeDefinition(typeInfo: any): PropSummaryValue {
  const { name, raw, description } = typeInfo;
  
  // Normalize description text
  const cleanDescription = description ? normalizeNewlines(description) : '';
  
  // Determine summary and detail
  let summary = name || 'unknown';
  let detail = raw || '';
  
  // Check if we need to truncate
  if (detail && isTooLongForTypeSummary(detail)) {
    // Keep original detail, use shorter summary
    summary = name || detail.substring(0, 20) + '...';
  } else if (detail === summary) {
    // Don't duplicate identical values
    detail = '';
  }
  
  return createSummaryValue(summary, detail || undefined);
}

// Documentation formatting helper
function formatDocumentationValue(value: string, maxLength: number): PropSummaryValue {
  const normalized = normalizeNewlines(value.trim());
  
  if (normalized.length <= maxLength) {
    return createSummaryValue(normalized);
  }
  
  const truncated = normalized.substring(0, maxLength).trim() + '...';
  return createSummaryValue(truncated, normalized);
}

// Batch processing utility
function processMultipleValues(values: string[]) {
  return values.map(value => {
    const normalized = normalizeNewlines(value);
    const isTooLong = isTooLongForTypeSummary(normalized);
    
    return {
      original: value,
      normalized,
      summary: createSummaryValue(
        isTooLong ? normalized.substring(0, 50) + '...' : normalized,
        isTooLong ? normalized : undefined
      ),
      truncated: isTooLong
    };
  });
}

Install with Tessl CLI

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

docs

argtypes-enhancement.md

component-extraction.md

constants.md

index.md

jsdoc-processing.md

type-conversion.md

utilities.md

tile.json