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

debugging.mddocs/

Debugging and Logging

Debugging system with namespaced loggers and configurable output for development and troubleshooting. Metalsmith uses the debug module with enhanced features for plugin development and build monitoring.

Capabilities

Debug Logger Creation

Create namespaced debug loggers for plugins and custom code.

/**
 * Create a namespaced debug logger
 * @param namespace - Debug namespace (typically plugin name)
 * @returns Enhanced debugger with multiple log levels
 */
debug(namespace: string): Debugger;

interface Debugger {
  /** Main debug function for general messages */
  (message: string, ...args: any[]): void;
  /** Info-level logging (namespace:info) */
  info(message: string, ...args: any[]): void;
  /** Warning-level logging (namespace:warn) */
  warn(message: string, ...args: any[]): void;
  /** Error-level logging (namespace:error) */
  error(message: string, ...args: any[]): void;
}

Usage Examples:

import Metalsmith from "metalsmith";

const metalsmith = Metalsmith(__dirname);

// Create debug logger for a plugin
function myPlugin(files, metalsmith, done) {
  const debug = metalsmith.debug('metalsmith-myplugin');
  
  debug('Starting plugin execution');
  debug('Processing %d files', Object.keys(files).length);
  
  Object.keys(files).forEach(filepath => {
    debug('Processing file: %s', filepath);
    
    try {
      // Process file...
      debug.info('Successfully processed: %s', filepath);
    } catch (error) {
      debug.error('Failed to process %s: %s', filepath, error.message);
    }
  });
  
  debug('Plugin execution completed');
  done();
}

// Use different log levels
function detailedPlugin(files, metalsmith, done) {
  const debug = metalsmith.debug('detailed-plugin');
  
  debug('Plugin started');                    // General debug
  debug.info('Configuration loaded');         // Info level
  debug.warn('Deprecated option used');       // Warning level
  debug.error('Critical error occurred');     // Error level
  
  done();
}

Debug Configuration

Control debug output through environment variables and Metalsmith settings.

/**
 * Debug configuration properties (available on metalsmith.debug)
 */
interface DebugConfig {
  /** Enable debug output for specific namespaces */
  enable(namespaces: string): void;
  /** Disable debug output */
  disable(): void;
  /** Set custom log handler function */
  handle: (...args: any[]) => void;
  /** Enable/disable color output */
  colors: boolean;
  /** Check if debug is currently enabled */
  enabled: boolean;
}

Environment Variable Control:

// Enable debug output via environment
metalsmith.env('DEBUG', '@metalsmith/*');        // All metalsmith plugins
metalsmith.env('DEBUG', 'metalsmith-markdown');  // Specific plugin
metalsmith.env('DEBUG', '*');                    // All debug output

// Enable in code
metalsmith.debug.enable('@metalsmith/*');

// Disable debug output
metalsmith.debug.disable();

// Check if debug is enabled
if (metalsmith.debug.enabled) {
  console.log('Debug mode is active');
}

Color Configuration:

// Enable colors (default for terminals)
metalsmith.debug.colors = true;

// Disable colors (useful for log files)
metalsmith.debug.colors = false;

Custom Log Handling

Configure custom log handlers for debug output.

/**
 * Set custom debug log handler
 * @param handler - Function to handle debug output
 */
debug.handle = (message: string) => void;

Usage Examples:

import fs from 'fs';

// Log to file
const logStream = fs.createWriteStream('debug.log', { flags: 'a' });
metalsmith.debug.handle = (message) => {
  logStream.write(message + '\n');
};

// Custom formatted logging
metalsmith.debug.handle = (message) => {
  const timestamp = new Date().toISOString();
  console.log(`[${timestamp}] ${message}`);
};

// Multiple handlers
const originalHandler = metalsmith.debug.handle;
metalsmith.debug.handle = (message) => {
  originalHandler(message);  // Console output
  logStream.write(`${new Date().toISOString()}: ${message}\n`);  // File output
};

Built-in Debug Features

Metalsmith includes enhanced debug features beyond standard debug module.

Buffer Formatter:

// Debug includes a %b formatter for buffers
function plugin(files, metalsmith, done) {
  const debug = metalsmith.debug('my-plugin');
  
  Object.keys(files).forEach(filepath => {
    const file = files[filepath];
    
    // %b formatter shows buffer content preview
    debug('File contents: %b', file.contents);
    // Output: "File contents: <Buffer contents preview...>"
  });
  
  done();
}

Performance Monitoring:

function performancePlugin(files, metalsmith, done) {
  const debug = metalsmith.debug('performance');
  
  const startTime = Date.now();
  
  // Process files...
  
  const duration = Date.now() - startTime;
  debug('Processing completed in %dms', duration);
  debug.info('Processed %d files', Object.keys(files).length);
  
  done();
}

Debug-enabled Build Process

Using debug output to monitor the build process.

// Enable comprehensive debugging
metalsmith
  .env('DEBUG', '*')
  .env('DEBUG_LOG', 'build.log')  // Optional: log to file
  .build((error, files) => {
    if (error) {
      console.error('Build failed:', error);
      return;
    }
    console.log('Build completed successfully');
  });

Plugin Debug Patterns

Best practices for debugging in plugins.

function robustPlugin(options = {}) {
  return function plugin(files, metalsmith, done) {
    const debug = metalsmith.debug('robust-plugin');
    
    // Log plugin start with configuration
    debug('Plugin starting with options: %o', options);
    
    const startTime = process.hrtime();
    const fileCount = Object.keys(files).length;
    
    debug('Processing %d files', fileCount);
    
    try {
      let processed = 0;
      
      Object.keys(files).forEach(filepath => {
        debug('Processing file %d/%d: %s', ++processed, fileCount, filepath);
        
        const file = files[filepath];
        
        // Detailed file information
        debug('File size: %d bytes', file.contents.length);
        debug('File metadata: %o', {
          title: file.title,
          date: file.date,
          tags: file.tags
        });
        
        // Process file with error handling
        try {
          // File processing logic...
          debug.info('Successfully processed: %s', filepath);
        } catch (fileError) {
          debug.error('Error processing %s: %s', filepath, fileError.message);
          throw fileError;  // Re-throw to stop build
        }
      });
      
      const [seconds, nanoseconds] = process.hrtime(startTime);
      const duration = (seconds * 1000) + (nanoseconds / 1000000);
      
      debug('Plugin completed in %dms', duration.toFixed(2));
      debug.info('Successfully processed %d files', processed);
      
      done();
    } catch (error) {
      debug.error('Plugin failed: %s', error.message);
      debug.error('Stack trace: %s', error.stack);
      done(error);
    }
  };
}

Environment-specific Debug Configuration

Configure debugging based on environment settings.

// Development environment with verbose debugging
if (process.env.NODE_ENV === 'development') {
  metalsmith
    .env('DEBUG', '@metalsmith/*,my-plugin*')
    .env('DEBUG_LOG', 'logs/debug.log');
  
  metalsmith.debug.colors = true;
}

// Production environment with error-only logging
if (process.env.NODE_ENV === 'production') {
  metalsmith.env('DEBUG', false);
  
  // Custom error-only handler
  metalsmith.debug.handle = (message) => {
    if (message.includes(':error')) {
      console.error(message);
    }
  };
}

// Conditional debugging in plugins
function conditionalPlugin(files, metalsmith, done) {
  const debug = metalsmith.debug('conditional-plugin');
  const verbose = metalsmith.env('VERBOSE');
  
  if (verbose) {
    debug('Verbose mode enabled');
    debug('File list: %o', Object.keys(files));
  }
  
  // Process files...
  done();
}

Debugging File Processing Issues

Common debugging scenarios for file processing problems.

function diagnosticPlugin(files, metalsmith, done) {
  const debug = metalsmith.debug('diagnostics');
  
  debug('=== DIAGNOSTIC INFORMATION ===');
  debug('Working directory: %s', metalsmith.directory());
  debug('Source directory: %s', metalsmith.source());
  debug('Destination directory: %s', metalsmith.destination());
  debug('Global metadata: %o', metalsmith.metadata());
  debug('Environment: %o', metalsmith.env());
  
  debug('=== FILE ANALYSIS ===');
  debug('Total files: %d', Object.keys(files).length);
  
  Object.keys(files).forEach(filepath => {
    const file = files[filepath];
    
    debug('File: %s', filepath);
    debug('  Size: %d bytes', file.contents.length);
    debug('  Mode: %s', file.mode);
    debug('  Stats: %o', file.stats);
    debug('  Metadata keys: %o', Object.keys(file).filter(k => !['contents', 'stats', 'mode'].includes(k)));
    
    // Check for front-matter parsing issues
    if (file.contents.toString().startsWith('---')) {
      debug.warn('  Potential front-matter parsing issue detected');
    }
  });
  
  done();
}

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