CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-cspell

A comprehensive spell checking tool specifically designed for source code with CLI interface and programmatic API

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

reporters.mddocs/

Reporter System

Extensible reporting system with built-in reporters and support for custom reporter modules, template-based output formatting, and color styling for presenting spell checking results.

Capabilities

Default Reporter

Get the built-in CLI reporter with comprehensive formatting and color support.

/**
 * Get the default CLI reporter with formatting and color support
 * @param options - Reporter configuration options
 * @param config - Optional additional reporter configuration
 * @returns CSpellReporter instance configured for CLI output
 */
function getDefaultReporter(options: ReporterOptions, config?: CSpellReporterConfiguration): CSpellReporter;

interface ReporterOptions {
  fileGlobs: string[];
  color?: boolean;
  debug?: boolean;
  issues?: boolean;
  issuesSummaryReport?: boolean;
  legacy?: boolean;
  progress?: boolean;
  relative?: boolean;
  root?: string;
  showContext?: boolean | number;
  showPerfSummary?: boolean;
  showSuggestions?: boolean;
  silent?: boolean;
  summary?: boolean;
  verbose?: boolean;
  wordsOnly?: boolean;
}

interface CSpellReporter {
  /** Report when spell checking begins */
  onBegin?: (settings: CSpellSettings, emitter: Emitter) => void;
  /** Report when a file begins processing */
  onFileBegin?: (filename: string) => void;
  /** Report when a file completes processing */
  onFileEnd?: (filename: string, result: FileResult) => void;
  /** Report spelling issues found */
  onIssue?: (issue: Issue) => void;
  /** Report errors encountered during processing */
  onError?: (message: string, error: Error) => void;
  /** Report when spell checking completes */
  onResult?: (result: RunResult) => void;
}

interface Issue {
  /** The misspelled text */
  text: string;
  /** Start offset in the file */
  offset: number;
  /** Length of the misspelled text */
  length: number;
  /** Line number (1-based) */
  line: number;
  /** Column number (1-based) */
  col: number;
  /** File path */
  filename: string;
  /** Issue context */
  context: IssueContext;
  /** Suggested corrections */
  suggestions?: string[];
}

interface FileResult {
  /** File path */
  filename: string;
  /** Number of issues found */
  issues: number;
  /** Whether file was processed successfully */
  success: boolean;
  /** Time taken to process file */
  elapsedTime?: number;
}

Usage Examples:

import { lint, getDefaultReporter } from "cspell";

// Use default reporter
const reporter = getDefaultReporter({
  fileGlobs: ["src/**/*.js"],
  verbose: true,
  showSuggestions: true,
  color: true
});
const result = await lint(
  ["src/**/*.js"], 
  { verbose: true },
  reporter  
);

// Custom reporter extending default behavior
class CustomReporter implements CSpellReporter {
  private defaultReporter = getDefaultReporter({
    fileGlobs: ["src/**/*.js"],
    verbose: true
  });
  
  onBegin = (settings: CSpellSettings, emitter: Emitter) => {
    console.log("🔍 Starting spell check...");
    this.defaultReporter.onBegin?.(settings, emitter);
  };
  
  onIssue = (issue: Issue) => {
    // Custom issue logging
    console.log(`❌ ${issue.filename}:${issue.line}:${issue.col} - "${issue.text}"`);
    
    // Still use default formatting
    this.defaultReporter.onIssue?.(issue);
  };
  
  onResult = (result: RunResult) => {
    console.log(`✅ Checked ${result.files} files, found ${result.issues} issues`);
    this.defaultReporter.onResult?.(result);
  };
}

Reporter Configuration

Configure reporter behavior with comprehensive options for output formatting and styling.

interface CSpellReporterConfiguration extends ReporterConfiguration, LinterCliOptions {
  /** Console interface for output */
  readonly console?: ReporterConsole;
}

interface ReporterConfiguration {
  /** Built-in reporter names or custom reporter module paths */
  reporter?: string[];
  /** Custom issue output template with placeholder variables */
  issueTemplate?: string;
  /** Show suggestions for misspelled words */
  showSuggestions?: boolean;
  /** Show context around issues */
  showContext?: boolean | number;
  /** Only show words without file/line information */
  wordsOnly?: boolean;
  /** Show unique errors only */
  unique?: boolean;
  /** Verbose output mode */
  verbose?: boolean;
  /** Enable color output */
  color?: boolean;
}

interface ReporterConsole {
  /** Standard output logging */
  log: (text: string) => void;
  /** Error output logging */
  error: (text: string) => void;
  /** Warning output logging */
  warn: (text: string) => void;
  /** Information output logging */
  info: (text: string) => void;
}

Usage Examples:

import { lint } from "cspell";

// Built-in reporter configuration
const result = await lint(
  ["src/**/*.ts"],
  {
    reporter: ["default"],        // Use default reporter explicitly
    showSuggestions: true,       // Show spelling suggestions  
    showContext: 10,             // Show 10 characters of context
    verbose: true,               // Verbose output
    color: true                  // Enable color output
  }
);

// JSON reporter for CI/CD
const result = await lint(
  ["**/*.md"],
  {
    reporter: ["@cspell/cspell-json-reporter"],
    verbose: false,
    color: false
  }
);

// Multiple reporters
const result = await lint(
  ["docs/**/*.md"],
  {
    reporter: [
      "default",                              // Console output
      "@cspell/cspell-json-reporter",        // JSON output  
      "./custom-reporters/slack-reporter.js" // Custom Slack reporter
    ]
  }
);

Custom Reporter Modules

Create custom reporter modules for specialized output formats and integrations.

interface CSpellReporterModule {
  /**
   * Get reporter instance with configuration
   * @param settings - Reporter settings object
   * @param config - Reporter configuration options
   * @returns Configured CSpellReporter instance
   */
  getReporter: <T>(settings: T, config: CSpellReporterConfiguration) => CSpellReporter;
}

// Example custom reporter module structure
interface CustomReporterSettings {
  /** Custom setting for reporter behavior */
  customOption?: string;
  /** Output file path for custom reporter */
  outputFile?: string;
}

Usage Examples:

// custom-reporter.js - Custom reporter module
export function getReporter(settings, config) {
  return {
    issues: [],
    
    onBegin(cspellSettings, emitter) {
      console.log(`Starting spell check with ${config.reporter?.length || 1} reporters`);
    },
    
    onIssue(issue) {
      this.issues.push({
        file: issue.filename,
        line: issue.line,
        column: issue.col,
        word: issue.text,
        suggestions: issue.suggestions || []
      });
    },
    
    onResult(result) {
      // Generate custom report format
      const report = {
        summary: {
          totalFiles: result.files,
          filesWithIssues: result.filesWithIssues.size,  
          totalIssues: result.issues,
          timestamp: new Date().toISOString()
        },
        issues: this.issues
      };
      
      if (settings.outputFile) {
        require('fs').writeFileSync(settings.outputFile, JSON.stringify(report, null, 2));
      } else {
        console.log(JSON.stringify(report, null, 2));
      }
    }
  };
}

// Using the custom reporter
import { lint } from "cspell";

const result = await lint(
  ["src/**/*.js"],
  {
    reporter: ["./custom-reporter.js"],
    customReporterSettings: {
      outputFile: "./spell-check-report.json"
    }
  }
);

Template-Based Output

Use customizable templates for issue output formatting with placeholder variable substitution.

interface TemplateSubstitutions {
  /** Column number */
  $col: string;
  /** Full context around the issue */
  $contextFull: string;
  /** Context text before the issue */
  $contextLeft: string;
  /** Context text after the issue */
  $contextRight: string;
  /** File name */
  $filename: string;
  /** Padding for context alignment */
  $padContext: string;
  /** Padding for row/column alignment */
  $padRowCol: string;
  /** Row (line) number */
  $row: string;
  /** Comma-separated suggestions */
  $suggestions: string;
  /** The misspelled text */
  $text: string;
  /** Quick fix suggestion (first suggestion) */
  $quickFix: string;
  /** Issue message */
  $message: string;
  /** Issue message with color formatting applied */
  $messageColored: string;
  /** Full URI of the file being checked */
  $uri: string;
}

// Predefined templates
type IssueTemplate = 
  | "default"           // Standard format with colors
  | "legacy"            // Legacy bracket format
  | "wordsOnly"         // Just the misspelled words
  | "withContext"       // Include surrounding text context
  | "withSuggestions"   // Include spelling suggestions
  | string;             // Custom template string

Usage Examples:

import { lint } from "cspell";

// Custom issue template
const result = await lint(
  ["src/**/*.ts"],
  {
    issueTemplate: "{green $filename}:{yellow $row:$col} - {red $text} -> {blue $suggestions}"
  }
);

// Context-aware template
const result = await lint(
  ["docs/**/*.md"],
  {
    issueTemplate: `
File: $filename (Line $row)
Issue: "$text" 
Context: ...$contextLeft{$text}$contextRight...
Suggestions: [$suggestions]
---`,
    showContext: 20
  }
);

// Minimal template for CI
const result = await lint(
  ["**/*.js"],
  {
    issueTemplate: "$filename:$row:$col:$text",
    color: false
  }
);

// Rich template with colors and suggestions
const result = await lint(
  ["src/**"],
  {
    issueTemplate: "{bgRed  ERROR } {green $filename}:{yellow $row}:{yellow $col} - {red {underline $text}} {gray (suggestions: {cyan $suggestions})}",
    showSuggestions: true
  }
);

Color and Styling

Control color output and styling in reporter output using Chalk color templates.

// Color template syntax (using Chalk template strings)
type ColorTemplate = 
  | "{green text}"          // Green text
  | "{red {underline text}}" // Red underlined text  
  | "{bgBlue {white text}}"  // White text on blue background
  | "{yellow text}"          // Yellow text
  | "{gray text}"            // Gray text
  | "{cyan text}"            // Cyan text
  | "{magenta text}"         // Magenta text
  | string;                  // Plain text

interface ColorConfiguration {
  /** Enable/disable color output */
  color?: boolean;
  /** Color support detection */
  colorSupport?: 'auto' | 'always' | 'never';
}

Usage Examples:

import { lint } from "cspell";

// Colorful output template  
const result = await lint(
  ["src/**/*.js"],
  {
    issueTemplate: "{bgRed {white  ERROR }} {green $filename}:{yellow $row:$col} - {red {bold $text}}",
    color: true
  }
);

// Disable colors for CI/automated environments
const result = await lint(
  ["**/*.ts"],
  {
    issueTemplate: "ERROR: $filename:$row:$col - $text (suggestions: $suggestions)",
    color: false,
    showSuggestions: true
  }
);

// Conditional color based on environment
const isCI = process.env.CI === 'true';
const result = await lint(
  ["docs/**/*.md"],
  {
    issueTemplate: isCI 
      ? "$filename:$row:$col - $text"  // Plain for CI
      : "{red ●} {green $filename}:{yellow $row:$col} - {red $text}", // Colorful for local
    color: !isCI
  }
);

Built-in Reporters

CSpell includes several built-in reporters for different output formats and use cases.

// Built-in reporter identifiers
type BuiltinReporter = 
  | "default"                           // Standard CLI reporter with colors
  | "@cspell/cspell-json-reporter"     // JSON format output
  | "@cspell/cspell-junit-reporter"    // JUnit XML format
  | "@cspell/cspell-github-actions"    // GitHub Actions annotations
  | string;                            // Path to custom reporter module

Usage Examples:

import { lint } from "cspell";

// Default console reporter
const result = await lint(["src/**/*.js"], {
  reporter: ["default"]
});

// JSON reporter for programmatic consumption
const result = await lint(["**/*.ts"], {
  reporter: ["@cspell/cspell-json-reporter"]
});

// JUnit XML for test result integration
const result = await lint(["tests/**/*.js"], {
  reporter: ["@cspell/cspell-junit-reporter"]
});

// GitHub Actions integration  
const result = await lint(["**/*.md"], {
  reporter: ["@cspell/cspell-github-actions"]
});

// Multiple reporters for comprehensive output
const result = await lint(["src/**"], {
  reporter: [
    "default",                          // Console output for developers
    "@cspell/cspell-json-reporter",    // JSON for automation
    "./reporters/slack-reporter.js"    // Custom Slack notifications
  ]
});

Reporter Error Handling

Handle errors and edge cases in custom reporters with proper error propagation.

interface ReporterErrorHandling {
  /** Handle errors during reporting */
  onError?: (message: string, error: Error) => void;
  /** Handle reporter initialization failures */
  onReporterError?: (reporterName: string, error: Error) => void;
}

// Error scenarios in reporters
type ReporterError = 
  | "REPORTER_NOT_FOUND"      // Reporter module not found
  | "REPORTER_INVALID"        // Reporter doesn't implement interface
  | "OUTPUT_WRITE_FAILED"     // Failed to write output file
  | "TEMPLATE_PARSE_ERROR"    // Invalid template syntax
  | "COLOR_SUPPORT_ERROR";    // Color support detection failed

Usage Examples:

// Robust reporter with error handling
class RobustReporter implements CSpellReporter {
  onError = (message: string, error: Error) => {
    console.error(`Reporter Error: ${message}`);
    console.error(`Details: ${error.message}`);
    
    // Continue processing instead of failing completely
    return;
  };
  
  onIssue = (issue: Issue) => {
    try {
      // Custom issue processing
      this.processIssue(issue);
    } catch (error) {
      this.onError?.("Failed to process issue", error as Error);
    }
  };
  
  private processIssue(issue: Issue) {
    // Safe issue processing with fallbacks
    const safeFilename = issue.filename || '<unknown>';
    const safeText = issue.text || '<empty>';
    
    console.log(`${safeFilename}:${issue.line}:${issue.col} - ${safeText}`);
  }
}

// Using reporter with error handling
try {
  const result = await lint(["src/**/*.js"], {
    reporter: ["./potentially-failing-reporter.js"]
  });
} catch (error) {
  console.error("Spell check failed:", error.message);
  
  // Fallback to default reporter
  const fallbackResult = await lint(["src/**/*.js"], {
    reporter: ["default"]
  });
}

Integration Examples

CI/CD Pipeline Integration

// ci-reporter.js - Optimized for CI environments
export function getReporter(settings, config) {
  return {
    onResult(result) {
      if (result.issues > 0) {
        console.log(`::error::Found ${result.issues} spelling issues in ${result.filesWithIssues.size} files`);
        process.exitCode = 1;
      } else {
        console.log(`::notice::Spell check passed - ${result.files} files checked`);
      }
    }
  };
}

Slack Integration

// slack-reporter.js - Send results to Slack
export function getReporter(settings, config) {
  return {
    issues: [],
    
    onIssue(issue) {
      this.issues.push(issue);
    },
    
    async onResult(result) {
      if (result.issues > 0 && settings.slackWebhook) {
        const message = {
          text: `Spell check found ${result.issues} issues`,
          attachments: [{
            color: 'warning',
            fields: [
              { title: 'Files Checked', value: result.files, short: true },
              { title: 'Issues Found', value: result.issues, short: true }
            ]
          }]
        };
        
        await fetch(settings.slackWebhook, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(message)
        });
      }
    }
  };
}

Install with Tessl CLI

npx tessl i tessl/npm-cspell

docs

cli-commands.md

configuration.md

index.md

programmatic-api.md

reporters.md

tile.json