Skip to content

feat: export getColorContrastContext for LLM-assisted color-contrast fixes Description:#714

Draft
younglim wants to merge 1 commit intomasterfrom
feat/color-contrast-for-scanPage-scanHTML
Draft

feat: export getColorContrastContext for LLM-assisted color-contrast fixes Description:#714
younglim wants to merge 1 commit intomasterfrom
feat/color-contrast-for-scanPage-scanHTML

Conversation

@younglim
Copy link
Copy Markdown
Collaborator

What

Adds a new named export getColorContrastContext to npmIndex that enriches color-contrast and
color-contrast-enhanced violations with structured, mathematically-computed data for LLM consumption.

Why

LLMs cannot reliably fix color-contrast violations by guessing. Without the actual foreground/background
values and contrast ratio, models apply heuristic darkening that frequently undershoots the required
threshold or adjusts in the wrong direction. This was validated across 90 failures in eval runs — the
root cause in every case was the LLM not knowing the exact colors or the required ratio.

Axe already computes this data (fgColor, bgColor, contrastRatio, fontSize, fontWeight) but it
is discarded when violations are filtered into ItemsInfo. This function recovers it by parsing the
failureSummary message that is preserved in the scan results.

How

getColorContrastContext(scanResults) accepts the output of scanPage or scanHTML and returns
ColorContrastFinding[]. For each violation it:

  1. Parses the axe failureSummary string to extract the foreground, background, actual ratio, required
    ratio, font size and weight
  2. Determines whether the element qualifies as large text (≥ 24px normal, ≥ 18.67px bold) which changes
    the required threshold
  3. Walks the HSL lightness channel of both the foreground and background independently until the required
    ratio is met, returning two pre-computed compliant hex alternatives
  4. Flags the WCAG level (AA for color-contrast, AAA for color-contrast-enhanced)

WCAG relative luminance and contrast ratio math is implemented inline with no new dependencies.

Usage

const results = await scanPage(page, config);
const findings = getColorContrastContext(results);
// pass findings to LLM — no guessing required

No breaking changes
scanPage and scanHTML return types are unchanged. This is purely additive.

This PR adds...

  • I've kept this PR as small as possible (~500 lines) by splitting it into PRs with manageable chunks of code
  • I've requested reviews from 1 reviewer
  • I've tested existing features (website scan, sitemap, custom flow) in both node index and cli
  • I've synced this fork with GovTechSG repo
  • I've added/updated unit tests
  • I've added/updated any necessary dependencies in package[-lock].json npm audit, portable installation on GitHub Actions

…ches color-contrast and color-contrast-enhanced violations with structured, mathematically-computed data for LLM consumption.
@younglim younglim marked this pull request as draft April 21, 2026 11:14
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.

1 participant