highlightjs / highlightjs/highlight.js
(x86asm, mipsasm, llvm) Label and directive matches swallow the preceding blank line
- Dominant language
- JavaScript
- Stars
- 25k
- Forks
- 3.8k
- Avg merge
- 11h 35m
- Merged PRs (30d)
- 3
Description
**Describe the issue**
In the assembly grammars, the label and directive rules anchor with `^\s*`. Because
`\s` matches `\n`, a match that starts at the beginning of a *preceding blank or
whitespace-only line* can run through the newline(s) and into the label on the next
line. Since JS regexes prefer the leftmost match, that earlier start wins over the
correct one, and the emitted `` begins one line too early:
```html
.exit:
```
The blank line is now inside the symbol span, so it picks up the label's styling
(visible in any theme that gives `.hljs-symbol` a background, and it also means the
highlighted region simply doesn't correspond to the token). It also breaks anything
that splits the highlighted HTML per line.
This only triggers when the label or directive is preceded by a blank (or
whitespace-only) line, which is why it has gone unnoticed. That happens to be the
normal shape of compiler-generated assembly, where functions are separated by blank
lines.
It's already baked into one of your own fixtures: `test/markup/mipsasm/default.expect.txt`
currently expects
```html
AckermannFunc:
```
Affected rules:
- `src/languages/x86asm.js:127` — `'^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)'`
- `src/languages/x86asm.js:129` — `'^\\s*%%[A-Za-z0-9_$#@~.?]*:'`
- `src/languages/x86asm.js:147` — `/^\s*\.[\w_-]+/`
- `src/languages/mipsasm.js:90,92` — `'^\\s*[a-z_\\.\\$][a-z0-9_\\.\\$]+:'`, `'^\\s*[0-9]+:'`
- `src/languages/llvm.js:38` — `/^\s*[a-z]+:/`
The trailing `\s+label` in the x86asm rule has the same defect independently: it can
join a bare identifier to a `label` keyword on the *following* line.
**Which language seems to have the issue?**
`x86asm`, `mipsasm` and `llvm` (explicit language, not auto-detection).
**Are you using `highlight` or `highlightAuto`?**
`highlight`.
**Sample Code to Reproduce**
```js
hljs.highlight("main:\n mov eax, 1\n\n.exit:\n ret\n", { language: "x86asm" }).value
```
Actual:
```html
main:
mov eax, 1
.exit:
ret
```
Same for directives (`\n\n .section .text` puts the newline inside `hljs-meta`), for
`mipsasm` and `llvm` labels, and for the x86asm `label` keyword form across two lines.
**Expected behavior**
The blank line stays outside the span:
```html
main:
mov eax, 1
.exit:
ret
```
**Additional context**
The fix is to use `[ \t]` rather than `\s` for the leading indentation (and for the
x86asm `label` separator): indentation before a label or directive is by definition
same-line. I have a patch with markup tests for all three grammars; PR to follow.
Verified against `main` (fc3f0639): with the fix the only existing expectation that
changes is the `mipsasm/default` one quoted above, and highlighting relevance is
unchanged for every case I tested, so auto-detection is unaffected.
Two related things I noticed while in here but deliberately left alone, as they're
separate defects with less obvious fixes:
- `src/languages/mipsasm.js:92` — the numbered-local-label rule `^\s*[0-9]+:` is
effectively dead: the `number` mode appears earlier in `contains`, so at a true
line start it always wins and `1:` highlights as a number followed by a bare colon.
Before this fix, the symbol rule only ever won when it could start on an earlier
blank line.
- `src/languages/mipsasm.js:57` — the keyword mode's `end: '\\s'` consumes the
terminating character, so a mnemonic at the end of a line emits
`nop\n`. Same class of problem, but tightening it
would change existing expectations for the trailing space in `addi `.
Investigated and drafted by Claude Code (Claude Opus 5) working with me; posted
from my account with my permission. I have reviewed the analysis and the patch and
can speak to them in review. `Assisted-by: Claude Opus 5 (high)`
Contributor guide
Research direction
Start with the affected rules in src/languages/x86asm.js, src/languages/mipsasm.js, and src/languages/llvm.js, then inspect test/markup/mipsasm/default.expect.txt and the proposed markup tests. Reproduce the x86asm example with highlight, update leading indentation and label separators to stay on the same line, and verify that blank lines remain outside spans without changing highlighting relevance.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100