CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-metalsmith

An extremely simple, pluggable static site generator for NodeJS

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

utilities.mddocs/

Utilities and Helpers

Utility methods for path resolution, file matching, environment variables, ignore patterns, and file watching. These helpers provide essential functionality for configuring and extending Metalsmith behavior.

Capabilities

Path Resolution

Resolve paths relative to the Metalsmith working directory.

/**
 * Resolve paths relative to the metalsmith working directory
 * @param paths - Path segments to resolve
 * @returns Absolute path resolved from working directory
 */
path(...paths: string[]): string;

Usage Examples:

import Metalsmith from "metalsmith";

const metalsmith = Metalsmith(__dirname);

// Resolve paths relative to working directory
const srcPath = metalsmith.path('src', 'content');
const buildPath = metalsmith.path('build');
const configPath = metalsmith.path('config', 'site.json');

console.log(srcPath);    // "/absolute/path/to/project/src/content"
console.log(buildPath);  // "/absolute/path/to/project/build"
console.log(configPath); // "/absolute/path/to/project/config/site.json"

// Use in plugins
function customPlugin(files, metalsmith, done) {
  const dataPath = metalsmith.path('data', 'api.json');
  const templatePath = metalsmith.path('templates');
  
  // Use resolved paths for file operations
  done();
}

File Pattern Matching

Match file paths against glob patterns using micromatch.

/**
 * Match filepaths against glob patterns
 * @param patterns - Glob pattern(s) to match against
 * @param input - Array of file paths to test (defaults to current files)
 * @param options - Micromatch options (excluding 'format')
 * @returns Array of matching file paths
 */
match(
  patterns: string | string[], 
  input?: string[], 
  options?: MatchOptions
): string[];

interface MatchOptions {
  /** Include dotfiles in matches */
  dot?: boolean;
  /** Case-sensitive matching */
  nocase?: boolean;
  /** Additional micromatch options */
  [key: string]: any;
}

Usage Examples:

const files = await metalsmith.read();
const filePaths = Object.keys(files);

// Match all markdown files
const markdownFiles = metalsmith.match('**/*.md', filePaths);

// Match multiple patterns
const contentFiles = metalsmith.match([
  '**/*.md',
  '**/*.html',
  '**/*.txt'
], filePaths);

// Match with options
const draftFiles = metalsmith.match('**/*draft*', filePaths, {
  nocase: true  // Case-insensitive
});

// Use in plugins
function selectivePlugin(files, metalsmith, done) {
  const targetFiles = metalsmith.match('posts/*.md');
  
  targetFiles.forEach(filepath => {
    // Process only matching files
    const file = files[filepath];
    file.processed = true;
  });
  
  done();
}

// Default input uses current files
metalsmith.use((files, metalsmith, done) => {
  // Automatically matches against Object.keys(files)
  const jsFiles = metalsmith.match('**/*.js');
  done();
});

Environment Variables

Get and set Metalsmith environment variables (case-insensitive).

/**
 * Get single environment variable
 * @param name - Variable name (case-insensitive)
 * @returns Variable value or undefined
 */
env(name: string): string | number | boolean | null;

/**
 * Get all environment variables
 * @returns Object with all environment variables
 */
env(): { [key: string]: string | number | boolean | null };

/**
 * Set single environment variable
 * @param name - Variable name (case-insensitive)
 * @param value - Variable value (primitives only)
 * @returns Metalsmith instance for chaining
 */
env(name: string, value: string | number | boolean | null): Metalsmith;

/**
 * Set multiple environment variables
 * @param env - Object with variable names and values
 * @returns Metalsmith instance for chaining
 */
env(env: { [key: string]: string | number | boolean | null }): Metalsmith;

Usage Examples:

// Set environment variables
metalsmith
  .env('NODE_ENV', 'production')
  .env('DEBUG', '@metalsmith/*')
  .env('SITE_URL', 'https://example.com');

// Set multiple at once
metalsmith.env({
  NODE_ENV: process.env.NODE_ENV,
  DEBUG: false,
  BUILD_TIME: Date.now()
});

// Get environment variables
const nodeEnv = metalsmith.env('NODE_ENV');
const isDebug = metalsmith.env('DEBUG');
const allEnv = metalsmith.env();

console.log('Environment:', nodeEnv);
console.log('Debug mode:', isDebug);
console.log('All vars:', allEnv);

// Use in plugins
function environmentAwarePlugin(files, metalsmith, done) {
  const isDev = metalsmith.env('NODE_ENV') === 'development';
  const debugEnabled = metalsmith.env('DEBUG');
  
  if (isDev) {
    // Development-specific processing
  }
  
  if (debugEnabled) {
    console.log('Processing files in debug mode');
  }
  
  done();
}

// Environment variables are case-insensitive
metalsmith.env('debug', true);
console.log(metalsmith.env('DEBUG')); // true

Ignore Patterns

Configure which files and directories to ignore during processing.

/**
 * Add files/paths to ignore list
 * @param files - File patterns, paths, or filter functions to ignore
 * @returns Metalsmith instance for chaining
 */
ignore(files: string | string[] | IgnoreFunction | IgnoreFunction[]): Metalsmith;

/**
 * Get current ignore list
 * @returns Array of ignore patterns and functions
 */
ignore(): (string | IgnoreFunction)[];

type IgnoreFunction = (filepath: string, stats: import('fs').Stats) => boolean;

Usage Examples:

import { Stats } from 'fs';

// Ignore specific files
metalsmith.ignore('README.md');

// Ignore patterns
metalsmith.ignore([
  '**/.DS_Store',
  '**/Thumbs.db',
  '**/*.tmp',
  'drafts/**'
]);

// Ignore using functions
metalsmith.ignore((filepath, stats) => {
  // Ignore hidden files
  return filepath.startsWith('.');
});

metalsmith.ignore((filepath, stats) => {
  // Ignore large files (>1MB)
  return stats.size > 1024 * 1024;
});

// Multiple ignore rules
metalsmith
  .ignore('node_modules/**')
  .ignore('*.log')
  .ignore((filepath, stats) => {
    // Ignore directories named 'temp'
    return stats.isDirectory() && filepath.endsWith('/temp');
  });

// Get current ignore list
const ignoreList = metalsmith.ignore();
console.log('Ignoring:', ignoreList);

File Watching

Configure file watching for automatic rebuilds (experimental feature).

/**
 * Get current watch configuration
 * @returns Current watch settings or false if disabled
 */
watch(): false | WatchOptions;

/**
 * Enable/disable file watching
 * @param enabled - True to watch source directory, false to disable
 * @returns Metalsmith instance for chaining
 */
watch(enabled: boolean): Metalsmith;

/**
 * Watch specific paths
 * @param paths - Directory paths or glob patterns to watch
 * @returns Metalsmith instance for chaining
 */
watch(paths: string | string[]): Metalsmith;

/**
 * Configure watch options
 * @param options - Chokidar watch options
 * @returns Metalsmith instance for chaining
 */
watch(options: WatchOptions): Metalsmith;

interface WatchOptions {
  /** Paths to watch (default: source directory) */
  paths?: string[];
  /** Wait for write operations to complete before triggering */
  awaitWriteFinish?: boolean;
  /** Ignore initial add events */
  ignoreInitial?: boolean;
  /** Use polling instead of native events */
  usePolling?: boolean;
  /** Polling interval in milliseconds */
  interval?: number;
  /** Additional chokidar options */
  [key: string]: any;
}

Usage Examples:

// Enable watching (experimental)
metalsmith
  .clean(false)    // Use partial rebuilds for better performance
  .watch(true)     // Watch source directory
  .build((error, files) => {
    if (error) {
      console.error('Build error:', error);
      metalsmith.watch(false); // Stop watching on error
      return;
    }
    console.log(`Rebuilt ${Object.keys(files).length} files`);
  });

// Watch specific directories
metalsmith.watch(['src', 'templates', 'data']);

// Advanced watch configuration
metalsmith.watch({
  paths: ['src/**/*.md', 'templates/**/*.hbs'],
  awaitWriteFinish: {
    stabilityThreshold: 2000,
    pollInterval: 100
  },
  ignoreInitial: true
});

// Get watch status
const watchConfig = metalsmith.watch();
if (watchConfig) {
  console.log('Watching:', watchConfig.paths);
} else {
  console.log('Watch mode disabled');
}

// Stop watching
metalsmith.watch(false);

Utility Usage Patterns

Common patterns for using utilities in plugins and workflows.

// Plugin using multiple utilities
function utilityPlugin(options = {}) {
  return function plugin(files, metalsmith, done) {
    const debug = metalsmith.env('DEBUG');
    const pattern = options.pattern || '**/*.md';
    
    // Use path utility for file operations
    const dataPath = metalsmith.path('data', 'config.json');
    
    // Match files using pattern
    const targetFiles = metalsmith.match(pattern);
    
    if (debug) {
      console.log(`Processing ${targetFiles.length} files matching ${pattern}`);
    }
    
    targetFiles.forEach(filepath => {
      const file = files[filepath];
      // Process file...
    });
    
    done();
  };
}

// Environment-based configuration
const isProduction = metalsmith.env('NODE_ENV') === 'production';
const debugEnabled = metalsmith.env('DEBUG');

metalsmith
  .clean(isProduction)  // Only clean in production
  .concurrency(isProduction ? 50 : 10)  // Higher concurrency in production
  .ignore(isProduction ? [] : ['drafts/**'])  // Include drafts in development
  .env('MINIFY', isProduction);  // Set flags for plugins

// Dynamic ignore patterns
metalsmith.ignore((filepath, stats) => {
  const isDraft = files[filepath]?.draft === true;
  const isProduction = metalsmith.env('NODE_ENV') === 'production';
  
  // Ignore drafts in production
  return isProduction && isDraft;
});

docs

build-processing.md

cli.md

core-configuration.md

debugging.md

file-operations.md

frontmatter.md

index.md

plugin-system.md

utilities.md

tile.json