Multiple output formats for linting results supporting console output, JSON, SARIF format, and editor integration.
Each formatter is implemented as an independent class without a shared base class. All formatters accept options in their constructor and provide a format method.
/**
* Pretty formatter for human-readable console output
* Default formatter with color-coded severity levels and file paths
*/
class PrettyFormatter {
constructor(options?: FormatterOptions): PrettyFormatter;
/**
* Format lint results as pretty console output
* @param results - Array of lint results
* @param todoInfo - Optional TODO statistics
* @returns Formatted string for console output
*/
format(results: LintResult[], todoInfo?: TodoInfo): string;
}
/**
* JSON formatter for structured output
* Outputs results as JSON array for programmatic consumption
*/
class JsonFormatter {
constructor(options?: FormatterOptions): JsonFormatter;
/**
* Format lint results as JSON
* @param results - Array of lint results
* @param todoInfo - Optional TODO statistics
* @returns JSON string representation of results
*/
format(results: LintResult[], todoInfo?: TodoInfo): string;
/** Default file extension for JSON output */
defaultFileExtension: 'json';
}
/**
* SARIF formatter for Static Analysis Results Interchange Format
* Outputs results compatible with GitHub Security tab and other SARIF consumers
*/
class SarifFormatter {
constructor(options?: FormatterOptions): SarifFormatter;
/**
* Format lint results as SARIF format
* @param results - Array of lint results
* @param todoInfo - Optional TODO statistics
* @returns SARIF-compliant JSON string
*/
format(results: LintResult[], todoInfo?: TodoInfo): string;
/** Default file extension for SARIF output */
defaultFileExtension: 'sarif';
}
/**
* Kakoune formatter for Kakoune editor integration
* Uses external eslint-formatter-kakoune package
*/
class KakouneFormatter {
constructor(options?: FormatterOptions): KakouneFormatter;
/**
* Format lint results for Kakoune editor
* @param results - Array of lint results
* @param todoInfo - Optional TODO statistics
* @returns Kakoune-compatible format string
*/
format(results: LintResult[], todoInfo?: TodoInfo): string;
}Configuration options passed to formatter constructors.
interface FormatterOptions {
/** Print absolute file paths instead of relative paths */
printFullPath?: boolean;
/** Include TODO items in formatter output */
includeTodo?: boolean;
/** File path for output (used by some formatters) */
outputFile?: string;
/** Suppress warnings, show only errors */
quiet?: boolean;
/** Whether the system is updating TODOs */
updateTodo?: boolean;
/** Include verbose details in output */
verbose?: boolean;
/** Whether results contain data */
hasResultData?: boolean;
/** Configuration object */
config?: any;
/** Working directory path */
workingDirectory?: string;
/** Console object for output */
console?: Console;
/** Whether running in interactive mode */
isInteractive?: boolean;
}System for dynamically loading formatters by name.
/**
* Load a formatter by name or path
* @param options - Options containing format name and formatter options
* @returns Formatter instance
*/
function loadFormatter(options: LoadFormatterOptions): Formatter;
interface LoadFormatterOptions {
/** Formatter name or path */
format: string;
/** Options to pass to formatter constructor */
printFullPath?: boolean;
includeTodo?: boolean;
outputFile?: string;
quiet?: boolean;
updateTodo?: boolean;
verbose?: boolean;
hasResultData?: boolean;
config?: any;
workingDirectory?: string;
console?: Console;
isInteractive?: boolean;
}
// Built-in formatter names
type BuiltInFormatterName =
| "pretty" // Default console formatter
| "json" // JSON array output
| "sarif" // SARIF format for security tools
| "kakoune" // Kakoune editor integration
| "multi"; // Multi-formatter (special case)Special formatter that can combine multiple output formats based on configuration.
/**
* Multi-formatter for combining multiple output formats
* Configured via project configuration rather than constructor options
*/
class MultiFormatter {
constructor(options?: FormatterOptions): MultiFormatter;
/**
* Process results using configured formatters
* Uses project configuration to determine which formatters to apply
*/
format(results: LintResult[], todoInfo?: TodoInfo): void;
}Usage Examples:
import { loadFormatter } from "ember-template-lint/lib/formatters/load-formatter.js";
// Load built-in formatters
const prettyFormatter = loadFormatter({ format: "pretty" });
const jsonFormatter = loadFormatter({
format: "json",
outputFile: "results.json"
});
// Format results
const results = await linter.verify({ source, filePath });
const prettyOutput = prettyFormatter.format(results);
const jsonOutput = jsonFormatter.format(results);
console.log(prettyOutput);
// Custom formatter options
const verboseFormatter = loadFormatter({
format: "pretty",
verbose: true,
printFullPath: true,
quiet: false
});
// Multi-formatter usage (configured via .template-lintrc.js)
const multiFormatter = loadFormatter({ format: "multi" });
// Uses project configuration to determine output formatsFormatters can be configured in your .template-lintrc.js:
// .template-lintrc.js
module.exports = {
rules: {
// ... rules
},
format: {
// Single formatter
name: "json",
outputFile: "lint-results.json"
}
// OR multiple formatters
format: {
formatters: [
{ name: "pretty" },
{ name: "json", outputFile: "results.json" },
{ name: "sarif", outputFile: "results.sarif" }
]
}
};You can create custom formatters by implementing the formatter interface:
// Custom formatter example
class CustomFormatter {
constructor(options = {}) {
this.options = options;
}
format(results, todoInfo) {
// Transform results into desired format
return results.map(result =>
`${result.filePath}:${result.line}:${result.column} - ${result.message}`
).join('\n');
}
}
// Load custom formatter
const customFormatter = loadFormatter({
format: "./path/to/custom-formatter.js"
});Optional TODO statistics provided to formatters when TODO functionality is enabled.
interface TodoInfo {
/** Number of new TODOs added */
add: number;
/** Number of TODOs removed */
remove: number;
/** Number of stable TODOs (unchanged) */
stable: number;
/** Number of expired TODOs */
expired: number;
}Formatters should handle missing or malformed data gracefully:
// Formatter error handling example
class RobustFormatter {
format(results = [], todoInfo = null) {
if (!Array.isArray(results)) {
return "Error: Invalid results format";
}
return results
.filter(result => result && typeof result === 'object')
.map(result => this.formatResult(result))
.join('\n');
}
formatResult(result) {
const filePath = result.filePath || '<unknown>';
const line = result.line || 0;
const column = result.column || 0;
const message = result.message || 'Unknown error';
const rule = result.rule || 'unknown-rule';
return `${filePath}:${line}:${column} [${rule}] ${message}`;
}
}