An ESLint plugin to enforce standard style for Commander.js option flags.
- Format Check: Ensures flags are in the format
-[char], --[word](or just one of them). - Internal Order: Enforces short flags to come before long flags (e.g.,
-p, --portinstead of--port, -p). - Alphabetical Sorting: Enforces chained
.option()calls to be sorted alphabetically by flag name.
You'll first need to install ESLint:
npm i eslint --save-devNext, install eslint-plugin-commander-option-flags:
npm install eslint-plugin-commander-option-flags --save-devThis project pins the Node.js and npm versions using Volta. It is highly recommended to install Volta to ensure you are using the correct versions automatically.
Once you have Volta installed, just cd into the project directory, and Volta will switch to the pinned Node.js version.
Add commander-option-flags to the plugins section of your .eslintrc configuration file. You can omit the eslint-plugin- prefix:
{
"plugins": [
"commander-option-flags"
],
"rules": {
"commander-option-flags/commander-option-flags": "warn"
}
}The rule accepts an optional object to configure the sorting order:
order:"long"(default) or"short". Determines whether to sort based on the long flag name or the short flag name.
"commander-option-flags/commander-option-flags": ["warn", { "order": "long" }]👎 Incorrect
program
.option('--banana, -b') // Invalid order within string
.option('-a, --apple') // Not sorted relative to previous
.option('--port, -p <number>') // Long flag before short flag
.option('port <number>') // Missing hyphens
.option('-a, -b, --c') // Too many parts
.option('-x, -x') // Duplicate short flags
.option('--verbose, --verbose') // Duplicate long flags👍 Correct
program
.option('-a, --apple')
.option('-b, --banana')
.option('-p, --port <number>')
.option('-s', 'short only')
.option('--long', 'long only')The core logic is located in lib/rules/commander-option-flags.js. Here is a high-level overview of how it works:
- AST Traversal: The rule listens for
CallExpressionnodes to identify calls to.option(). It specifically checks if the callee is aMemberExpressionwith the property nameoption. - Flag Parsing: It extracts the first argument (the flags string, e.g.,
"-p, --port <number>") and cleans it by removing argument placeholders (like<path>or[value]). The remaining string is split to identify potential short (-s) and long (--long) flags. - Validation Phases:
- Format Check: Verifies that the flags strictly match the
-[char]or--[word]patterns and ensures no duplicates exist. - Internal Order Check: Checks if both short and long flags are present. If so, it verifies that the short flag appears before the long flag in the string.
- Sorting Check: It inspects the parent object to find the preceding chained call. If the previous call was also an
.option(), it compares their flag names alphabetically (based on theorderconfiguration).
- Format Check: Verifies that the flags strictly match the
- Autofix Mechanism:
- Internal Reordering: Reconstructs the flag string with the short flag first, preserving any trailing arguments.
- Sorting: Uses
fixer.replaceTextRangeto swap the entire code range of the current.option(...)call with the preceding one.
This plugin works with TypeScript files parsed by @typescript-eslint/parser.
MIT