Visitar URL original
Replace picocolors with node:util styleText by mrpmohiburrahman · Pull Request #2139 · postcss/postcss · GitHub
Skip to content

Replace picocolors with node:util styleText - #2139

Open
mrpmohiburrahman wants to merge 2 commits into
postcss:mainfrom
mrpmohiburrahman:fix/replace-picocolors-with-node-styletext
Open

mrpmohiburrahman wants to merge 2 commits into
postcss:mainfrom
mrpmohiburrahman:fix/replace-picocolors-with-node-styletext

Conversation

@mrpmohiburrahman

Copy link
Copy Markdown

Fixes #2116

picocolors was only there to color terminal output, and node:util does the
same job, so this drops it from dependencies. New lib/colors.js exports a
createColor(...formats) factory plus an isColorSupported flag, modelled on
the colors.js in size-limit; the three call sites keep their text => string
shape, so HIGHLIGHT_THEME and showSourceCode() are unchanged in structure.

Rather than eyeball the output, I diffed it against picocolors byte for byte —
old and new showSourceCode() and showSourceCode(true) are identical across
9 environments (piped, FORCE_COLOR, NO_COLOR, CI, TERM=dumb, --color,
and the empty-string variants of each). The empty-string cases are why the
detector uses truthiness rather than presence: NO_COLOR="" must not disable
color, per no-color.org and picocolors.

Two details worth flagging, both of which changed the code:

  • styleText accepts an array of formats only since 20.13, not 20.12.
    On 20.12.x, createColor('bold', 'red') throws ERR_INVALID_ARG_VALUE —
    while formatting a syntax error, which is the worst possible moment. So the
    guard is a feature detect, not a version check.
  • ./lib/terminal-highlight is a published entry in exports, and its old
    pico.yellow values were no-ops when color was unsupported. The theme is
    gated on isColorSupported so direct importers keep that contract.

size-limit drops 16.38 kB → 16.18 kB, so I lowered the budget to 16.25 kB.
New test/colors.test.ts covers the detection signals and the degrade path;
I checked it is not vacuous by breaking the code four ways and confirming a
specific test goes red each time.

One thing I need you to decide

This is the conservative version: on Node < 20.13 the module degrades to plain
text, the color assertions degrade with it, every CI leg stays green, and
engines is untouched. The cost is a real regression — error output loses
its color on Node 14, 16, 18 and 20.0–20.12
, where picocolors colored fine.
It degrades silently rather than throwing.

If 9.0 is bumping the Node floor anyway, the other version is smaller and
cleaner: engines → >=20.13, prune the old matrix to 20, and delete the
fallback branch entirely. I did not want to make that call on your behalf.
Say which you prefer and I will rewrite this.

picocolors was only used to color terminal output, and node:util can do
the same since styleText() landed in Node.js 20.12. The new lib/colors.js
exports a createColor(...formats) factory and an isColorSupported flag,
so the three call sites keep their text => string shape.

Formats are combined in a single call rather than nested, because Node
re-opens the parent style after a nested one only since 22.19 and 24.5.
Arrays of formats are themselves supported only since 20.13, so the
guard is a feature detect rather than a version check: on 20.12
createColor('bold', 'red') would throw ERR_INVALID_ARG_VALUE while
formatting a syntax error.

Where styleText is missing the module degrades to plain text and the
color assertions degrade with it, so the old Node legs stay green and
engines is untouched.

lib/colors.js is stubbed in the browser map, so no Node builtin reaches
the browser bundle and showSourceCode() falls back to its identity
helpers there. HIGHLIGHT_THEME stays gated on isColorSupported because
./lib/terminal-highlight is a published export whose colors were
no-ops without color support.
Comment thread lib/colors.js Outdated

// util.styleText() was added in Node.js 20.12, but it accepts an array
// of formats only since 20.13. Detect what we actually use.
let hasStyleText = typeof styleText === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No, we do not need it. We will work with >=22 in PostCSS 9.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — the detect and the plain-text fallback are gone, and engines is now >=22.

Heads-up on CI: the old job now runs entirely below that floor. Node 20 still passes (setup-node resolves it to 20.19, which has styleText and the array form), but 10, 12, 14, 16 and 18 have no styleText at all, so those five legs fail by design. I left .github/workflows/ alone since that job is yours to decide on — happy to drop it here, along with test/old-node.js and the old script, if you want that in this PR.

One detail worth knowing: eslint-plugin-n still flags util.styleText because it treats it as experimental until 23.5, so I kept the node-builtins ignore entry. >=22.13 doesn't clear it either — I checked.

PostCSS 9 will work with Node.js >=22, so the feature detect and the
plain-text fallback are not needed: styleText() exists since 20.12 and
accepts an array of formats since 20.13, both well below the new floor.

Formats are still combined in a single call, because Node re-opens the
parent style after a nested one only since 22.19 and 24.5.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove colors lib

2 participants