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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"author": "Maciej Mensfeld <maciej@mensfeld.pl>",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
"node": ">=18.3.0"
},
"dependencies": {
"fast-glob": "^3.3.2",
Expand Down
6 changes: 5 additions & 1 deletion src/output/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import type { ValidationResult, Finding, StaleReason } from '../core/types.js';

/** Inline ANSI color helpers (replaces chalk) */
const ansi = (code: number, close: number) => (s: string) => `\x1b[${code}m${s}\x1b[${close}m`;
const colorEnabled =
!('NO_COLOR' in process.env) &&
(process.stdout.isTTY === true || process.env.FORCE_COLOR !== undefined);
Comment on lines +8 to +10
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FORCE_COLOR is treated as an enable flag whenever it is present, which means FORCE_COLOR=0 will still enable ANSI output (and also won’t disable colors on TTY). If you want to support FORCE_COLOR, it should interpret the value and treat 0 as disabling colors (and optionally allow 1+ to force-enable), otherwise redirected output can unexpectedly contain ANSI sequences.

Suggested change
const colorEnabled =
!('NO_COLOR' in process.env) &&
(process.stdout.isTTY === true || process.env.FORCE_COLOR !== undefined);
const noColor = 'NO_COLOR' in process.env;
const forceColorValue = process.env.FORCE_COLOR;
let colorEnabled: boolean;
if (noColor) {
// NO_COLOR always disables colors, regardless of FORCE_COLOR or TTY
colorEnabled = false;
} else if (forceColorValue !== undefined) {
// Interpret FORCE_COLOR according to common conventions:
// - "0" => disable colors
// - "1"+ => force-enable colors
colorEnabled = forceColorValue !== '0';
} else {
// Default: enable colors only when output is a TTY
colorEnabled = process.stdout.isTTY === true;
}

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +10
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Color enablement now depends on NO_COLOR, TTY detection, and FORCE_COLOR, but this behavior isn’t covered by tests. Since CLI integration tests exist, please add cases to assert: (1) default output is uncolored when stdout is non-TTY, (2) NO_COLOR disables coloring even when forced, and (3) FORCE_COLOR forces coloring when stdout is non-TTY (including the FORCE_COLOR=0 disabling case if supported).

Suggested change
const colorEnabled =
!('NO_COLOR' in process.env) &&
(process.stdout.isTTY === true || process.env.FORCE_COLOR !== undefined);
const noColor = 'NO_COLOR' in process.env;
const forceColor = process.env.FORCE_COLOR;
const colorEnabled = !noColor && (
forceColor === '0'
? false
: forceColor !== undefined
? true
: process.stdout.isTTY === true
);

Copilot uses AI. Check for mistakes.
const ansi = (code: number, close: number) =>
colorEnabled ? (s: string) => `\x1b[${code}m${s}\x1b[${close}m` : (s: string) => s;
const gray = ansi(90, 39);
const yellow = ansi(33, 39);
const red = ansi(31, 39);
Expand Down
2 changes: 1 addition & 1 deletion src/validator/glob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function globMatches(
try {
const isMatch = picomatch(normalizedPattern, {
dot,
matchBase: !normalizedPattern.includes('/')
basename: !normalizedPattern.includes('/')
});
return files.filter((file) => isMatch(file));
} catch {
Expand Down
Loading