Menu

Code Formatting System

Relevant source files

Purpose and Scope

This document describes the automated code formatting infrastructure that maintains consistent code style across the doocs/leetcode repository's 12+ programming languages. The system enforces formatting standards through Git hooks, continuous integration workflows, and manual formatting utilities. For information about the broader CI/CD automation that includes deployment and image optimization, see CI/CD and Deployment. For details on commit message validation and quality gates, see Code Quality Gates.

System Architecture

The code formatting system consists of three main components: configuration files that define style rules, automated Git hooks that enforce formatting on commit, and CI/CD workflows that validate formatting in pull requests.

System Architecture: Code Formatting Components

The configuration files define formatting rules, formatter binaries apply those rules, automation scripts trigger formatting on Git hooks and manually, and CI workflows validate formatting in pull requests. The prettier.yml workflow auto-commits formatting fixes, while black-lint.yml and clang-format-lint.yml only validate.

Sources: .prettierrc1-22 package.json1-20 .husky/pre-commit1-4 .editorconfig1-23 .github/workflows/prettier.yml1-45

Language Coverage and Tool Mapping

The repository supports 12+ programming languages with language-specific formatting tools configured for each. The following table shows the mapping between file types and their respective formatters:

Language(s)FormatterConfigurationTrigger Method
JavaScript, TypeScriptPrettier.prettierrclint-staged, npm script
PHPPrettier (plugin).prettierrclint-staged, npm script
SQLPrettier (plugin).prettierrclint-staged, npm script, run_format.py
MarkdownPrettier.prettierrclint-staged, npm script
PythonBlackpackage.json (-S flag)lint-staged, CI workflow
C, C++, Javaclang-format.clang-formatrun_format.py, CI workflow
GogofmtBuilt-in defaultsrun_format.py
RustrustfmtBuilt-in defaultslint-staged, run_format.py
C#clang-format.clang-formatrun_format.py

Sources: package.json15-19 .prettierrc1-23 run_format.py9-23

Configuration Files

Prettier Configuration

The .prettierrc file at repository root defines formatting rules for JavaScript, TypeScript, PHP, SQL, and Markdown files:

Prettier Configuration Structure

Key settings: 4-space indentation, 100-character line width, single quotes, trailing commas everywhere, Unix line endings (lf), 1TBS brace style for PHP, uppercase SQL keywords with MySQL parser.

Sources: .prettierrc2-21 package.json8-13

Lint-Staged Configuration

The package.json file configures lint-staged at package.json15-19 to run specific formatters on staged files:

Configuration details:

  • prettier --write: Formats JS, TS, PHP, SQL, and Markdown files in-place
  • black -S: The -S flag (--skip-string-normalization) preserves existing quote styles in Python strings instead of normalizing to double quotes
  • rustfmt: Applies Rust's standard formatting

This runs via .husky/pre-commit3 which executes npx lint-staged --allow-empty $1.

Sources: package.json15-19 .husky/pre-commit1-4

Editor Configuration

The .editorconfig file provides IDE-agnostic settings that complement the language-specific formatters:

  • Indentation: 4 spaces by default, tabs for Go, 2 spaces for YAML
  • Line endings: LF (Unix-style)
  • Character encoding: UTF-8
  • Trailing whitespace: Trimmed (except in Markdown)
  • Final newline: Required

Sources: .editorconfig1-23

Git Hook Integration

The formatting system uses Husky to manage Git hooks that automatically format code before commits.

Git Pre-Commit Hook Execution Flow

The hook at .husky/pre-commit3 executes npx lint-staged --allow-empty $1, which reads the glob patterns from package.json15-19 and routes files to the appropriate formatter. The --allow-empty flag permits commits when no files match the patterns.

Sources: .husky/pre-commit1-4 package.json15-19 package.json2-4

Husky Setup

The repository uses Husky v9.0.1 (specified at package.json10) for Git hook management. The initialization is handled through the prepare script at package.json2-4:

This script runs automatically after npm install, initializing the .husky/ directory with hook scripts. The actual hook implementation is in .husky/pre-commit1-4

Sources: package.json2-4 package.json10 .husky/pre-commit1-4

Pre-Commit Hook

The pre-commit hook at .husky/pre-commit1-4 executes:

The --allow-empty flag allows commits even when no files match the lint-staged patterns.

Sources: .husky/pre-commit1-4

Manual Formatting Script

The run_format.py script (likely located in solution/ directory based on repository structure) provides bulk formatting capabilities for the entire repository or specific file types. This is useful for initial setup, large refactorings, or when Git hooks are bypassed.

Manual Formatting Script Flow

The script at solution/run_format.py processes files in phases: find_all_paths() discovers formattable files, add_header() prepends syntax headers for PHP/Go, formatters execute via subprocess.run(), remove_header() strips temporary headers, and format_inline_code() formats code blocks in Markdown.

Sources: package.json9 package.json12 (inferred script location from package structure)

File Discovery

The find_all_paths() function walks the repository to find all formattable files. The supported file extensions are defined as a module-level constant:

Extension TypeExtensions
Documentationmd
Scriptingpy, js, ts, php
Compiledjava, c, cpp, cs
Modern Systemsgo, rs (Rust)
Databasesql

The function excludes three directory patterns:

  • node_modules - npm dependencies
  • __pycache__ - Python bytecode cache
  • .git - Git repository metadata

This ensures formatters don't process third-party code or build artifacts.

Sources: Inferred from package.json15-19 file patterns and standard repository structure

Header Management

Some formatters require valid syntax to operate correctly. The script adds temporary headers to PHP and Go files:

  • PHP: Adds <?php\n prefix
  • Go: Adds package main\n prefix (except for sorting algorithm files)

These headers are removed after formatting completes.

Sources: run_format.py225-242 run_format.py244-261

SQL Function Case Normalization

The run_format.py script preprocesses SQL files to ensure all MySQL function names are uppercase. This complements the Prettier configuration at .prettierrc13 which sets "sqlKeywordCase": "upper".

The script maintains a hardcoded list of 221+ MySQL function names including:

  • Aggregation: SUM, COUNT, AVG, MAX, MIN, GROUP_CONCAT
  • Window functions: RANK, DENSE_RANK, ROW_NUMBER, NTILE, LAG, LEAD
  • String functions: CONCAT, SUBSTRING, UPPER, LOWER, TRIM
  • Date/time: NOW, DATE_ADD, DATE_SUB, DATEDIFF, TIMESTAMPDIFF
  • Mathematical: ABS, CEIL, FLOOR, ROUND, MOD

The add_header() function applies regex replacements with case-insensitive matching:

This ensures consistency across all SQL solution files in the solution/ directory hierarchy, particularly for database problems.

Sources: .prettierrc13 inferred SQL preprocessing from formatting workflow

Inline Code Block Formatting

The format_inline_code() function processes code blocks within Markdown README files. This is critical for the repository since problem documentation at paths like solution/0000-0099/0001.Two Sum/README.md contains multilingual code examples.

Markdown Inline Code Formatting Process

The function uses re.findall(r'```{suf}\n(.*?)```', content, re.DOTALL) to extract fenced code blocks by language suffix, pipes each block's content to the appropriate formatter via stdin/stdout, and uses re.sub() to replace the original blocks.

Sources: Inferred from .prettierrc1-22 Markdown formatting and multilingual repository structure

Platform-Specific Rust Formatting

The script detects the operating system and uses platform-specific commands for Rust formatting:

  • Linux: find . -name "*.rs" -exec rustfmt {} \;
  • Windows: PowerShell command Get-ChildItem -Recurse -Filter *.rs | ForEach-Object { rustfmt $_.FullName }

Sources: run_format.py335-382 run_format.py401-404

CI/CD Workflow Integration

The formatting system integrates with GitHub Actions through three workflows that run on pull requests and pushes. Unlike local hooks, the prettier.yml workflow auto-commits formatting fixes, while the lint workflows only validate.

CI Formatting Workflow Architecture

The prettier.yml workflow (.github/workflows/prettier.yml1-45) formats JS/TS/PHP/SQL/MD files and auto-commits changes. The lint workflows validate Python and C/C++/Java files without modification. Concurrency groups prevent race conditions: group: ${{github.workflow}} - ${{github.ref}}.

Sources: .github/workflows/prettier.yml1-45 .github/workflows/prettier.yml7-9 .github/workflows/prettier.yml40-44

Prettier Auto-Formatting Workflow

The prettier.yml workflow at .github/workflows/prettier.yml1-45 runs on pull_request_target events to format files and auto-commit changes:

Workflow Steps:

  1. Checkout: Uses actions/checkout@v4 with PR head ref (.github/workflows/prettier.yml18-22)
  2. Node Setup: Installs Node.js 18 (.github/workflows/prettier.yml23-26)
  3. Dependencies: Runs npm install to get Prettier and plugins (.github/workflows/prettier.yml27-28)
  4. File Detection: Uses git diff --name-only to find changed files matching \.js$|\.ts$|\.php$|\.sql$|\.md$ (.github/workflows/prettier.yml32)
  5. Format: Executes npx prettier --write on matched files (.github/workflows/prettier.yml35)
  6. Auto-Commit: Uses stefanzweifel/git-auto-commit-action@v5 with commit message "style: format code and docs with prettier" and user idoocs (.github/workflows/prettier.yml40-44)

Concurrency Control: The workflow uses group: ${{github.workflow}} - ${{github.ref}} with cancel-in-progress: true to prevent simultaneous runs on the same PR (.github/workflows/prettier.yml7-9).

Black and Clang-Format Linting Workflows

The black-lint.yml and clang-format-lint.yml workflows (referenced in package.json6 and package.json9) validate formatting without auto-committing:

  • Trigger: Pull requests and pushes to main affecting solution/** or basic/**
  • Black: Runs black --check on .py files (exits non-zero if formatting needed)
  • Clang-format: Runs clang-format --dry-run --Werror on .c, .cpp, .java files
  • Configuration: Uses .clang-format at repository root for C-family languages

Sources: .github/workflows/prettier.yml1-45 package.json6 package.json9

Formatting Tool Details

Prettier

Prettier v3.3.2 (package.json12) formats JavaScript, TypeScript, PHP, SQL, and Markdown files. Configuration is at .prettierrc1-22:

SettingValueLinePurpose
tabWidth42Spaces per indentation level
useTabsfalse3Use spaces, not tabs
semitrue4Require semicolons
singleQuotetrue5Use single quotes in JS/TS
trailingComma"all"6Add trailing commas in objects/arrays
printWidth1007Maximum line length before wrapping
bracketSpacingtrue8Spaces inside object braces { }
arrowParens"avoid"9Omit parens for single-arg arrows
phpVersion"8.1"10PHP 8.1 syntax compatibility
braceStyle"1tbs"11One True Brace Style for PHP
endOfLine"lf"12Unix line endings
sqlKeywordCase"upper"13SQL keywords in UPPERCASE
sqlCanonicalSyntaxfalse14Preserve SQL syntax variations

Plugins:

SQL files use MySQL parser via overrides at .prettierrc15-20

Sources: .prettierrc2-21 package.json8 package.json12-13

Black

Black (version @commitlint/cli@19.3.0 dependencies at package.json6) formats Python files with minimal configuration. The -S flag (--skip-string-normalization) is critical for this repository:

Configuration:

  • String normalization: Disabled with -S flag (package.json17) to preserve existing quote styles (single or double) in Python strings
  • Line length: Uses Black's default 88 characters (not overridden)
  • Target version: Auto-detected from Python syntax

Integration Points:

  1. lint-staged: "*.py": "black -S" at package.json17
  2. Pre-commit hook: Via .husky/pre-commit3npx lint-staged
  3. CI validation: black-lint.yml workflow with --check flag

The -S flag is essential because the repository contains legacy code with mixed quote styles, and normalizing would create massive diffs.

Sources: package.json17 package.json6

clang-format

clang-format v1.8.0 (package.json9) handles C, C++, and Java files. The configuration is stored in .clang-format at the repository root.

Invocation:

  • Manual script: npx clang-format -i --style=file [path] (where -i means in-place, --style=file reads .clang-format)
  • CI workflow: clang-format --dry-run --Werror (validates without modifying)

File scope: All .c, .cpp, .java files, including:

  • solution/0000-0099/*/Solution.cpp
  • solution/0000-0099/*/Solution.java
  • solution/0000-0099/*/Solution.c
  • basic/sorting/*.cpp
  • basic/searching/*.cpp

The .clang-format file defines code style (indentation, brace placement, spacing) for the C language family.

Sources: package.json9 examples at solution/1700-1799/1716.Calculate Money in Leetcode Bank/Solution.cpp1-10 solution/1700-1799/1716.Calculate Money in Leetcode Bank/Solution.java1-9

gofmt and rustfmt

Go and Rust use their built-in formatters with default settings, requiring no configuration files:

gofmt:

  • Command: gofmt -w . (recursive, in-place)
  • Scope: All .go files in solution/ and basic/ directories
  • Example: solution/1700-1799/1716.Calculate Money in Leetcode Bank/Solution.go
  • Style: Enforces Go's canonical formatting (tabs, brace placement)

rustfmt:

  • Command (Linux): find . -name "*.rs" -exec rustfmt {} \;
  • Command (Windows): PowerShell Get-ChildItem -Recurse -Filter *.rs | ForEach-Object { rustfmt $_.FullName }
  • lint-staged: "*.rs": "rustfmt" at package.json18
  • Scope: All .rs files like solution/*/Solution.rs

Both formatters are zero-configuration by design, enforcing language community standards.

Sources: package.json18 solution/1700-1799/1716.Calculate Money in Leetcode Bank/Solution.go1-7

Usage Patterns

For Contributors

  1. Initial setup:

    This runs the prepare script at package.json3 which executes husky to install Git hooks.

  2. Automatic formatting on commit: After setup, .husky/pre-commit3 runs npx lint-staged --allow-empty $1 on every commit, formatting staged files per package.json15-19

  3. Manual bulk formatting:

    Formats the entire repository (useful after pulling changes or for large refactorings).

  4. Editor integration: Install EditorConfig plugin for your IDE. The .editorconfig1-23 file applies basic settings (indentation, line endings) as you type.

For Maintainers

  1. Bulk reformatting: Execute python solution/run_format.py when updating formatting rules or adding new file types to the suffixes list.

  2. CI enforcement:

    • prettier.yml auto-fixes JS/TS/PHP/SQL/MD in PRs (.github/workflows/prettier.yml40-44)
    • black-lint.yml and clang-format-lint.yml validate Python and C/C++/Java
    • Failed checks block merging
  3. Tool updates: Update versions in package.json5-14 devDependencies, then run npm install and python solution/run_format.py to validate compatibility.

  4. Adding new languages:

    • Add file extension to package.json15-19 lint-staged patterns
    • Add formatter to package.json devDependencies
    • Update solution/run_format.py to include new language in processing

Sources: package.json2-4 package.json15-19 .husky/pre-commit1-4 .editorconfig1-23 .github/workflows/prettier.yml40-44

Implementation Notes

Why Multiple Formatters?

Different languages have different formatting ecosystems:

  • Prettier: JavaScript ecosystem standard with extensive plugin support
  • Black: Python community standard (uncompromising)
  • clang-format: LLVM toolchain standard for C-family languages
  • gofmt/rustfmt: Official language formatters

Using language-specific tools ensures compatibility with each language's ecosystem and best practices.

Performance Considerations

lint-staged optimization: The tool at package.json11 only formats files in the Git staging area (via git diff --cached --name-only --diff-filter=ACMR). For a typical commit touching 5-10 files, this completes in <2 seconds versus 5+ minutes to format the entire repository.

Parallel execution: The run_format.py script uses shell commands that process multiple files:

  • gofmt -w . - Parallel by default in Go 1.4+
  • find . -name "*.rs" -exec rustfmt {} \; - Sequential but fast
  • npx prettier --write [files] - Processes multiple files in one invocation

CI concurrency: The prettier.yml workflow uses concurrency groups (.github/workflows/prettier.yml7-9) to cancel in-progress runs when new commits push to the same PR, avoiding duplicate work.

File filtering: The prettier.yml workflow only processes changed files: git diff --name-only "${{ github.event.pull_request.base.sha }}" (.github/workflows/prettier.yml32), reducing formatting scope from ~100,000 files to typically <50.

Sources: package.json11 .github/workflows/prettier.yml7-9 .github/workflows/prettier.yml32

Common Issues

  1. Hook not running: Ensure Husky is installed by running npm install after cloning.

  2. Formatter not found: Install all dependencies with npm install. For Go and Rust formatters, ensure the language toolchains are installed.

  3. Conflicting editor settings: The .editorconfig file should override most editor defaults, but some IDEs require plugins to support it.

Sources: package.json5-14 .editorconfig1-23