Skip to content

Commit 6bdac78

Browse files
committed
AG-49899 Closing brackets are incorrectly highlighted in Element Hiding rules
Squashed commit of the following: commit 7f04e04 Author: Kurbanali Ruslan <r.kurbanali@adguard.com> Date: Fri Jan 30 17:27:30 2026 +0500 AG-49899 Closing brackets are incorrectly highlighted in Element Hiding rules
1 parent a71f6b6 commit 6bdac78

4 files changed

Lines changed: 46 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic
1616
### Fixed
1717

1818
- Highlighting for cosmetic rules modifiers [#134], [#151].
19+
- Highlighting nested selector in CSS pseudo-class [#156].
1920

2021
[#120]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/120
2122
[#131]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/131
2223
[#134]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/134
2324
[#137]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/137
2425
[#151]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/151
26+
[#156]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/156
2527

2628
## [2.1.4] (prerelease) - 2025-12-26
2729

syntaxes/adblock.yaml-tmlanguage

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ repository:
246246
name: keyword.control.adblock
247247
"4":
248248
patterns:
249-
- include: "#cssSelector"
249+
- include: "#htmlFilteringCssSelector"
250250
251251
scriptletRules:
252252
patterns:
@@ -464,7 +464,7 @@ repository:
464464
match: "\\\\u[0-9A-Fa-f]{4}"
465465
- name: constant.character.escape.regexp
466466
match: "\\\\."
467-
467+
468468
# Character class brackets
469469
- begin: "(\\[)(\\^)?"
470470
beginCaptures:
@@ -481,7 +481,7 @@ repository:
481481
- match: "\\\\[\\]\\-\\\\]"
482482
name: constant.character.escape.regexp
483483
- match: "[^\\]]"
484-
484+
485485
# Groups and captures
486486
- begin: "(\\()(\\?[:=!<]|\\?<[=!]|\\?P?<[^>]+>)?"
487487
beginCaptures:
@@ -495,23 +495,23 @@ repository:
495495
name: punctuation.definition.group.regexp
496496
patterns:
497497
- include: "#regexp"
498-
498+
499499
# Alternation
500500
- name: keyword.operator.or.regexp
501501
match: "\\|"
502-
502+
503503
# Quantifiers
504504
- name: keyword.operator.quantifier.regexp
505505
match: "[*+?]\\??"
506506
- name: keyword.operator.quantifier.regexp
507507
match: "\\{\\d+(,\\d*)?\\}\\??"
508-
508+
509509
# Anchors and boundaries
510510
- name: keyword.control.anchor.regexp
511511
match: "\\^|\\$"
512512
- name: keyword.control.anchor.regexp
513513
match: "\\\\[bB]"
514-
514+
515515
# Backreferences
516516
- name: keyword.other.back-reference.regexp
517517
match: "\\\\[1-9]\\d*"
@@ -931,6 +931,11 @@ repository:
931931
match: ".*"
932932

933933
cssSelector:
934+
patterns:
935+
- name: entity.name.function.adblock
936+
match: ".+"
937+
938+
htmlFilteringCssSelector:
934939
patterns:
935940
# ID selector
936941
- match: |-
@@ -1087,7 +1092,25 @@ repository:
10871092
\s* # Optional whitespace after regexp value
10881093
)
10891094
|( # Group 13: unquoted value
1090-
[^\)]+ # Value is 1 or more non-) characters
1095+
(?: # Nested parentheses allowed up to 3 levels
1096+
[^()]+ # TODO: This can be improved to allow any level of nesting with recursion,
1097+
| # but to do so, the whole selector logic would need to be rewritten with begin/end.
1098+
\(
1099+
(?:
1100+
[^()]+
1101+
|
1102+
\(
1103+
(?:
1104+
[^()]+
1105+
|
1106+
\(
1107+
[^()]+
1108+
\)
1109+
)*
1110+
\)
1111+
)*
1112+
\)
1113+
)*
10911114
)
10921115
)?
10931116
(\)) # Group 14: Closing parenthesis

syntaxes/test/adblock/cosmetic/html.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,18 @@ describe('HTML filtering rules', () => {
554554
{ fragment: ')', scopes: PSEUDO_CLASS_CLOSE },
555555
],
556556
},
557+
{
558+
actual: '$$div:has(> div:not([class]) > a)',
559+
expected: [
560+
{ fragment: '$$', scopes: SEPARATOR },
561+
{ fragment: 'div', scopes: TYPE_SELECTOR },
562+
{ fragment: ':', scopes: PSEUDO_CLASS_PREFIX },
563+
{ fragment: 'has', scopes: PSEUDO_CLASS },
564+
{ fragment: '(', scopes: PSEUDO_CLASS_OPEN },
565+
{ fragment: '> div:not([class]) > a', scopes: PSEUDO_CLASS_UNQUOTED },
566+
{ fragment: ')', scopes: PSEUDO_CLASS_CLOSE },
567+
],
568+
},
557569
{
558570
actual: '$$tag > tag + tag ~ tag tag, tag + tag',
559571
expected: [

test/static/rules/test_rules.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ $$:class1(arg1), :class2("arg2"), :class3('arg3'), :class4(/arg4/i)
219219
$$:class1("arg \" 1"), :class2('arg \' 2'), :class3(/arg\/3/i)
220220
$$:class1( arg1 ), :class2( "arg2" ), :class3( 'arg3' ), :class4( /arg4/i )
221221
$$:class(arg with spaces), :class(multiple, args, here)
222+
$$div:has(> div:not([class]) > a)
222223
$$tag > tag + tag ~ tag tag, tag + tag
223224
example.org$$script[id="hello"][tag-content="hello"][max-length="100"]
224225
example.org,example.com$@$script[id="hello"][tag-content="something"]

0 commit comments

Comments
 (0)