Skip to content

fix: patch hljs markdown grammar and re-enable for diff view#388

Merged
tomasz-tomczyk merged 2 commits intomainfrom
fix/hljs-markdown-patches
Apr 29, 2026
Merged

fix: patch hljs markdown grammar and re-enable for diff view#388
tomasz-tomczyk merged 2 commits intomainfrom
fix/hljs-markdown-patches

Conversation

@tomasz-tomczyk
Copy link
Copy Markdown
Owner

Summary

Restores markdown syntax highlighting (#375). PR #283 disabled it because hljs's stock grammar produced cascading visual bugs on common markdown content. Rather than ship without the feature, vendor a patched grammar that overrides the upstream registration after load.

frontend/highlight-markdown-patch.js re-registers markdown with four fixes:

  • hljs#4279 — intraword underscores no longer trigger italic/bold (snake_case, flutter_eval, :no_entry:, _id stay plain). Lookbehind/lookahead enforce non-alphanumeric flanks. Asterisk variants unchanged (CommonMark allows intraword *).
  • hljs#3719 — bare ***/---/___ lines render as horizontal rule, not bold. Tightened to full-line match; reordered before BOLD in contains[].
  • Italic bleed across code spans — moved CODE ahead of BOLD/ITALIC so backtick spans are consumed first. Tightened asterisk patterns to require same-line closer + lookbehind so **/*.go (no closing **) doesn't open a runaway span.
  • Setext heading false-positives — YAML frontmatter --- and list-item-followed-by---- no longer match setext heading. Per CommonMark §4.3, setext heading text must be a paragraph (not list/blockquote/ATX/ordered-list/indented code). Tightened the upper-line lookahead.

Wired into the bundle via copy-deps.js (appended after upstream languages so it overrides). Markdown files are also now pre-highlighted in diff view (extends the gate at app.js:410 and :750); buildCodeLineBlocks stays gated to code-only. The lang === 'markdown' skip guard in the markdown-it highlight callback is removed.

frontend/test-markdown-patch.mjs runs 30 vm-sandboxed assertions covering all four bug classes plus regression checks (**bold**, *italic*, ***bold-italic***, ATX headings, legitimate setext, code spans). Run with node frontend/test-markdown-patch.mjs.

Review

  • Code review: passed (4 NOTEs, 0 blockers — lookbehind compat documented, upstream tab-in-charclass quirk preserved, setext lookahead O(n) acceptable, test not yet in CI)
  • Parity port to crit-web: in progress on tomasz-tomczyk/crit-web branch fix/hljs-markdown-patches

Test plan

  • make test (go test -race -count=1 ./...) — passing
  • node frontend/test-markdown-patch.mjs — 30/30 passing
  • Manual: make test-diff rendered the screenshot fixture (nested \``markdown` fence, snake_case, YAML frontmatter delimiters) cleanly
  • golangci-lint, ESLint (1 pre-existing warning), Stylelint, CSS-vars check — all clean via pre-commit

Notes

  • Lookbehind requires Chrome 62+/Safari 16.4+/Firefox 78+ — fine for crit's audience.
  • When a future @highlightjs/cdn-assets bump silently changes the upstream grammar, the patch may need re-syncing. The smoke test catches that — consider wiring it into update-deps or CI later.

🤖 Generated with Claude Code

Restores markdown syntax highlighting (PR #283 had disabled it because
hljs's stock grammar mangled snake_case identifiers, bare ***/---/___
lines, code spans containing emphasis chars, and treated YAML frontmatter
delimiters as setext heading underlines).

Adds frontend/highlight-markdown-patch.js — a vendored grammar override
re-registered after the upstream language file loads. Fixes:

- hljs#4279: intraword underscores no longer trigger italic/bold (snake_case,
  flutter_eval, ⛔ stay plain)
- hljs#3719: bare ***/---/___ lines render as horizontal rule, not bold
- code spans (\`*foo*\`) consumed before emphasis matchers — no italic bleed
- setext headings reject upper lines that are list items / blockquotes /
  ATX headers / ordered lists / indented code (per CommonMark §4.3),
  fixing YAML frontmatter false-positives

Wired through copy-deps.js to append after languages bundle. Markdown
files are now also pre-highlighted in diff view (preHighlightFile and
the call-site gate in app.js). Removes the markdown skip guard from
the markdown-it highlight callbacks.

frontend/test-markdown-patch.mjs runs 30 vm-sandboxed assertions against
the bundled grammar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.59%. Comparing base (41ad343) to head (f79cda5).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #388      +/-   ##
==========================================
+ Coverage   66.58%   66.59%   +0.01%     
==========================================
  Files          19       19              
  Lines        8176     8176              
==========================================
+ Hits         5444     5445       +1     
+ Misses       2310     2309       -1     
  Partials      422      422              
Flag Coverage Δ
e2e 34.07% <ø> (ø)
unit 62.61% <ø> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 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.

axe-core flagged hljs-quote (#22863a) on .addition (#dafbe1) at 4.15:1
contrast — fails WCAG AA (needs 4.5:1). Same color is shared with
hljs-name, hljs-selector-pseudo, hljs-selector-tag. Darken all four
to fg-default (#1f2328) when nested inside .addition rows in light
theme. Mirrors the existing .diff-word-del + hljs-* override pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tomasz-tomczyk added a commit to tomasz-tomczyk/crit-web that referenced this pull request Apr 29, 2026
Mirrors tomasz-tomczyk/crit fix — hljs-quote/name/selector-pseudo/
selector-tag (#22863a) on .addition (#dafbe1) fails WCAG AA at 4.15:1.
Darken to fg-default (#1f2328) when nested inside .addition rows in
light theme.

See also: tomasz-tomczyk/crit#388

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tomasz-tomczyk added a commit to tomasz-tomczyk/crit-web that referenced this pull request Apr 29, 2026
* fix: patch hljs markdown grammar and re-enable for fenced blocks

Ports the hljs markdown grammar fix from tomasz-tomczyk/crit#388 to
keep the review page in parity. Hosted reviews now syntax-highlight
nested ```markdown fences without the cascading visual bugs that
caused PR #283 (in crit) to disable markdown highlighting.

Adds assets/js/highlight-markdown-patch.js — exports
registerMarkdownPatch(hljs) which re-registers the markdown language
with four fixes:

- hljs#4279: intraword underscores no longer trigger italic/bold
- hljs#3719: bare ***/---/___ lines render as horizontal rule, not bold
- code spans consumed before emphasis matchers (no italic bleed)
- setext headings reject upper lines that aren't paragraphs (per
  CommonMark §4.3) — fixes YAML frontmatter false-positives

The patch is registered at the top of document-renderer.js, immediately
after `import hljs from "highlight.js"` and before any hljs.highlight()
call. esbuild bundles document-renderer.js as a chunk only loaded on
/r/:token, so the patch is applied exactly once per review-page mount.

Also removes the `lang === 'markdown'` skip guard from the markdown-it
highlight() callback, mirroring the same change in crit/.

assets/test-markdown-patch.mjs runs 30 vm-sandboxed assertions covering
all four bug classes plus regressions. Run with
`node assets/test-markdown-patch.mjs`.

See also: tomasz-tomczyk/crit#388

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: AA contrast for green hljs groups on addition rows in light theme

Mirrors tomasz-tomczyk/crit fix — hljs-quote/name/selector-pseudo/
selector-tag (#22863a) on .addition (#dafbe1) fails WCAG AA at 4.15:1.
Darken to fg-default (#1f2328) when nested inside .addition rows in
light theme.

See also: tomasz-tomczyk/crit#388

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tomasz-tomczyk tomasz-tomczyk merged commit 57c7a3d into main Apr 29, 2026
5 of 6 checks passed
@tomasz-tomczyk tomasz-tomczyk deleted the fix/hljs-markdown-patches branch April 29, 2026 10:32
tomasz-tomczyk added a commit that referenced this pull request Apr 29, 2026
* fix: patch hljs markdown grammar and re-enable for diff view

Restores markdown syntax highlighting (PR #283 had disabled it because
hljs's stock grammar mangled snake_case identifiers, bare ***/---/___
lines, code spans containing emphasis chars, and treated YAML frontmatter
delimiters as setext heading underlines).

Adds frontend/highlight-markdown-patch.js — a vendored grammar override
re-registered after the upstream language file loads. Fixes:

- hljs#4279: intraword underscores no longer trigger italic/bold (snake_case,
  flutter_eval, ⛔ stay plain)
- hljs#3719: bare ***/---/___ lines render as horizontal rule, not bold
- code spans (\`*foo*\`) consumed before emphasis matchers — no italic bleed
- setext headings reject upper lines that are list items / blockquotes /
  ATX headers / ordered lists / indented code (per CommonMark §4.3),
  fixing YAML frontmatter false-positives

Wired through copy-deps.js to append after languages bundle. Markdown
files are now also pre-highlighted in diff view (preHighlightFile and
the call-site gate in app.js). Removes the markdown skip guard from
the markdown-it highlight callbacks.

frontend/test-markdown-patch.mjs runs 30 vm-sandboxed assertions against
the bundled grammar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: AA contrast for green hljs groups on addition rows in light theme

axe-core flagged hljs-quote (#22863a) on .addition (#dafbe1) at 4.15:1
contrast — fails WCAG AA (needs 4.5:1). Same color is shared with
hljs-name, hljs-selector-pseudo, hljs-selector-tag. Darken all four
to fg-default (#1f2328) when nested inside .addition rows in light
theme. Mirrors the existing .diff-word-del + hljs-* override pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Test <test@test.com>
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