diff --git a/ext/node/polyfills/internal/util/inspect.mjs b/ext/node/polyfills/internal/util/inspect.mjs index e9b65ee5119e29..b156a9b711fe08 100644 --- a/ext/node/polyfills/internal/util/inspect.mjs +++ b/ext/node/polyfills/internal/util/inspect.mjs @@ -676,6 +676,14 @@ function styleText(format, text, options) { stream, ); } + // Node's util.styleText returns the text unchanged when the target stream + // is not a TTY, so callers can pass any writable and only get color when + // the destination would render it. + if ( + stream !== undefined && stream !== null && !stream.isTTY + ) { + return text; + } } const formatArray = ArrayIsArray(format) ? format : [format]; diff --git a/libs/npm_installer/resolution.rs b/libs/npm_installer/resolution.rs index c24cd83f0dc3a4..65e9610ae04b9e 100644 --- a/libs/npm_installer/resolution.rs +++ b/libs/npm_installer/resolution.rs @@ -410,7 +410,8 @@ fn peer_dep_diagnostics_to_display_tree( // now output it let mut root_node = DisplayTreeNode { text: format!( - "{} The following peer dependency issues were found:", + "{} The following peer dependency issues were found.\n\ + To resolve, pin the affected package(s) under \"overrides\" in your package.json (https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides):", colors::yellow("Warning") ), children: Vec::new(), diff --git a/tests/specs/install/peer_dep_specific_constraint/install.out b/tests/specs/install/peer_dep_specific_constraint/install.out index d0547b9cf13284..50711dc956400b 100644 --- a/tests/specs/install/peer_dep_specific_constraint/install.out +++ b/tests/specs/install/peer_dep_specific_constraint/install.out @@ -1,6 +1,7 @@ Download http://localhost:4260/@denotest%2fadd Download http://localhost:4260/@denotest%2fpeer-dep-specific-constraint -Warning The following peer dependency issues were found: +Warning The following peer dependency issues were found. + To resolve, pin the affected package(s) under "overrides" in your package.json (https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides): └─┬ @denotest/peer-dep-specific-constraint@1.0.0 └── peer @denotest/add@0.5: resolved to 1.0.0 diff --git a/tests/unit_node/util_test.ts b/tests/unit_node/util_test.ts index d0821966c7e742..faee2183218f9e 100644 --- a/tests/unit_node/util_test.ts +++ b/tests/unit_node/util_test.ts @@ -271,6 +271,31 @@ Deno.test("[util] styleText() with array of formats", () => { assertEquals(colored, "\x1b[31m\x1b[32merror\x1b[39m\x1b[39m"); }); +Deno.test("[util] styleText() respects stream.isTTY", () => { + const streamTTY = { write() {}, isTTY: true }; + const streamNoTTY = { write() {}, isTTY: false }; + + assertEquals( + util.styleText("bgYellow", "TTY", { stream: streamTTY }), + "\x1b[43mTTY\x1b[49m", + ); + assertEquals( + util.styleText("bgYellow", "No TTY", { stream: streamNoTTY }), + "No TTY", + ); +}); + +Deno.test("[util] styleText() with validateStream: false bypasses isTTY check", () => { + const streamNoTTY = { write() {}, isTTY: false }; + assertEquals( + util.styleText("bgYellow", "forced", { + stream: streamNoTTY, + validateStream: false, + }), + "\x1b[43mforced\x1b[49m", + ); +}); + Deno.test("[util] stripVTControlCharacters() removes OSC 8 hyperlinks", () => { // OSC 8 hyperlink with ESC \ (ST) terminator const input =