Skip to content

feat(parser): add code block title and line highlighting - #41

Merged
engineervix merged 3 commits into
engineervix:mainfrom
beatriz-dominguez-bot:feat/code-block-title-and-highlight
Jul 6, 2026
Merged

feat(parser): add code block title and line highlighting#41
engineervix merged 3 commits into
engineervix:mainfrom
beatriz-dominguez-bot:feat/code-block-title-and-highlight

Conversation

@beatriz-dominguez-bot

@beatriz-dominguez-bot beatriz-dominguez-bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds two new capabilities to the parser for fenced code blocks:

  • Code block titles: via the title attribute (e.g. ```go title="main.go"`), rendered as a header above the block.
  • Line highlighting: via the `hl` attribute (e.g. ```go hl="2-4,7"`), which highlights specific line ranges in the rendered output.

Changes

File Change
`assets/theme.css` +56 lines — highlight glow styles
`docs/guide/03-markdown.md` +81 lines — documentation
`internal/parser/doc.go` +6 lines — title field on `CodeBlock`
`internal/parser/highlight.go` +614 lines — highlight line parsing and rendering
`internal/parser/highlight_test.go` +242 lines — test coverage
`internal/parser/parse.go` +2 lines — parse title attribute
`internal/parser/parser_test.go` +262 lines — parse test cases

Implements github.com/engineervix/issues/6

- title="..." attribute renders a <figure class="code-block"> with a
  <div class="code-title"> header bar above the <pre>.
- {n,m-p} attribute highlights specific lines (1-indexed) with a
  <span class="highlight-line"> class (accent bg + left border).
- Both can be combined on the same fence.
- Plain code blocks (no custom attrs) are untouched.

Implementation:
- Extends internal/parser/highlight.go via AST transformer (priority 200)
  and custom NodeRenderer.
- Chroma is called directly with line numbers; HTML post-processed to
  inject highlight-line class.
- 28 new unit tests covering all combinations and edge cases.
- CSS rules for .code-block / .code-title / .code-body / .highlight-line
  (light + dark variants) added to assets/theme.css.
- docs/guide/03-markdown.md updated with rendered examples.

@engineervix engineervix left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Summary

Reviewed the Go parser extension for code-block titles + line highlighting. Build and go vet are clean, CI is green, and test coverage is thorough (28 new tests covering quoting, ordering, D2 interop, out-of-range, empty title, etc.).

What's good:

  • Title text and the Chroma fallback path are properly HTML-escaped — no XSS via title="…".
  • Plain code blocks (no custom attrs) keep the old zero-overhead path unchanged — verified by TestCodeBlockPlainPassthrough.
  • D2 diagram blocks are correctly unaffected (transformer priority 100 vs. 200 — confirmed the ordering in d2.go).
  • Architecture matches the existing extension pattern in this codebase (AST transformer + NodeRenderer pair, same as the D2 extension).

Requesting changes for one item: the unbounded highlight-range expansion (inline comment on highlight.go:304) — I reproduced a 2+ minute hang from a single typo'd range ({2-2000000000}) in a standalone test. The rest are non-blocking nits (inline comments): a redundant/duplicate code path, a couple of literal-tab-byte string literals, and an unused parameter — none change behavior, just worth cleaning up.

Checked against the Web Interface Guidelines skill too — no violations, since this PR touches static CSS with no interactive elements.

Comment thread internal/parser/highlight.go
Comment thread internal/parser/highlight.go Outdated
Comment thread internal/parser/highlight.go Outdated
Comment thread internal/parser/highlight.go Outdated
… extension

Addresses review feedback on engineervix#41:

- Cap {lo-hi} expansion at 10k lines. A typo'd range like {2-2000000000}
  previously tried to build a slice with billions of ints and hung
  indefinitely instead of being silently dropped like other malformed input.
- Remove the looksLikeSingleAttr branch/helper in codeAttrsTransformer.Transform
  — it duplicated the fallback path below it for the same inputs.
- Use \t escapes instead of literal tab bytes in two string/rune literals.
- Drop the unused darkStyle/darkStyleName plumbing in codeAttrsExtension,
  codeAttrsRenderer, and renderCodeBlockBody; classed HTML only needs the
  light style since dark colours come from the separate
  [data-theme="dark"] stylesheet (same reasoning already documented for
  newMarkdown's highlighting.WithStyle call).

@engineervix engineervix left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

All four review findings addressed in 10722b6 (unbounded highlight-range hang capped, redundant code path removed, literal-tab-byte literals fixed, unused darkStyle plumbing dropped) — verified build/vet/tests pass, and re-ran the original hang repro to confirm it now returns immediately. CI is green.

engineervix

This comment was marked as duplicate.

@engineervix engineervix left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reversing decision to approve PR as there are several things wrong with the styling

@engineervix
engineervix dismissed their stale review July 6, 2026 09:12

Superceded by updated review

…de colours

- Switch Chroma to inline line numbers (WithLineNumbers, no
  LineNumbersInTable) instead of the two-<pre> table layout. Fixes
  gutter/code misalignment and the ~48px gap between them (each <pre> had
  its own padding), and removes the need to special-case main.js's copy
  button against a second, number-only <pre>.
- Drop the left accent bar on highlighted lines (box-shadow), matching
  mkdocs-material/VitePress convention.
- Bleed the highlight-line background into the code block's own padding
  so it reaches the card edges instead of stopping short.
- Scope ChromaCSS's light-theme rules to :root:not([data-theme="dark"])
  (previously only dark rules were scoped). A Chroma style commonly
  leaves some token types uncoloured, relying on the base foreground —
  github-dark has no explicit entry for plain identifiers or punctuation,
  so those tokens rendered in github (light)'s near-black colour even in
  dark mode, since an unscoped rule that directly matches an element
  always wins over an inherited value regardless of specificity. This
  was a pre-existing site-wide bug, not specific to the new highlighting
  feature.
- Bump .highlight-line's selector depth to match the real DOM nesting:
  scoping the light rules above made Chroma's own .hl rule 4 classes
  deep, which briefly outranked the previous 3-class override.
@engineervix
engineervix merged commit 465ee5c into engineervix:main Jul 6, 2026
5 checks passed
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.

2 participants