Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@
| 🔒 **Strict and predictable** | Rejects malformed JSON, unknown options, duplicate keys, and invalid UTF-8. |
| 🌍 **International subjects** | Counts Unicode code points while keeping syntax checks fast and ASCII-based. |

## 🔎 Quick Commitlint vs Commitlint

This comparison uses `@commitlint/cli` 21.2.1 and the `@commitlint/config-conventional` and `@commitlint/config-angular` 21.2.0 packages pinned by this repository.

| Area | Quick Commitlint | Commitlint |
| -------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Conventional preset | Built in as `conventional` and used by default | Available through `@commitlint/config-conventional` or the CLI's `--default-config` fallback |
| Angular preset | Built in as `angular` and selected in strict JSON | Available as the shareable `@commitlint/config-angular` package |
| Runtime and dependencies | Small Node.js launcher plus a bundled native Zig executable; no runtime npm dependencies | Node.js CLI with its JavaScript configuration, parsing, formatting, and rule dependencies |
| Configuration | One strict `.quick-commitlint.json` format, two presets, and 14 supported rule overrides | JS, TS, JSON, YAML, and package configuration with shareable configs, plugins, and custom behavior |
| Inputs and ignored commits | Reads standard input or one commit-message file and lints every message | Also reads Git ranges, tags, the last commit, and edit/environment files; supports default ignores |
| Best fit | Projects using the included presets that value predictable configuration and native linting | Projects needing broader rules, custom parsers, plugins, shareable configs, ignores, or history linting |

The supported Conventional and Angular defaults are protected by differential tests, but Quick Commitlint is not a drop-in replacement for every Commitlint setup. Read the [full compatibility guide](https://celtian.github.io/quick-commitlint/docs/compatibility/) for the exact boundary.

## 📊 Performance

Reference cold-process benchmark:

| Preset | Quick Commitlint median | Commitlint median | Improvement |
| ------------ | ----------------------: | ----------------: | ----------: |
| Conventional | 20.686 ms | 250.597 ms | 12.1× |
| Angular | 20.535 ms | 250.228 ms | 12.2× |

These are median wall-clock results from 40 measured launches after 3 warmups on Linux x64 under WSL2, using a 13th Gen Intel Core i9-13900H and Node.js 24.18.0. See the dedicated [Performance documentation](https://celtian.github.io/quick-commitlint/docs/performance/) for the complete method and reproduction steps.

## 🚀 Install

With npm:
Expand Down
54 changes: 26 additions & 28 deletions bun.lock

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
},
"devDependencies": {
"@angular-eslint/builder": "22.1.0",
"@angular/build": "^22.0.8",
"@angular/build": "^22.0.9",
"@angular/cdk": "^22.0.6",
"@angular/cli": "^22.0.8",
"@angular/cli": "^22.0.9",
"@angular/common": "^22.0.8",
"@angular/compiler": "^22.0.8",
"@angular/compiler-cli": "^22.0.8",
Expand All @@ -64,7 +64,7 @@
"@angular/platform-browser": "^22.0.8",
"@angular/platform-server": "^22.0.8",
"@angular/router": "^22.0.8",
"@angular/ssr": "^22.0.8",
"@angular/ssr": "^22.0.9",
"@commitlint/cli": "21.2.1",
"@commitlint/config-angular": "21.2.0",
"@commitlint/config-conventional": "21.2.0",
Expand All @@ -78,14 +78,14 @@
"axe-core": "^4.12.1",
"eslint": "^10.8.0",
"fs-extra": "^11.4.0",
"globals": "^17.7.0",
"globals": "^17.8.0",
"husky": "^9.1.7",
"jsdom": "^29.1.1",
"lint-staged": "^17.0.8",
"jsdom": "^30.0.1",
"lint-staged": "^17.2.0",
"marked": "^18.0.7",
"ngx-markdown": "^22.0.0",
"ngx-scrolltop": "^22.0.0",
"postcss": "^8.5.23",
"postcss": "^8.5.24",
"prettier": "^3.9.6",
"rimraf": "^6.1.3",
"rxjs": "^7.8.2",
Expand Down
1 change: 1 addition & 0 deletions projects/portal/public/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<url><loc>https://celtian.github.io/quick-commitlint/docs/presets/</loc></url>
<url><loc>https://celtian.github.io/quick-commitlint/docs/rules/</loc></url>
<url><loc>https://celtian.github.io/quick-commitlint/docs/cli/</loc></url>
<url><loc>https://celtian.github.io/quick-commitlint/docs/performance/</loc></url>
<url><loc>https://celtian.github.io/quick-commitlint/docs/compatibility/</loc></url>
<url><loc>https://celtian.github.io/quick-commitlint/docs/development/</loc></url>
</urlset>
62 changes: 37 additions & 25 deletions projects/portal/src/app/docs/content/compatibility.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
# Commitlint compatibility

Quick Commitlint is a focused native implementation of a tested subset of commitlint behavior. It is designed for projects that want the included Conventional or Angular rules without loading commitlint's JavaScript configuration and rule stack for every commit.
Quick Commitlint is a focused native implementation of a tested subset of Commitlint behavior. It is designed for projects that want the included Conventional or Angular rules without loading Commitlint's JavaScript configuration and rule stack for every commit.

It is not a drop-in replacement for every commitlint configuration.
The comparison baseline is `@commitlint/cli` 21.2.1 with `@commitlint/config-conventional` 21.2.0 and `@commitlint/config-angular` 21.2.0, matching the packages pinned by this repository. Consult Commitlint's official [CLI](https://commitlint.js.org/reference/cli.html), [configuration](https://commitlint.js.org/reference/configuration.html), and [plugin](https://commitlint.js.org/reference/plugins.html) references for its complete feature set.

## Supported behavior
Quick Commitlint is not a drop-in replacement for every Commitlint configuration.

- Built-in `conventional` and `angular` presets matching the local commitlint 21.2 reference packages
- The 14 rules listed in the [Rules reference](docs/rules/)
- Commitlint-style severity, condition, and value tuples
- Conventional header, body, footer, scope, subject, and breaking-marker checks
- JSON rule overrides layered on a preset
- Warning-only success and rule-error failure statuses
## At a glance

| Area | Quick Commitlint | Commitlint |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Runtime | Small Node.js launcher selects a bundled native Zig linting executable; the package has no runtime npm dependencies | Node.js CLI with JavaScript packages for loading configuration, parsing, formatting, and linting |
| Default configuration | Uses the built-in `conventional` preset when no configuration is found | Normally loads discovered or supplied rules; `--default-config` can provide a Conventional fallback |
| Configuration files | Strict `.quick-commitlint.json` JSON | JS, TS, JSON, YAML, extensionless, and `package.json` or `package.yaml` configuration |
| Presets | Exactly `conventional` and `angular`, embedded in the executable | Shareable npm or local configurations composed through `extends` |
| Rules | Fixed 14-rule subset with static JSON values | Larger built-in rule set plus plugins, local rules, and function or promise values |
| Parser | Fixed native parser | Configurable parser presets and parser options |
| Ignores | Lints every supplied message | Provides default generated-message ignores and custom ignore functions |
| Inputs | Standard input or one commit-message file | Standard input, edit or environment files, the last commit, Git ranges, and ranges from the last tag |
| Output | Colored lint report on stderr; help and version on stdout | Configurable colors, formatters, quiet and verbose modes, help URLs, and strict warning/error exit codes |
| Platforms | Bundled for macOS arm64/x64, Linux arm64/x64, and Windows x64 | Runs where its supported Node.js and Git versions are available |

## Conventional and Angular presets

The repository runs differential cases against `@commitlint/cli`, `@commitlint/config-conventional`, and `@commitlint/config-angular` 21.2 to protect the intended preset behavior.
| Mode | Quick Commitlint | Commitlint reference | Tested compatibility |
| ------------ | -------------------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------- |
| Conventional | Built-in `conventional` preset, active by default | `@commitlint/config-conventional` 21.2.0 | Supported preset defaults and diagnostics are compared through `@commitlint/cli` 21.2.1 |
| Angular | Built-in `angular` preset, selected with `"preset": "angular"` | `@commitlint/config-angular` 21.2.0 | Supported preset defaults and diagnostics are compared through `@commitlint/cli` 21.2.1 |

## Deliberate differences
The differential corpus currently exercises 66 Conventional and Angular cases. It checks pass/fail behavior and expected diagnostics for the supported preset rules. This protects the intended compatibility boundary; it does not claim parity for Commitlint rules or features that Quick Commitlint does not implement.

| Area | Quick Commitlint | Full commitlint |
| --------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------- |
| Runtime | Small Node.js launcher plus a native Zig linting executable | Node.js |
| Default configuration | Built-in `conventional` when no config is found | Normally requires a discovered or supplied configuration |
| Configuration files | Strict `.quick-commitlint.json` JSON | Multiple JS/TS/JSON/YAML formats through its configuration stack |
| Presets | Exactly `conventional` and `angular` | Shareable npm configurations and `extends` |
| Rules | Fixed 14-rule subset | Larger rule set plus plugins and local rules |
| Rule values | Static JSON values | Values may be supplied by JavaScript functions and promises |
| Parser | Fixed native parser | Configurable parser presets and parser options |
| Ignores | Every message is linted | Default and custom ignore functions are available |
| Output | Colored report is always written to stderr; help/version use stdout | More output and formatting controls |
Within that boundary, Quick Commitlint supports:

- The 14-rule union listed in the [Rules reference](docs/rules/)
- The complete embedded defaults documented in the [Presets reference](docs/presets/)
- Commitlint-style severity, condition, and value tuples
- Conventional header, body, footer, scope, subject, and breaking-marker checks
- JSON rule overrides layered on either preset
- Warning-only success and rule-error failure statuses

## Configuration features not supported

Expand All @@ -46,13 +56,15 @@ Quick Commitlint does not implement:

Adding any unknown top-level key or rule is an error rather than being silently ignored.

## Parser differences
## Parser and ignore differences

The native parser expects an exact `: ` header separator and an ASCII alphanumeric or underscore type. It does not provide custom header patterns, custom scope delimiters, or multiple-scope parsing. Only a recognized final paragraph becomes the footer.

Generated commit messages—merge, revert, fixup, tag, and initial messages—are linted. If a workflow wants to ignore them, it must avoid invoking Quick Commitlint for those messages or preprocess the input before calling it.

## Choosing Quick Commitlint
For measured Conventional and Angular cold-start numbers, methodology, and reproduction steps, see the dedicated [Performance](docs/performance/) page.

## Choosing between them

Quick Commitlint is a good fit when:

Expand All @@ -61,4 +73,4 @@ Quick Commitlint is a good fit when:
- fast native linting and no additional runtime npm dependencies matter;
- macOS arm64/x64, Linux arm64/x64, or Windows x64 is the deployment platform.

Use full commitlint when the project depends on shareable npm configurations, plugins, custom parsers, custom ignores, or rules outside the supported subset.
Use Commitlint when the project depends on shareable npm configurations, plugins, custom parsers, custom ignores, Git-range linting, or rules outside the supported subset.
6 changes: 5 additions & 1 deletion projects/portal/src/app/docs/content/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ bun run package

## Benchmark

Run the cold-process benchmark against `@commitlint/cli`:
Run the cold-process benchmark against `@commitlint/cli` with both the Conventional and Angular presets:

```bash
bun run benchmark
```

The script reports the environment, median wall-clock time for each tool, and the relative improvement after three warmups and 40 measured launches per command by default. Set `BENCHMARK_ITERATIONS` to change the measured sample count.

The current reference results and methodology are published on the [Performance](docs/performance/) page.

The documentation portal is an Angular 22 static site. Run it locally with `bun run portal:start` and validate it with `bun run portal:validate`.

The pre-commit hook runs ESLint and Prettier fixes on staged TypeScript and Angular template files. Run `bun run validate` before handoff because the hook does not run the full test and build suite.
Expand Down
41 changes: 41 additions & 0 deletions projects/portal/src/app/docs/content/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Performance

Quick Commitlint runs message parsing, JSON configuration, and lint rules in a bundled native Zig executable. The npm command uses a small Node.js launcher to select that executable. Commitlint loads its Node.js configuration and linting stack in the CLI process.

## Reference cold-process benchmark

| Preset | Quick Commitlint median | Commitlint median | Improvement |
| ------------ | ----------------------: | ----------------: | ----------: |
| Conventional | 20.686 ms | 250.597 ms | 12.1× |
| Angular | 20.535 ms | 250.228 ms | 12.2× |

## Method

The table contains median wall-clock results from 40 measured launches after 3 warmups on:

- Linux x64 under WSL2
- 13th Gen Intel Core i9-13900H
- Node.js 24.18.0
- `@commitlint/cli` 21.2.1
- `@commitlint/config-conventional` and `@commitlint/config-angular` 21.2.0

Each command received the same valid message through standard input. Quick Commitlint used its built-in default for Conventional and a strict JSON file for Angular. Commitlint extended the corresponding configuration package.

This benchmark measures complete cold-process startup and one lint operation. It does not measure long-running API throughput. Results vary with the machine, operating system, filesystem, and process state, so treat the numbers as a reference run rather than a performance guarantee.

## Reproduce the benchmark

Build the release package, then run the benchmark:

```bash
bun run package
bun run benchmark
```

The command reports the environment, median time for each tool, and the relative improvement for both presets. Set `BENCHMARK_ITERATIONS` to change the measured sample count:

```bash
BENCHMARK_ITERATIONS=100 bun run benchmark
```

See [Commitlint compatibility](docs/compatibility/) for differences in configuration, extensibility, parsing, ignores, and input modes.
17 changes: 17 additions & 0 deletions projects/portal/src/app/docs/document-registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,21 @@ describe('document registry', () => {
expect(presetMarkdown).toContain('`conventional`');
expect(presetMarkdown).toContain('`angular`');
});

it('identifies the commitlint CLI and both reference preset versions', () => {
const compatibilityMarkdown = markdownFor('compatibility');
const performanceMarkdown = markdownFor('performance');

expect(compatibilityMarkdown).toContain('`@commitlint/cli` 21.2.1');
expect(compatibilityMarkdown).toContain('`@commitlint/config-conventional` 21.2.0');
expect(compatibilityMarkdown).toContain('`@commitlint/config-angular` 21.2.0');
expect(compatibilityMarkdown).toContain('[Performance](docs/performance/)');
expect(performanceMarkdown).toContain('## Reference cold-process benchmark');
expect(performanceMarkdown).toMatch(
/\|\s+Conventional\s+\|\s+\d+\.\d{3} ms\s+\|\s+\d+\.\d{3} ms\s+\|\s+\d+\.\d×\s+\|/u,
);
expect(performanceMarkdown).toMatch(
/\|\s+Angular\s+\|\s+\d+\.\d{3} ms\s+\|\s+\d+\.\d{3} ms\s+\|\s+\d+\.\d×\s+\|/u,
);
});
});
10 changes: 10 additions & 0 deletions projects/portal/src/app/docs/document-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ export const DOCUMENTS = [
heading: 'CLI reference',
load: () => import('./content/cli.md').then((module) => module.default),
},
{
path: 'performance',
label: 'Performance',
group: 'Reference',
title: 'Performance | Quick Commitlint',
description:
'Compare Quick Commitlint and Commitlint cold-process performance for Conventional and Angular presets.',
heading: 'Performance',
load: () => import('./content/performance.md').then((module) => module.default),
},
{
path: 'compatibility',
label: 'Commitlint compatibility',
Expand Down
1 change: 1 addition & 0 deletions projects/portal/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/app",
"rootDir": "src",
"types": ["node"]
},
"include": ["src/**/*.ts"],
Expand Down
1 change: 1 addition & 0 deletions projects/portal/tsconfig.spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"rootDir": "src/app",
"types": ["vitest/globals"]
},
"include": ["src/**/*.d.ts", "src/**/*.spec.ts"]
Expand Down
Loading
Loading