Skip to content

Add parseAnsiStyles to resolve ANSI SGR codes into styled text runs - #279

Closed
nev21 with Copilot wants to merge 3 commits into
mainfrom
copilot/feature-add-parser-for-ansi-sgr-codes
Closed

nev21 with Copilot wants to merge 3 commits into
mainfrom
copilot/feature-add-parser-for-ansi-sgr-codes

Conversation

Copilot AI commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

chromacon can locate escape sequences but not say what they do, so consumers rendering coloured output outside a terminal (HTML log panels, SVG, reports) each write their own SGR interpreter. This adds a parser that resolves SGR codes into styled runs, plus supporting helpers.

parseAnsiStyles("\x1b[1;31mFAIL\x1b[22m still red\x1b[0m plain");
// [
//   { text: "FAIL",       style: { bold: true, fg: { type: "basic", index: 1 } } },
//   { text: " still red", style: { fg: { type: "basic", index: 1 } } },
//   { text: " plain",     style: {} }
// ]
  • parseAnsiStyles(value, state?) (ansi/parseAnsiStyles.ts)
    • Resolves the SGR attributes and resets listed in the issue (bold, dim, italic, underline/double, blink, inverse, hidden, strikethrough, overline, fg/bg/underline colour).
    • Reads multi-parameter sequences, and extended colours in both semicolon and colon (ITU) forms.
    • 38;5;n with n < 16 is reported as basic. Malformed or out-of-range colours are ignored.
    • Handles the 8-bit CSI \x9b, drops non-SGR sequences, and exposes OSC 8 as style.link.
    • Merges adjacent runs with the same style and omits empty runs.
    • state is cloned, not mutated.
    • createAnsiStyleParser() is a stateful push(chunk) / state() wrapper for line-at-a-time input.
  • Colour helpers (ansi/ansiColors.ts): ansi256ToRgb (xterm 6×6×6 cube and greyscale ramp, with an overridable 0–15 palette), ansiColorToCss, and DEFAULT_ANSI_PALETTE.
  • getSgrName(code) (ansi/sgrCodes.ts) gives a runtime lookup of SGR code names. CSIColors stays a const enum. The names are newly chosen (e.g. fgRed, bgBrightBlue), so reviewers may want to weigh in on them.
  • ansiToHtml(value, options?) (ansi/ansiToHtml.ts) is a separate module for tree-shaking.
    • HTML-escapes text.
    • Emits class-based (ansi- prefix by default) or inline-style spans.
    • Emits OSC 8 links as <a rel="noopener noreferrer">. Links can be disabled, and javascript:, data: and vbscript: URLs are never emitted as links.
  • All new symbols are exported from index.ts. The implementation avoids object spread and adds no new dependencies, to stay ES5-friendly.
  • Tests in test/src/ansi/parseAnsiStyles.test.ts cover the issue's test table plus the helpers, getSgrName, the stateful parser and ansiToHtml.

Not done:

  • No CHANGELIST.md entry.
  • The repo's own build, lint and test targets were not run, because core has no installed dependencies in this environment.

Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com>
Copilot AI changed the title [WIP] Add parser that resolves ANSI SGR codes into styled text runs Add parseAnsiStyles to resolve ANSI SGR codes into styled text runs Oct 27, 2026
Copilot AI requested a review from nev21 October 27, 2026 17:04
Comment thread core/src/ansi/parseAnsiStyles.ts Resolved
Comment thread core/src/ansi/ansiColors.ts Resolved
Co-authored-by: nev21 <82737406+nev21@users.noreply.github.com>
Copilot AI requested a review from nev21 October 28, 2026 06:28
@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 8.12183% with 181 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.92%. Comparing base (4559e38) to head (fe13c1c).

Files with missing lines Patch % Lines
core/src/ansi/parseAnsiStyles.ts 4.95% 115 Missing ⚠️
core/src/ansi/ansiToHtml.ts 7.69% 36 Missing ⚠️
core/src/ansi/ansiColors.ts 19.04% 17 Missing ⚠️
core/src/ansi/sgrCodes.ts 18.75% 13 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (4559e38) and HEAD (fe13c1c). Click for more details.

HEAD has 3 uploads less than BASE
Flag BASE (4559e38) HEAD (fe13c1c)
4 1
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #279       +/-   ##
===========================================
- Coverage   89.86%   49.92%   -39.94%     
===========================================
  Files          23       27        +4     
  Lines         513      709      +196     
  Branches      138      213       +75     
===========================================
- Hits          461      354      -107     
- Misses         52      355      +303     
Files with missing lines Coverage Δ
core/src/ansi/sgrCodes.ts 18.75% <18.75%> (ø)
core/src/ansi/ansiColors.ts 19.04% <19.04%> (ø)
core/src/ansi/ansiToHtml.ts 7.69% <7.69%> (ø)
core/src/ansi/parseAnsiStyles.ts 4.95% <4.95%> (ø)

... and 12 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.


function _copy<T extends object>(src: T): T {
const result: any = {};
Object.keys(src).forEach((k) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot, you should be using the ts-utils helpers for ALL of these

@nev21

nev21 commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Taking over and implementing a fuller solution

@nev21 nev21 closed this Oct 28, 2026
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.

[Feature] Add a parser that resolves ANSI SGR codes into styled text runs

2 participants