Skip to content

fix: keep line ranges and titles out of the code block language - #1306

Merged
nunomaduro merged 1 commit into
dev-null-sh:productionfrom
raz-iacob:fix/code-block-fence-language
Nov 3, 2026
Merged

nunomaduro merged 1 commit into
dev-null-sh:productionfrom
raz-iacob:fix/code-block-fence-language

Conversation

@raz-iacob

@raz-iacob raz-iacob commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1210. Some opening fences put the wrong thing in the code block's language, or lost their title:

  • A fence with no language that starts with a title, like ``` title="routes/web.php", used title="routes/web.php" as its label and had no filename.
  • A line range written right after the language, like ```js{2} (the VitePress and Gatsby style), kept js{2} as the language, so the block wasn't highlighted and the label showed js{2}.
  • A single-quoted title, like ```php title='app/Models/User.php', was ignored.

Now the first block shows routes/web.php, also in quoted commits and notifications, the second is highlighted as js, and the third shows app/Models/User.php.

Changes

  • CodeSpans reads the whole info string with the same tokens as before (key="value" pairs, {…} ranges, bare words), plus key='value' pairs, and { now ends a bare word. The language is the first token only when it's a bare word. lib/code.ts mirrors it, and both sides are tested with the same cases.
  • CodeBlock keeps its header for a block with a filename but no language in excerpts, where there's no copy button.

Validation

Local, on 90d02728 (based on f7aa5e97, the latest production):

  • composer test:lint and composer test:types pass, type coverage is 100%.
  • Pest passes all 5,393 tests at 100% coverage, and every Node and .tsx unit test passes.
  • The new feature cases fail on production. The rows for an apostrophe inside double quotes and for an empty or unclosed single-quoted title are guards and pass on both.
  • Server and client parse 30,000 generated fences identically, including glued ranges, attribute-first fences, single and mixed quotes, NBSP and multibyte text.
  • Layout shift is 0 on first load and on client navigation from the log, at every viewport and theme below.

Visual evidence

Guest view of the same demo commit in Chrome (2x), production (f7aa5e97) vs this branch.

Before After
1440×900 light
1440×900 dark
390×844 light
390×844 dark

1366×650: light before · light after · dark before · dark after

Quoted excerpt of a block with only a title:

Before After
1440×900 light
390×844 dark

Its other viewports and themes are on the assets branch.

Device verification

No mobile interaction changes, only a label and highlighting. 390×844 was checked with viewport emulation in Chrome, not on hardware or a simulator.

Independent review

A separate, read-only reviewer agent (given the task, #1210, the repo guidelines, the diff and these captures) returned CODE: PASS and VISUAL: PASS for a4670abe..f6cd14b9, media b2c285a9, and again for the rebased f7aa5e97..90d02728, media fccf3217, checking that #1351's new code block wrapper is intact and that nothing else reads the language or filename, after parity runs of 120,134 fuzzed and real-world fences (c++, f#, js:line-numbers, ts twoslash, mixed quotes and more) with 0 mismatches. It confirmed the feature tests fail on production and the guard rows pass on both. Nested fences (#1227) were checked by reading the code, since only the opening line is parsed.

Limitations

  • Not checked in Safari or Firefox.
  • Quarto-style fences like ```{r} used to show {r} as the label and now show none. Neither was highlighted.
  • The composer preview and notifications weren't captured. The preview uses the client parser, which the shared cases and the parity run cover, and notifications render the same excerpt as quotes.

Summary by CodeRabbit

  • Bug Fixes
    • Improved code-fence parsing for language labels and filename attributes, including single- and double-quoted values and compact attribute formats.
    • Filenames now appear in code-block headers even when no language label is present.
    • Corrected filename display in both commit views and static excerpts, avoiding an unintended language label.
    • Improved handling of line ranges and unusual or incomplete attribute values, including fences that begin with a title or line range.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3587eaa4-5301-485f-8b78-89145d32aecd
Commits

Reviewing files that changed from the base of the PR and between f6cd14b and 90d0272.

Files selected for processing: 1
  • resources/js/components/code-block.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

Code fence parsing now supports quoted attributes and selects language and filename values in both PHP and JavaScript. Code block headers render when a filename is present, including when no language is set.

Changes: Fence metadata and filename labels

Layer / File(s) Summary
Parse fence languages and attributes
app/Services/CodeSpans.php, resources/js/lib/code.ts, tests/Unit/Services/CodeSpansTest.php, tests/Unit/ComposerPreview.test.tsx
Both parsers tokenize fence info strings and support single- and double-quoted attributes. The tests cover language and filename selection, including empty and unterminated values.
Render filename-only headers
resources/js/components/code-block.tsx, tests/Unit/ComposerPreview.test.tsx
The header renders when a filename is present, even without a language. Tests check filename labels in commit and static excerpt rendering.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related issues

  • [RFC] Gists #1363: The issue requests matching highlighted rendering for gist code blocks. This PR changes fence parsing but does not implement gist rendering.

Possibly related PRs

Suggested reviewers: mnapoli, xheaven

Merge Risk: Minimal · up to 90d02

No actionable current-head defect was established in the reviewed parser or filename-header behavior.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "fix: keep line ranges and titles out of the code block language" matches the main change in the changeset. The raw summary shows that the parser in CodeSpans::block and resources/js/lib/cod…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "fix: keep line ranges and titles out of the code block language" matches the main change in the changeset. The raw summary shows that the parser in CodeSpans::block and resources/js/lib/code.ts now takes the language only from the first token that is not a brace group or a quoted key=value attribute. The tests add cases for line ranges and single-quoted titles and filenames. The title is specific, uses a conventional commit prefix, and is a single sentence of 12 words.

Full details: Docstring Coverage

Explanation

Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 5 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

raz-iacob added a commit to raz-iacob/dev-null.sh that referenced this pull request Nov 1, 2026
@raz-iacob
raz-iacob force-pushed the fix/code-block-fence-language branch from f6cd14b to 90d0272 Compare November 1, 2026 19:05
@nunomaduro
nunomaduro merged commit 134dcc1 into dev-null-sh:production Nov 3, 2026
1 check passed
@raz-iacob
raz-iacob deleted the fix/code-block-fence-language branch November 3, 2026 18:50
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