CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-commitlint--lint

Lint a string against commitlint rules

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

index.mddocs/

@commitlint/lint

@commitlint/lint is a TypeScript library that provides core linting functionality for commitlint, a tool that validates commit messages against conventional commit format rules. It analyzes commit messages by parsing their structure and checking compliance with configurable rules, supporting both built-in and custom validation rules through a flexible plugin system.

Package Information

  • Package Name: @commitlint/lint
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @commitlint/lint

Core Imports

import lint from "@commitlint/lint";

For CommonJS:

const lint = require("@commitlint/lint").default;

Type imports from @commitlint/types:

import type { 
  LintOptions, 
  LintOutcome, 
  QualifiedRules, 
  RuleConfigSeverity 
} from "@commitlint/types";

Basic Usage

import lint from "@commitlint/lint";

// Basic linting with no rules (always passes)
const result = await lint("feat: add new feature");
console.log(result.valid); // true

// Linting with specific rules
const result = await lint(
  "feat: add new feature",
  {
    "type-enum": [2, "always", ["feat", "fix", "docs"]], // Error level
    "subject-empty": [2, "never"], // Subject must not be empty
  }
);

if (!result.valid) {
  console.log("Errors:", result.errors);
  console.log("Warnings:", result.warnings);
}

Architecture

@commitlint/lint is built around several key components:

  • Main Lint Function: Core validation logic that processes commit messages
  • Rule System: Supports both built-in rules from @commitlint/rules and custom rules via plugins
  • Parser Integration: Uses @commitlint/parse to break down commit message structure
  • Ignore Patterns: Built-in and custom ignore patterns to skip certain commit messages
  • Type System: Full TypeScript integration with comprehensive type definitions from @commitlint/types

Capabilities

Message Linting

Core linting functionality that validates commit messages against a configurable set of rules.

/**
 * Lint a commit message against commitlint rules
 * @param message - The commit message string to validate
 * @param rawRulesConfig - Optional rules configuration object
 * @param rawOpts - Optional linting options
 * @returns Promise resolving to validation results
 */
export default function lint(
  message: string,
  rawRulesConfig?: QualifiedRules,
  rawOpts?: LintOptions
): Promise<LintOutcome>;

interface LintOptions {
  /** If it should ignore the default commit messages (defaults to true) */
  defaultIgnores?: boolean;
  /** Additional commits to ignore, defined by ignore matchers */
  ignores?: Matcher[];
  /** The parser configuration to use when linting the commit */
  parserOpts?: Options;
  /** Plugin system for custom rules */
  plugins?: PluginRecords;
  /** Help URL for documentation */
  helpUrl?: string;
}

interface LintOutcome {
  /** The processed commit message as string */
  input: string;
  /** If the linted commit is considered valid */
  valid: boolean;
  /** All errors, per rule, for the commit */
  errors: LintRuleOutcome[];
  /** All warnings, per rule, for the commit */
  warnings: LintRuleOutcome[];
}

interface LintRuleOutcome {
  /** If the commit is considered valid for the rule */
  valid: boolean;
  /** The severity of the rule (1 = warning, 2 = error) */
  level: RuleConfigSeverity;
  /** The name of the rule */
  name: string;
  /** The message returned from the rule, if invalid */
  message: string;
}

Usage Examples:

import lint from "@commitlint/lint";

// Simple validation
const result = await lint("fix: resolve memory leak");

// With custom rules
const result = await lint(
  "feat(auth): add JWT support",
  {
    "type-enum": [2, "always", ["feat", "fix", "docs", "style"]],
    "scope-empty": [1, "never"], // Warning level
    "subject-min-length": [2, "always", 10],
  }
);

// With parser options
const result = await lint(
  "JIRA-123: implement feature",
  {
    "references-empty": [2, "never"],
  },
  {
    parserOpts: {
      issuePrefixes: ["JIRA-"],
    },
  }
);

// With custom ignore patterns
const result = await lint(
  "WIP: work in progress",
  {
    "type-empty": [2, "never"],
  },
  {
    ignores: [(commit) => commit.startsWith("WIP:")],
  }
);

Rule Configuration System

Rules are configured using arrays with severity level, condition, and optional value:

// QualifiedRules is imported from @commitlint/types
type QualifiedRules = Partial<RulesConfig<RuleConfigQuality.Qualified>>;

type RuleConfigTuple<T = unknown> =
  | Readonly<[RuleConfigSeverity.Disabled]> // [0]
  | Readonly<[RuleConfigSeverity, RuleConfigCondition]> // [1, "always"]
  | Readonly<[RuleConfigSeverity, RuleConfigCondition, T]>; // [2, "always", ["feat", "fix"]]

enum RuleConfigSeverity {
  Disabled = 0,
  Warning = 1,
  Error = 2,
}

type RuleConfigCondition = "always" | "never";

enum RuleConfigQuality {
  User,
  Qualified,
}

// RulesConfig interface defines all available built-in rules
interface RulesConfig<V = RuleConfigQuality.User> {
  "body-case": RuleConfig<V>;
  "body-empty": RuleConfig<V>;
  "body-full-stop": RuleConfig<V, string>;
  "body-leading-blank": RuleConfig<V>;
  "body-max-length": RuleConfig<V, number>;
  "body-max-line-length": RuleConfig<V, number>;
  "body-min-length": RuleConfig<V, number>;
  "footer-empty": RuleConfig<V>;
  "footer-leading-blank": RuleConfig<V>;
  "footer-max-length": RuleConfig<V, number>;
  "footer-max-line-length": RuleConfig<V, number>;
  "footer-min-length": RuleConfig<V, number>;
  "header-case": RuleConfig<V>;
  "header-full-stop": RuleConfig<V, string>;
  "header-max-length": RuleConfig<V, number>;
  "header-min-length": RuleConfig<V, number>;
  "header-trim": RuleConfig<V>;
  "references-empty": RuleConfig<V>;
  "scope-case": RuleConfig<V>;
  "scope-empty": RuleConfig<V>;
  "scope-enum": RuleConfig<V, string[]>;
  "scope-max-length": RuleConfig<V, number>;
  "scope-min-length": RuleConfig<V, number>;
  "signed-off-by": RuleConfig<V, string>;
  "subject-case": RuleConfig<V>;
  "subject-empty": RuleConfig<V>;
  "subject-full-stop": RuleConfig<V, string>;
  "subject-max-length": RuleConfig<V, number>;
  "subject-min-length": RuleConfig<V, number>;
  "trailer-exists": RuleConfig<V, string>;
  "type-case": RuleConfig<V>;
  "type-empty": RuleConfig<V>;
  "type-enum": RuleConfig<V, string[]>;
  "type-max-length": RuleConfig<V, number>;
  "type-min-length": RuleConfig<V, number>;
  // Plugins may add their custom rules
  [key: string]: RuleConfig<V, unknown> | RuleConfig<V, void>;
}

type RuleConfig<V = RuleConfigQuality.Qualified, T = void> = 
  V extends RuleConfigQuality.Qualified ? RuleConfigTuple<T> : RuleConfigTuple<T>;

Rule Configuration Examples:

const rules: QualifiedRules = {
  // Disable rule
  "type-empty": [0],
  
  // Warning when condition is not met
  "subject-min-length": [1, "always", 10],
  
  // Error when condition is not met
  "type-enum": [2, "always", ["feat", "fix", "docs", "style", "refactor", "test", "chore"]],
  
  // Error when condition IS met (never allow empty subjects)
  "subject-empty": [2, "never"],
};

Plugin System

Custom rules can be added through the plugin system:

type PluginRecords = Record<string, Plugin>;

interface Plugin {
  rules: {
    [ruleName: string]: Rule<unknown>;
  };
}

type Rule<Value = unknown> = (
  parsed: Commit,
  when?: RuleConfigCondition,
  value?: Value
) => RuleOutcome | Promise<RuleOutcome>;

type RuleOutcome = Readonly<[boolean, string?]>;

Plugin Usage Example:

import lint from "@commitlint/lint";

const result = await lint(
  "custom: my commit",
  {
    "custom-rule": [2, "always", "required-value"],
  },
  {
    plugins: {
      "my-plugin": {
        rules: {
          "custom-rule": (parsed, when, value) => {
            const isValid = parsed.header?.includes(value) ?? false;
            return [isValid, isValid ? "" : `Header must contain "${value}"`];
          },
        },
      },
    },
  }
);

Parser Options

Configure how commit messages are parsed (using Options from conventional-commits-parser):

interface Options {
  /** Custom header pattern regex */
  headerPattern?: RegExp;
  /** Issue reference prefixes (e.g., ["JIRA-", "TICKET-"]) */
  issuePrefixes?: string[];
  /** Comment character to ignore in commit messages */
  commentChar?: string;
  /** Custom merge pattern regex */
  mergePattern?: RegExp;
  /** Custom revert pattern regex */
  revertPattern?: RegExp;
  /** Merge correlation pattern */
  mergeCorrespondence?: string[];
  /** Revert correspondence pattern */
  revertCorrespondence?: string[];
  /** Field patterns for parsing */
  fieldPattern?: RegExp;
  /** Header correspondence */
  headerCorrespondence?: string[];
  /** Note keywords for parsing commit notes */
  noteKeywords?: string[];
  /** Reference actions for parsing references */
  referenceActions?: string[];
}

Error Handling

The lint function throws errors for invalid configurations:

  • RangeError: When rules are configured but not implemented
  • Error: When rule configurations are invalid (wrong format, invalid severity levels, etc.)

Error Examples:

// Throws RangeError for unknown rule
await lint("test", { "unknown-rule": [2, "always"] });
// RangeError: Found rules without implementation: unknown-rule

// Throws Error for invalid config format
await lint("test", { "type-enum": "invalid" } as any);
// Error: config for rule type-enum must be array

// Throws Error for invalid severity level
await lint("test", { "type-enum": [5, "always"] } as any);
// Error: level for rule type-enum must be between 0 and 2

Ignore Patterns

Control which commit messages are ignored during linting:

type Matcher = (commit: string) => boolean;

interface IsIgnoredOptions {
  /** Custom ignore pattern functions */
  ignores?: Matcher[];
  /** Whether to use built-in default ignore patterns */
  defaults?: boolean;
}

Default ignore patterns include:

  • Merge commits: Merge branch ...
  • Revert commits: Revert "..."
  • Fixup commits: fixup! ...
  • Squash commits: squash! ...

Custom Ignore Example:

const result = await lint(
  "WIP: work in progress",
  { "type-empty": [2, "never"] },
  {
    defaultIgnores: true, // Keep default ignores
    ignores: [
      (commit) => commit.startsWith("WIP:"),
      (commit) => commit.includes("[skip-lint]"),
    ],
  }
);
// This commit will be ignored and return { valid: true }

Types

interface Commit {
  raw: string;
  header: string | null;
  type: string | null;
  scope: string | null;
  subject: string | null;
  body: string | null;
  footer: string | null;
  notes: CommitNote[];
  references: CommitReference[];
  mentions: string[];
  merge: string | null;
  revert: Revert | null;
}

interface CommitNote {
  title: string;
  text: string;
}

interface CommitReference {
  action: string;
  owner: string | null;
  repository: string | null;
  issue: string;
  raw: string;
  prefix: string;
}

interface Revert {
  header: string | null;
  hash: string | null;
}

docs

index.md

tile.json