From 620402c2b639eee73a89769cd214c34c1f1abb83 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 17 Mar 2026 22:36:11 +0000 Subject: [PATCH 1/2] Convert coverage-dir from named option to positional argument Breaking change: `--coverage-dir=` is replaced by a positional argument, e.g. `css-coverage ./coverage --min-coverage=0.8`. Updates argument parsing, validation error messages, tests, and help text. https://claude.ai/code/session_01HyhRGi53stHdRSZBkxTAeQ --- src/cli/arguments.test.ts | 28 ++++++++++++---------------- src/cli/arguments.ts | 10 +++++----- src/cli/help.ts | 12 +++++++----- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/cli/arguments.test.ts b/src/cli/arguments.test.ts index b9ca987..3efaa3e 100644 --- a/src/cli/arguments.test.ts +++ b/src/cli/arguments.test.ts @@ -2,33 +2,29 @@ import { test, expect } from '@playwright/test' import { resolve } from 'node:path' import { parse_arguments } from './arguments' -test.describe('--coverage-dir', () => { +test.describe('', () => { let cov = '--min-coverage=1' - test('missing --coverage-dir', () => { + test('missing coverage-dir', () => { expect(() => parse_arguments([cov])).toThrowError() }) - test('empty --coverage-dir', () => { - expect(() => parse_arguments([cov, '--coverage-dir'])).toThrowError() - }) - - test('valid --coverage-dir=coverage', () => { - let result = parse_arguments([cov, '--coverage-dir=coverage']) + test('valid coverage-dir positional', () => { + let result = parse_arguments(['coverage', cov]) expect(result['coverage-dir']).toEqual(resolve('coverage')) }) - test('path traversal --coverage-dir=../../etc', () => { - expect(() => parse_arguments([cov, '--coverage-dir=../../etc'])).toThrowError() + test('path traversal ../../etc', () => { + expect(() => parse_arguments(['../../etc', cov])).toThrowError() }) - test('path traversal --coverage-dir=../sibling', () => { - expect(() => parse_arguments([cov, '--coverage-dir=../sibling'])).toThrowError() + test('path traversal ../sibling', () => { + expect(() => parse_arguments(['../sibling', cov])).toThrowError() }) }) test.describe('--min-coverage', () => { - let dir = '--coverage-dir=coverage' + let dir = 'coverage' test('missing --min-coverage', () => { expect(() => parse_arguments([dir])).toThrowError() @@ -49,7 +45,7 @@ test.describe('--min-coverage', () => { }) test.describe('--min-file-coverage', () => { - let args = ['--coverage-dir=coverage', '--min-coverage=1'] + let args = ['coverage', '--min-coverage=1'] test('missing --min-file-coverage defaults to 0', () => { let result = parse_arguments([...args]) @@ -71,7 +67,7 @@ test.describe('--min-file-coverage', () => { }) test.describe('--reporter', () => { - let args = ['--coverage-dir=coverage', '--min-coverage=1'] + let args = ['coverage', '--min-coverage=1'] test('missing --reporter defaults to pretty', () => { let result = parse_arguments([...args]) @@ -98,7 +94,7 @@ test.describe('--reporter', () => { }) test.describe('--show-uncovered', () => { - let args = ['--coverage-dir=coverage', '--min-coverage=1'] + let args = ['coverage', '--min-coverage=1'] test('missing --show-uncovered defaults to violations', () => { let result = parse_arguments([...args]) diff --git a/src/cli/arguments.ts b/src/cli/arguments.ts index 5de66cf..d027db8 100644 --- a/src/cli/arguments.ts +++ b/src/cli/arguments.ts @@ -16,10 +16,10 @@ export type CliArguments = { } export function parse_arguments(args: string[]): CliArguments { - let { values } = parseArgs({ + let { values, positionals } = parseArgs({ args, + allowPositionals: true, options: { - 'coverage-dir': { type: 'string' }, 'min-coverage': { type: 'string' }, 'min-file-coverage': { type: 'string', default: '0' }, 'show-uncovered': { type: 'string', default: 'violations' }, @@ -29,9 +29,9 @@ export function parse_arguments(args: string[]): CliArguments { let issues: string[] = [] - let coverage_dir = values['coverage-dir'] + let coverage_dir = positionals[0] if (!coverage_dir) { - issues.push('--coverage-dir is required') + issues.push(' is required') } else { let resolved = resolve(coverage_dir) let cwd = process.cwd() @@ -70,7 +70,7 @@ export function parse_arguments(args: string[]): CliArguments { } return { - 'coverage-dir': resolve(coverage_dir!), + 'coverage-dir': resolve(coverage_dir), 'min-coverage': min_coverage, 'min-file-coverage': min_file_coverage, 'show-uncovered': show_uncovered, diff --git a/src/cli/help.ts b/src/cli/help.ts index 07f99cd..48bf040 100644 --- a/src/cli/help.ts +++ b/src/cli/help.ts @@ -3,11 +3,13 @@ import { styleText } from 'node:util' export function help() { return ` ${styleText(['bold'], 'USAGE')} - $ css-coverage --coverage-dir= --min-coverage= [options] + $ css-coverage --min-coverage= [options] + +${styleText('bold', 'ARGUMENTS')} + Where your Coverage JSON files are ${styleText('bold', 'OPTIONS')} Required: - --coverage-dir Where your Coverage JSON files are --min-coverage Minimum overall CSS coverage [0-1] Optional: @@ -26,12 +28,12 @@ Optional: ${styleText('bold', 'EXAMPLES')} ${styleText('dim', '# analyze all .json files in ./coverage; require 80% overall coverage')} - $ css-coverage --coverage-dir=./coverage --min-coverage=0.8 + $ css-coverage ./coverage --min-coverage=0.8 ${styleText('dim', '# Require 50% coverage per file')} - $ css-coverage --coverage-dir=./coverage --min-coverage=0.8 --min-file-coverage=0.5 + $ css-coverage ./coverage --min-coverage=0.8 --min-file-coverage=0.5 ${styleText('dim', 'Report JSON')} - $ css-coverage --coverage-dir=./coverage --min-coverage=0.8 --reporter=json + $ css-coverage ./coverage --min-coverage=0.8 --reporter=json `.trim() } From ddf03cb25b87405069c6586098b33c7cad4a4e2e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 17 Mar 2026 22:40:52 +0000 Subject: [PATCH 2/2] Fix TS2345: restore non-null assertion on coverage_dir in return positionals[0] is string | undefined; the assertion is safe because we throw before reaching the return when coverage_dir is missing. https://claude.ai/code/session_01HyhRGi53stHdRSZBkxTAeQ --- src/cli/arguments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/arguments.ts b/src/cli/arguments.ts index d027db8..735c45c 100644 --- a/src/cli/arguments.ts +++ b/src/cli/arguments.ts @@ -70,7 +70,7 @@ export function parse_arguments(args: string[]): CliArguments { } return { - 'coverage-dir': resolve(coverage_dir), + 'coverage-dir': resolve(coverage_dir!), 'min-coverage': min_coverage, 'min-file-coverage': min_file_coverage, 'show-uncovered': show_uncovered,