Skip to content

Multi-backend console formatter: ANSI + CSS, semantic palette#129

Draft
DmitrySharabin wants to merge 27 commits intomainfrom
format-console-multi-backend
Draft

Multi-backend console formatter: ANSI + CSS, semantic palette#129
DmitrySharabin wants to merge 27 commits intomainfrom
format-console-multi-backend

Conversation

@DmitrySharabin
Copy link
Copy Markdown
Member

@DmitrySharabin DmitrySharabin commented Apr 24, 2026

Summary

  • Replaces single-backend ANSI formatter in src/format-console.js with tokenizer + two emitters: ANSI (Node terminal; truecolor / 256 / strip) and CSS (browser %c styling, cross-engine).
  • Introduces src/util/palette.js as single source of truth — base 16 ANSI-named colors + semantic tokens.
  • Migrates TestResult, env/node, env/console, render, and format-diff to semantic tokens.
  • Drops chalk devDependency.

Closes #30.

What changed

src/util/format-console.js (moved from src/, rewritten)

New API:

format(str, mode?)
// mode: "truecolor" | "256" | "strip" | "css"
  • Positional second arg. Browser auto-detects "css"; Node auto-detects via env (NO_COLOR / FORCE_COLOR / COLORTERM / TERM).
  • ANSI backend returns a string; CSS backend returns [text, ...styles] to spread into console.log.
  • Tag syntax loosened: <c NAME> / <bg NAME> where NAME is a palette token (semantic or base) or hex literal (#rgb or #rrggbb).
  • Unknown colors fall through silently (matches prior behavior for typos).

src/util/palette.js (new)

Two-tier semantic system:

  • Solidpass / fail / skip / message / highlight / text
  • Tintpass-tint / fail-tint / skip-tint / message-tint (muted variants for secondary text)
  • Diffdiff-added / diff-added-tint / diff-removed / diff-removed-tint / gutter

All values hex-authored. No runtime conversion. Readable in both light and dark terminals.

Caller migration

File Change
TestResult.js Badges: <bg pass|skip|fail><c text>. Names: <c ${color}-tint>. Summary: <c pass> / <c fail>. Messages header: <c message>.
env/node.js Highlighted icon uses <c highlight>.
env/console.js format(str, "css") spread into console.log / group*.
render.js CSS array spread in details onclick.
format-diff.js (from #127) Chunk bg: diff-{added|removed}-tint. Line bg: side-specific diff-{added|removed}.

Browser support

Previous code emitted ANSI escape codes into browser console.log. Chrome rendered them; Firefox and Safari printed literal \x1b[…. CSS backend works in all three engines via %c.

Non-goals

  • Fixing Windows output issues (Janky cli test output #7 — orthogonal).
  • Third-party color library adoption (evaluated and rejected).

Test plan

  • npm test passes (self-hosted suite).
  • npm run eslint clean.
  • Visual check in light and dark terminals — PASS / FAIL / SKIP badges readable, diff highlights distinguishable.
  • Browser console check (Chrome / Firefox / Safari) via npm run dev and a failing-test details click — styled output, no raw escapes, no visible %c.

🤖 Generated with Claude Code

- Flatten c/bg symmetry via isColor/isBg + single stack selector.
- Rename foregroundStack/backgroundStack → colorStack/bgStack.
- Use findLast(Boolean) idiom over findLast(hex => hex).
- Merge defaultMode into detectMode; env default keys off IS_NODEJS so
  browser short-circuits to "truecolor" without a wrapper.
- Cache detectedMode at module load.
- Drop asymmetric empty-string early return; let tokenize handle str ?? "".
- Drop WHAT comments; add WHY notes on cubeLevels, null push, replay,
  detectMode caching.
Replace `format(str, { css, mode })` with `format(str, mode)`. Modes:
"truecolor" | "256" | "strip" | "css". Browser detection falls back to
"css" instead of "truecolor".

Updates env/console.js and tests to match. render.js and env/node.js
use defaults — unchanged.
- Chunk bg: red/green → diff-removed-emph/diff-added-emph.
- Line bg: single neutral lightblack → side-specific diff-removed/diff-added.
- Import path: ../format-console.js → ./format-console.js (sibling in src/util/).
- sides config: color → { chunk, line }; colorize reads both.
Two-tier semantic palette:
- pass/fail/skip/message — solid variant.
- pass-tint/fail-tint/skip-tint/message-tint — muted variant for
  secondary text (test names, etc.).

Rename diff-added-emph/diff-removed-emph → diff-added-tint/diff-removed-tint
for consistency with the new suffix.

TestResult.js:
- Badge bg uses <bg pass|skip|fail>; label uses <c text> (passes WCAG
  on all three bg colors).
- Test name uses <c \${color}-tint>.
- Summary: <c green>/<c red> → <c pass>/<c fail>.
- Messages header: <c yellow> → <c message>.

SKIP badge color changes from yellow to gray (skip = #a0a8b4).
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 24, 2026

Deploy Preview for h-test ready!

Name Link
🔨 Latest commit d5f24d0
🔍 Latest deploy log https://app.netlify.com/projects/h-test/deploys/69f0b29f163d610008a3f91e
😎 Deploy Preview https://deploy-preview-129--h-test.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

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.

Use a third-party library for Terminal colors?

1 participant