fix(css, less, scss, stylus) keep escaped characters in selector names - #4513
Open
maximilliangrand wants to merge 1 commit into
Open
fix(css, less, scss, stylus) keep escaped characters in selector names#4513maximilliangrand wants to merge 1 commit into
maximilliangrand wants to merge 1 commit into
Conversation
Class and id names may contain CSS escape sequences, as Tailwind emits for variant separators (`.dark\:hover\:bg-sky-500`). The selector patterns stopped at the backslash, so the name was cut short and the rest was rescanned: the escaped `\:hover` was scoped as a pseudo class and the trailing `500` as a number. Adds a shared ESCAPE_RE and SELECTOR_IDENT_RE to lib/css-shared.js and uses them for the class and id patterns in all four css-like grammars, so they stay consistent. The hex branches of the escape are kept disjoint so the surrounding quantifier cannot backtrack exponentially. Fixes highlightjs#3965 Assisted-by: Claude Opus 4.8 (high)
joshgoebel
reviewed
Aug 23, 2026
Comment on lines
+14
to
+16
| + '[\\da-fA-F]{6}(?=[\\da-fA-F])' | ||
| + '|[\\da-fA-F]{1,6}(?![\\da-fA-F]) ?' | ||
| + '|[^\\da-fA-F\\r\\n]' |
Member
There was a problem hiding this comment.
Can we add a few comments on what each of these is hoping to match?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3965.
The bug
Class and id names may contain CSS escape sequences, which Tailwind emits for its variant separators. The selector patterns stopped at the backslash, so the name was cut short and the remainder rescanned:
On 11.12.0 that scopes
.darkas the class, then the escaped\:hoveras a pseudo class and500as a number. All four css-like grammars are affected.Root cause
Each grammar spelled its own class and id pattern from a plain character class with no notion of escapes:
src/languages/css.js:17(IDENT_RE, used by selector-class) and:40src/languages/scss.js:38and:43src/languages/less.js:188and:189, viaINTERP_IDENT_REsrc/languages/stylus.js:76and:82The fix
Adds
ESCAPE_REandSELECTOR_IDENT_REtosrc/languages/lib/css-shared.jsand uses them for the class and id patterns in all four grammars, following your note on the issue about pushing a shared name pattern down intocss-shared.js. Each grammar keeps its own leading-character rules, so the change is additive.The hex branches of the escape are kept disjoint: a six digit run is only taken when a seventh follows, and every shorter run has to reach a non-hex character. Without that,
\0plus0and\00are both valid splits of the same text andtest/regexfails with exponential backtracking on"\00".repeat(n).Tests
Four escape cases added to
test/markup/css/css_consistency.txtand mirrored into less, scss and stylus withtools/css, so the shared fixture is what proves the four grammars now agree.With the source change reverted those four
css_consistencytests fail (598 passing, 4 failing); with it applied the markup suite is 602 passing and the full suite 1649 passing, 3 pending, matching main.Assisted-by: Claude Opus 4.8 (high)