or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdconfiguration.mdindex.mdplugins.mdtheme-api.mdutilities.md
tile.json

utilities.mddocs/

Utilities

File system utilities, caching, and build helpers for processing documentation files and managing project structure.

Capabilities

File System Utilities

Utilities for working with file paths and content extraction.

/**
 * Convert filesystem path to route ID using kebab-case
 * @param fsPath - Filesystem path to convert
 * @returns Kebab-cased route identifier
 */
function getFileIdFromFsPath(fsPath: string): string;

/**
 * Extract specific line ranges from file content
 * @param content - File content as string
 * @param range - Range specification (e.g., "L1-L10", "L5")
 * @returns Extracted lines as string
 */
function getFileRangeLines(content: string, range: string): string;

/**
 * Extract content from file using regular expression
 * @param content - Source file content
 * @param regexp - Regular expression string
 * @param filePath - Source file path for error reporting
 * @returns Matched content or full content on error
 */
function getFileContentByRegExp(
  content: string,
  regexp: string,
  filePath: string
): string;

/**
 * Parse frontmatter from code blocks (supports JS/HTML comments)
 * @param raw - Raw code string with potential frontmatter
 * @returns Object with separated code and frontmatter
 */
function parseCodeFrontmatter(raw: string): {
  code: string;
  frontmatter: Record<string, any> | null;
};

Usage:

import { 
  getFileIdFromFsPath, 
  getFileRangeLines, 
  parseCodeFrontmatter 
} from "dumi";

// Convert file paths to route IDs
const routeId = getFileIdFromFsPath('/src/components/ButtonGroup/index.tsx');
// Result: "button-group"

// Extract specific lines from content
const content = `line 1
line 2
line 3
line 4`;

const excerpt = getFileRangeLines(content, 'L2-L3');
// Result: "line 2\nline 3"

// Parse frontmatter from code
const codeWithMeta = `/**
 * title: Button Demo
 * description: Basic button component
 */
export default function Button() {
  return <button>Click me</button>;
}`;

const { code, frontmatter } = parseCodeFrontmatter(codeWithMeta);
// frontmatter: { title: "Button Demo", description: "Basic button component" }
// code: "export default function Button() { ... }"

Project Structure Utilities

Utilities for working with monorepo projects and build configurations.

/**
 * Get root directory for monorepo projects
 * @param cwd - Current working directory
 * @returns Root directory path for monorepo or current directory
 */
function getProjectRoot(cwd: string): string;

/**
 * Attempt to load Father build configurations
 * @param cwd - Project directory
 * @returns Array of Father build configurations
 */
function tryFatherBuildConfigs(cwd: string): Promise<any[]>;

/**
 * Convert component path to webpack chunk name
 * @param component - Component file path
 * @param cwdPath - Current working directory path
 * @returns Webpack-compatible chunk name
 */
function componentToChunkName(
  component: string,
  cwdPath?: string
): string;

/**
 * Generate metadata chunk name for route
 * @param path - Route path
 * @param cwd - Current working directory
 * @param locales - Available locales
 * @returns Metadata chunk name
 */
function generateMetaChunkName(
  path: string,
  cwd: string,
  locales?: string[]
): string;

Usage:

import { 
  getProjectRoot, 
  componentToChunkName,
  tryFatherBuildConfigs 
} from "dumi";

// Find monorepo root
const projectRoot = getProjectRoot('/path/to/packages/ui-lib');
// Returns: "/path/to" (if workspace detected)

// Generate chunk names
const chunkName = componentToChunkName(
  '/src/components/Button/index.tsx',
  '/project/root'
);
// Result: "components__Button__index"

// Load Father configs for build integration
const buildConfigs = await tryFatherBuildConfigs(process.cwd());
console.log('Available build configurations:', buildConfigs);

Cache Management

File system caching utilities for performance optimization.

/**
 * Get filesystem cache instance for specific namespace
 * @param ns - Cache namespace
 * @returns Cache instance with get/set methods
 */
function getCache(ns: string): {
  /** Set cache value */
  set(key: string, value: any): Promise<void>;
  /** Get cache value */
  get(key: string): Promise<any>;
  /** Set cache value synchronously */
  setSync(key: string, value: any): void;
  /** Get cache value synchronously */
  getSync(key: string): any;
};

/**
 * Set custom cache directory (internal use)
 * @param dir - Cache directory path
 */
function _setFSCacheDir(dir: string): void;

Usage:

import { getCache } from "dumi";

// Create namespace-specific cache
const apiCache = getCache('api-parsing');
const themeCache = getCache('theme-data');

// Cache expensive operations
async function parseComponentAPI(filePath: string) {
  const cacheKey = `api-${getContentHash(filePath)}`;
  
  // Try cache first
  let apiData = await apiCache.get(cacheKey);
  
  if (!apiData) {
    // Expensive parsing operation
    apiData = await parseTypeScriptFile(filePath);
    
    // Cache result
    await apiCache.set(cacheKey, apiData);
  }
  
  return apiData;
}

// Disable caching for development
process.env.DUMI_CACHE = 'none';

Content Processing

Utilities for content hashing and processing.

/**
 * Generate MD5 hash for content
 * @param content - Content to hash
 * @param length - Hash length (default: 8)
 * @returns Hex hash string
 */
function getContentHash(content: string, length?: number): string;

/**
 * Check if version satisfies range requirement
 * @param version - Version string to check
 * @param range - Semver range requirement
 * @param options - Additional semver options
 * @returns Whether version satisfies range
 */
function isVersionInRange(
  version: string,
  range: string | Range,
  options?: RangeOptions
): boolean;

Usage:

import { getContentHash, isVersionInRange } from "dumi";

// Generate content hashes for cache keys
const fileContent = 'export default function Component() {}';
const hash = getContentHash(fileContent);
// Result: "a1b2c3d4"

const longHash = getContentHash(fileContent, 16);
// Result: "a1b2c3d4e5f6g7h8"

// Check version compatibility
const isCompatible = isVersionInRange('2.4.21', '^2.0.0');
// Result: true

const supportsFeature = isVersionInRange('1.5.0', '>=1.6.0');
// Result: false

Webpack Loader Integration

Utilities for webpack loader processing and integration.

/**
 * Run webpack loaders programmatically
 * @param options - Loader configuration options
 * @returns Promise resolving to loader result
 */
function runLoaders(options: RunLoaderOption): Promise<RunLoaderResult>;

interface RunLoaderOption {
  /** Resource path to process */
  resource?: string;
  /** Array of loaders to apply */
  loaders?: Array<{
    loader: string;
    options?: any;
  }>;
  /** Loader context */
  context?: any;
  /** Custom resource reader function */
  readResource?: (resource: string) => Promise<Buffer>;
}

interface RunLoaderResult {
  /** Loader processing results */
  result: Buffer[];
  /** Original resource buffer */
  resourceBuffer: Buffer;
  /** Whether result is cacheable */
  cacheable: boolean;
  /** File dependencies */
  fileDependencies: string[];
  /** Context dependencies */
  contextDependencies: string[];
}

/**
 * Get loader context (internal webpack utility)
 * @param loader - Loader function or object
 * @returns Loader context
 */
function getContext(loader: any): any;

Usage:

import { runLoaders } from "dumi";

// Process markdown files with custom loader
async function processMarkdownFile(filePath: string) {
  const result = await runLoaders({
    resource: filePath,
    loaders: [
      {
        loader: require.resolve('./markdown-loader'),
        options: {
          extractToc: true,
          generateDemos: true,
        },
      },
    ],
    context: {
      rootDir: process.cwd(),
    },
  });
  
  return {
    content: result.result[0].toString(),
    dependencies: result.fileDependencies,
    cacheable: result.cacheable,
  };
}

// Custom loader implementation
function markdownLoader(content: string) {
  const options = this.getOptions();
  
  // Process markdown content
  const processed = processMarkdown(content, options);
  
  // Track dependencies
  this.addDependency('./components/Button.tsx');
  
  return processed;
}

Advanced Utility Patterns

Custom File Processing Pipeline

import { 
  parseCodeFrontmatter, 
  getContentHash, 
  getCache,
  runLoaders 
} from "dumi";

class DocumentProcessor {
  private cache = getCache('doc-processing');
  
  async processFile(filePath: string, content: string) {
    const hash = getContentHash(content);
    const cacheKey = `processed-${filePath}-${hash}`;
    
    // Check cache
    let result = await this.cache.get(cacheKey);
    
    if (!result) {
      // Parse frontmatter
      const { code, frontmatter } = parseCodeFrontmatter(content);
      
      // Process with loaders
      const loaderResult = await runLoaders({
        resource: filePath,
        loaders: [
          { loader: require.resolve('./custom-loader') },
        ],
      });
      
      result = {
        content: code,
        meta: frontmatter,
        processed: loaderResult.result[0].toString(),
        dependencies: loaderResult.fileDependencies,
      };
      
      // Cache result
      await this.cache.set(cacheKey, result);
    }
    
    return result;
  }
}

Project Structure Analysis

import { 
  getProjectRoot, 
  getFileIdFromFsPath,
  tryFatherBuildConfigs 
} from "dumi";
import path from 'path';
import fs from 'fs';

class ProjectAnalyzer {
  async analyzeProject(startDir: string) {
    const projectRoot = getProjectRoot(startDir);
    const buildConfigs = await tryFatherBuildConfigs(projectRoot);
    
    // Scan for component files
    const components = this.scanComponents(projectRoot);
    
    // Generate route mapping
    const routes = components.map(filePath => ({
      filePath,
      routeId: getFileIdFromFsPath(
        path.relative(projectRoot, filePath)
      ),
      chunkName: componentToChunkName(filePath, projectRoot),
    }));
    
    return {
      projectRoot,
      buildConfigs,
      components: routes,
    };
  }
  
  private scanComponents(rootDir: string): string[] {
    // Implementation for scanning component files
    const componentFiles: string[] = [];
    
    function scanDir(dir: string) {
      const entries = fs.readdirSync(dir);
      
      for (const entry of entries) {
        const fullPath = path.join(dir, entry);
        const stat = fs.statSync(fullPath);
        
        if (stat.isDirectory()) {
          scanDir(fullPath);
        } else if (/\.(tsx?|jsx?)$/.test(entry)) {
          componentFiles.push(fullPath);
        }
      }
    }
    
    scanDir(path.join(rootDir, 'src'));
    return componentFiles;
  }
}

Tech Stack Utilities

Utilities for building custom tech stack integrations and API parsing.

/**
 * Language metadata parser interface for tech stacks
 */
interface ILanguageMetaParser {
  /** Language identifier */
  language: string;
  /** Parse component/function metadata from code */
  parse(code: string, options: {
    filename: string;
    entryFile?: string;
  }): Promise<AtomAsset[]>;
}

/**
 * File patching interface for tech stack processing
 */
interface IPatchFile {
  /** File path to patch */
  path: string;
  /** Patch content */
  content: string;
  /** Patch type */
  type: 'add' | 'modify' | 'delete';
}

/**
 * Base options for API parser creation
 */
interface IBaseApiParserOptions {
  /** Entry file for parsing */
  entryFile?: string;
  /** Custom resolver filter function */
  resolveFilter?: (args: {
    id: string;
    ids: string;
    type: 'COMPONENT' | 'FUNCTION';
  }) => boolean;
}

/**
 * Create API parser for tech stack integration
 * @param options - Parser configuration options
 * @returns API parser instance
 */
function createApiParser(options: IBaseApiParserOptions): ILanguageMetaParser;

/**
 * Get Babel core instance for code transformation
 * @returns Babel core module
 */
function babelCore(): typeof import('@babel/core');

/**
 * Get Babel TypeScript preset
 * @returns Babel TypeScript preset configuration
 */
function babelPresetTypeScript(): any;

/**
 * Get Babel environment preset
 * @returns Babel environment preset configuration
 */
function babelPresetEnv(): any;

Usage:

import { 
  createApiParser, 
  babelCore,
  babelPresetTypeScript,
  type ILanguageMetaParser 
} from "dumi/tech-stack-utils";

// Create custom API parser
const parser = createApiParser({
  entryFile: './src/index.ts',
  resolveFilter: ({ id, type }) => {
    // Skip private components
    return !id.startsWith('_');
  },
});

// Use Babel for code transformation
const babel = babelCore();
const result = babel.transformSync(code, {
  presets: [babelPresetTypeScript()],
});

// Custom language parser implementation
class VueMetaParser implements ILanguageMetaParser {
  language = 'vue';
  
  async parse(code: string, options: { filename: string }) {
    // Parse Vue SFC for component metadata
    const component = parseVueComponent(code);
    
    return [{
      type: 'COMPONENT',
      id: getComponentName(options.filename),
      props: extractProps(component),
      methods: extractMethods(component),
    }];
  }
}

Performance Optimization Helpers

import { getCache, getContentHash } from "dumi";

class PerformanceOptimizer {
  private parseCache = getCache('parsing');
  private buildCache = getCache('build');
  
  async optimizedParse(filePath: string, parser: Function) {
    const content = fs.readFileSync(filePath, 'utf-8');
    const hash = getContentHash(content);
    const cacheKey = `parse-${filePath}-${hash}`;
    
    let result = await this.parseCache.get(cacheKey);
    
    if (!result) {
      console.time(`Parsing ${filePath}`);
      result = await parser(content, filePath);
      console.timeEnd(`Parsing ${filePath}`);
      
      await this.parseCache.set(cacheKey, result);
    }
    
    return result;
  }
  
  async batchProcess<T>(
    items: T[],
    processor: (item: T) => Promise<any>,
    concurrency = 5
  ) {
    const results = [];
    
    for (let i = 0; i < items.length; i += concurrency) {
      const batch = items.slice(i, i + concurrency);
      const batchResults = await Promise.all(
        batch.map(processor)
      );
      results.push(...batchResults);
    }
    
    return results;
  }
}