The formatting system provides types for customizing the display and formatting of lint results. This includes support for colors, symbols, verbose output, and custom formatters.
type Formatter = (
report: FormattableReport,
options: FormatOptions,
) => string;A formatter is a function that takes a lint report and formatting options, then returns a formatted string representation of the results.
interface FormatOptions {
color?: boolean;
signs?: readonly [string, string, string];
colors?: readonly [ChalkColor, ChalkColor, ChalkColor];
verbose?: boolean;
helpUrl?: string;
}Configuration options for formatting output:
type ChalkColor = ColorName | ModifierName;Union type representing all available chalk colors and modifiers from the chalk library.
interface FormattableReport {
results?: (FormattableResult & WithInput)[];
}Top-level report structure containing an array of results, each combining result data with input information.
interface FormattableResult {
errors?: FormattableProblem[];
warnings?: FormattableProblem[];
}Result structure containing arrays of problems categorized by severity:
interface FormattableProblem {
level: RuleConfigSeverity;
name: keyof QualifiedRules;
message: string;
}Individual problem representation:
interface WithInput {
input?: string;
}Mixin interface that adds optional input property to associate results with their original commit message.
import {
Formatter,
FormattableReport,
FormatOptions,
RuleConfigSeverity
} from "@commitlint/types";
const simpleFormatter: Formatter = (report, options) => {
if (!report.results || report.results.length === 0) {
return "No results to format";
}
const lines: string[] = [];
report.results.forEach(result => {
if (result.input) {
lines.push(`Input: ${result.input}`);
}
// Format errors
if (result.errors && result.errors.length > 0) {
lines.push("Errors:");
result.errors.forEach(error => {
const sign = options.signs?.[2] || "✖";
lines.push(` ${sign} ${error.name}: ${error.message}`);
});
}
// Format warnings
if (result.warnings && result.warnings.length > 0) {
lines.push("Warnings:");
result.warnings.forEach(warning => {
const sign = options.signs?.[1] || "⚠";
lines.push(` ${sign} ${warning.name}: ${warning.message}`);
});
}
});
return lines.join("\n");
};import { Formatter, ChalkColor } from "@commitlint/types";
import chalk from "chalk";
const colorFormatter: Formatter = (report, options) => {
if (!report.results || report.results.length === 0) {
return chalk.green("✓ All commit messages are valid");
}
const lines: string[] = [];
const errorColor: ChalkColor = options.colors?.[2] || "red";
const warningColor: ChalkColor = options.colors?.[1] || "yellow";
const inputColor: ChalkColor = options.colors?.[0] || "dim";
report.results.forEach(result => {
if (result.input) {
lines.push(chalk[inputColor](`Commit: ${result.input}`));
}
// Colorized errors
if (result.errors && result.errors.length > 0) {
result.errors.forEach(error => {
const sign = options.signs?.[2] || "✖";
lines.push(chalk[errorColor](` ${sign} ${error.name}: ${error.message}`));
});
}
// Colorized warnings
if (result.warnings && result.warnings.length > 0) {
result.warnings.forEach(warning => {
const sign = options.signs?.[1] || "⚠";
lines.push(chalk[warningColor](` ${sign} ${warning.name}: ${warning.message}`));
});
}
});
if (options.helpUrl) {
lines.push("");
lines.push(`For more information, visit: ${options.helpUrl}`);
}
return lines.join("\n");
};import { FormatOptions } from "@commitlint/types";
// Minimal format options
const minimalOptions: FormatOptions = {
color: false,
verbose: false
};
// Detailed format options
const detailedOptions: FormatOptions = {
color: true,
signs: ["→", "⚠", "✖"] as const,
colors: ["dim", "yellow", "red"] as const,
verbose: true,
helpUrl: "https://commitlint.js.org/"
};
// Custom symbols
const customOptions: FormatOptions = {
color: true,
signs: ["📝", "⚠️", "❌"] as const,
colors: ["blue", "yellow", "red"] as const,
verbose: false
};import { Formatter } from "@commitlint/types";
const jsonFormatter: Formatter = (report, options) => {
const output = {
valid: !report.results?.some(r => r.errors && r.errors.length > 0),
results: report.results?.map(result => ({
input: result.input,
valid: !result.errors || result.errors.length === 0,
errorCount: result.errors?.length || 0,
warningCount: result.warnings?.length || 0,
errors: result.errors?.map(e => ({
rule: e.name,
severity: e.level,
message: e.message
})) || [],
warnings: result.warnings?.map(w => ({
rule: w.name,
severity: w.level,
message: w.message
})) || []
})) || []
};
return JSON.stringify(output, null, options.verbose ? 2 : 0);
};import { Formatter, RuleConfigSeverity } from "@commitlint/types";
const verboseFormatter: Formatter = (report, options) => {
if (!options.verbose) {
return "Use --verbose for detailed output";
}
const lines: string[] = [];
let totalErrors = 0;
let totalWarnings = 0;
lines.push("=".repeat(50));
lines.push("COMMITLINT DETAILED REPORT");
lines.push("=".repeat(50));
report.results?.forEach((result, index) => {
lines.push(`\nResult #${index + 1}:`);
if (result.input) {
lines.push(`Input: "${result.input}"`);
lines.push(`Length: ${result.input.length} characters`);
}
const errors = result.errors || [];
const warnings = result.warnings || [];
totalErrors += errors.length;
totalWarnings += warnings.length;
lines.push(`Errors: ${errors.length}`);
lines.push(`Warnings: ${warnings.length}`);
if (errors.length > 0) {
lines.push("\nError Details:");
errors.forEach((error, i) => {
lines.push(` ${i + 1}. Rule: ${error.name}`);
lines.push(` Level: ${error.level} (${RuleConfigSeverity[error.level]})`);
lines.push(` Message: ${error.message}`);
});
}
if (warnings.length > 0) {
lines.push("\nWarning Details:");
warnings.forEach((warning, i) => {
lines.push(` ${i + 1}. Rule: ${warning.name}`);
lines.push(` Level: ${warning.level} (${RuleConfigSeverity[warning.level]})`);
lines.push(` Message: ${warning.message}`);
});
}
lines.push("-".repeat(30));
});
lines.push("\nSUMMARY:");
lines.push(`Total Results: ${report.results?.length || 0}`);
lines.push(`Total Errors: ${totalErrors}`);
lines.push(`Total Warnings: ${totalWarnings}`);
lines.push(`Overall Status: ${totalErrors > 0 ? "FAILED" : "PASSED"}`);
if (options.helpUrl) {
lines.push(`\nHelp: ${options.helpUrl}`);
}
return lines.join("\n");
};import {
FormattableReport,
FormattableResult,
FormattableProblem,
WithInput,
RuleConfigSeverity
} from "@commitlint/types";
function buildReport(
input: string,
errors: FormattableProblem[],
warnings: FormattableProblem[]
): FormattableReport {
const result: FormattableResult & WithInput = {
input,
errors,
warnings
};
return {
results: [result]
};
}
// Example usage
const sampleErrors: FormattableProblem[] = [
{
level: RuleConfigSeverity.Error,
name: "type-enum",
message: "type must be one of [feat, fix, docs]"
}
];
const sampleWarnings: FormattableProblem[] = [
{
level: RuleConfigSeverity.Warning,
name: "subject-max-length",
message: "subject may not be longer than 50 characters"
}
];
const report = buildReport(
"invalid: this is a test commit message that is too long",
sampleErrors,
sampleWarnings
);