or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

case-validation.mdconfiguration.mdformatting.mdindex.mdlinting.mdparsing.mdplugins.mdprompts.mdrules-config.md
tile.json

case-validation.mddocs/

Case Validation

The case validation system provides types for enforcing consistent text case formatting across different parts of commit messages. This ensures standardized formatting for commit types, scopes, subjects, and other message components.

Target Case Types

TargetCaseType Union

type TargetCaseType =
  | "camel-case"
  | "kebab-case"
  | "snake-case"
  | "pascal-case"
  | "start-case"
  | "upper-case"
  | "uppercase"
  | "sentence-case"
  | "sentencecase"
  | "lower-case"
  | "lowercase"
  | "lowerCase";

Union type defining all supported case formats for text validation:

  • camel-case: camelCase - First word lowercase, subsequent words capitalized
  • kebab-case: kebab-case - Words separated by hyphens, all lowercase
  • snake-case: snake_case - Words separated by underscores, all lowercase
  • pascal-case: PascalCase - All words capitalized, no separators
  • start-case: Start Case - All words capitalized with spaces
  • upper-case: UPPER CASE - All characters uppercase with spaces
  • uppercase: UPPERCASE - All characters uppercase, no spaces
  • sentence-case: Sentence case - First letter capitalized, rest lowercase
  • sentencecase: sentencecase - Alternative form, all lowercase
  • lower-case: lower case - All characters lowercase with spaces
  • lowercase: lowercase - All characters lowercase, no spaces
  • lowerCase: lowerCase - Camel case starting with lowercase

Usage in Rule Configuration

Case validation is primarily used in rule configurations that validate text formatting:

type CaseRuleConfig<V = RuleConfigQuality.User> = RuleConfig<
  V,
  TargetCaseType | TargetCaseType[]
>;

Rule configuration type that accepts either a single case type or an array of acceptable case types.

Usage Examples

Single Case Enforcement

import { TargetCaseType, RuleConfigSeverity } from "@commitlint/types";

// Enforce lowercase for commit types
const typeRule = [
  RuleConfigSeverity.Error,
  "always",
  "lower-case" as TargetCaseType
];

// Enforce kebab-case for scopes
const scopeRule = [
  RuleConfigSeverity.Error,
  "always", 
  "kebab-case" as TargetCaseType
];

// Enforce sentence case for subjects
const subjectRule = [
  RuleConfigSeverity.Warning,
  "always",
  "sentence-case" as TargetCaseType
];

Multiple Case Options

import { TargetCaseType, RulesConfig } from "@commitlint/types";

const rules: Partial<RulesConfig> = {
  // Allow either lowercase or upper-case for types
  "type-case": [2, "always", ["lowercase", "upper-case"] as TargetCaseType[]],
  
  // Allow camel-case or kebab-case for scopes
  "scope-case": [2, "always", ["camel-case", "kebab-case"] as TargetCaseType[]],
  
  // Allow sentence-case or lower-case for subjects
  "subject-case": [1, "always", ["sentence-case", "lower-case"] as TargetCaseType[]],
  
  // Enforce snake_case for body text
  "body-case": [1, "always", "snake-case" as TargetCaseType]
};

Case Validation in Different Commit Components

import { TargetCaseType, RuleConfigSeverity } from "@commitlint/types";

// Configuration for different parts of commit message
const commitCaseRules = {
  // Type: must be lowercase (feat, fix, docs)
  type: {
    case: "lowercase" as TargetCaseType,
    severity: RuleConfigSeverity.Error
  },
  
  // Scope: can be camelCase or kebab-case
  scope: {
    case: ["camel-case", "kebab-case"] as TargetCaseType[],
    severity: RuleConfigSeverity.Error
  },
  
  // Subject: sentence case (first letter capitalized)
  subject: {
    case: "sentence-case" as TargetCaseType,
    severity: RuleConfigSeverity.Warning
  },
  
  // Body: any case allowed (no restriction)
  body: {
    case: undefined, // No case restriction
    severity: RuleConfigSeverity.Disabled
  }
};

Case Transformation Examples

Understanding what each case type looks like:

import { TargetCaseType } from "@commitlint/types";

const examples: Record<TargetCaseType, string> = {
  "camel-case": "camelCaseExample",
  "kebab-case": "kebab-case-example", 
  "snake-case": "snake_case_example",
  "pascal-case": "PascalCaseExample",
  "start-case": "Start Case Example",
  "upper-case": "UPPER CASE EXAMPLE",
  "uppercase": "UPPERCASEEXAMPLE",
  "sentence-case": "Sentence case example",
  "sentencecase": "sentencecaseexample",
  "lower-case": "lower case example",
  "lowercase": "lowercaseexample",
  "lowerCase": "lowerCaseExample"
};

// Function to validate case format
function validateCase(text: string, expectedCase: TargetCaseType): boolean {
  const expected = examples[expectedCase];
  // Implementation would transform input to expected case and compare
  return transformToCase(text, expectedCase) === text;
}

Complex Case Rules

import { TargetCaseType, RulesConfig, RuleConfigSeverity } from "@commitlint/types";

// Advanced case configuration for monorepo
const monorepoRules: Partial<RulesConfig> = {
  // Types must be lowercase
  "type-case": [RuleConfigSeverity.Error, "always", "lowercase"],
  
  // Scopes can be kebab-case for packages or camelCase for modules
  "scope-case": [
    RuleConfigSeverity.Error, 
    "always", 
    ["kebab-case", "camel-case"] as TargetCaseType[]
  ],
  
  // Subjects should start with lowercase for consistency
  "subject-case": [
    RuleConfigSeverity.Warning,
    "always",
    ["lowercase", "sentence-case"] as TargetCaseType[]
  ],
  
  // Headers (type + scope + subject) follow sentence case
  "header-case": [RuleConfigSeverity.Warning, "always", "sentence-case"]
};

Case Validation Utilities

import { TargetCaseType } from "@commitlint/types";

// Utility to check if text matches case requirement
function matchesCase(text: string, caseType: TargetCaseType): boolean {
  switch (caseType) {
    case "lowercase":
    case "lower-case":
      return text === text.toLowerCase();
      
    case "uppercase": 
    case "upper-case":
      return text === text.toUpperCase();
      
    case "camel-case":
      return /^[a-z][a-zA-Z0-9]*$/.test(text);
      
    case "kebab-case":
      return /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(text);
      
    case "snake-case":
      return /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/.test(text);
      
    case "pascal-case":
      return /^[A-Z][a-zA-Z0-9]*$/.test(text);
      
    case "sentence-case":
      return /^[A-Z][a-z0-9\s]*$/.test(text);
      
    default:
      return true; // Unknown case types pass validation
  }
}

// Utility to validate against multiple allowed cases
function matchesAnyCases(text: string, cases: TargetCaseType[]): boolean {
  return cases.some(caseType => matchesCase(text, caseType));
}

Integration with Commit Rules

import { TargetCaseType, CaseRuleConfig, RuleConfigSeverity } from "@commitlint/types";

// Function to create case rule configurations
function createCaseRule(
  cases: TargetCaseType | TargetCaseType[],
  severity: RuleConfigSeverity = RuleConfigSeverity.Error
): CaseRuleConfig {
  return [severity, "always", cases];
}

// Apply to common commit message components
const caseRules = {
  typeCase: createCaseRule("lowercase", RuleConfigSeverity.Error),
  scopeCase: createCaseRule(["kebab-case", "camel-case"], RuleConfigSeverity.Error),
  subjectCase: createCaseRule("sentence-case", RuleConfigSeverity.Warning),
  bodyCase: createCaseRule(["sentence-case", "lower-case"], RuleConfigSeverity.Warning)
};