From 892df8b3e765069c1997cd1d5242e10f495e802f Mon Sep 17 00:00:00 2001 From: deathaxe Date: Mon, 16 Dec 2024 14:25:25 +0100 Subject: [PATCH 1/5] Refactor attributes 1. add dedicated `meta.directive` scopes (like in VueJS syntax) 2. use angular expression syntax in directive values instead of plain JavaScript --- NgxHTML.sublime-syntax | 150 ++++++++----- tests/syntax_test_scopes.component.html | 279 ++++++++++++++++++++++++ 2 files changed, 374 insertions(+), 55 deletions(-) diff --git a/NgxHTML.sublime-syntax b/NgxHTML.sublime-syntax index 9e401b3..6436839 100644 --- a/NgxHTML.sublime-syntax +++ b/NgxHTML.sublime-syntax @@ -40,11 +40,7 @@ contexts: tag-attributes: - meta_prepend: true - - include: tag-ng-template-attribute - - include: tag-ng-reference-attribute - - include: tag-ng-bind-attribute - - include: tag-ng-on-attribute - - include: tag-ng-bindon-attribute + - include: ng-directives ###[ ANGULAR EXPRESSIONS ]##################################################### @@ -61,60 +57,91 @@ contexts: - include: ng-strings - include: ng-variables -###[ ANGULAR TAG ATTRIBUTES ]################################################## +###[ ANGULAR DIRECTIVES ]###################################################### - tag-ng-template-attribute: - - match: (\*)([a-zA-Z]\w*) - scope: meta.attribute-with-value.template.html + ng-directives: + # template + - match: (\*)(?:(ngIf)|(ngFor)|(ngSwitch(?:Case|Default))|([a-zA-Z]\w*)) + scope: meta.directive.template.ngx captures: - 1: punctuation.definition.template.html - 2: entity.other.attribute-name.template.html - push: - - tag-event-attribute-meta - - tag-event-attribute-assignment - - tag-ng-reference-attribute: + 1: punctuation.definition.template.ngx + 2: keyword.control.conditional.if.ngx + 3: keyword.control.loop.for.ngx + 4: keyword.control.conditional.case.ngx + 5: entity.other.attribute-name.template.ngx + push: ng-directive-assignment + # reference - match: (\#)([a-zA-Z]\w*) - scope: meta.attribute.reference.html + scope: meta.directive.reference.ngx captures: - 1: punctuation.definition.reference.html - 2: entity.other.attribute-name.reference.html - push: - - tag-event-attribute-meta - - tag-event-attribute-assignment - - tag-ng-bind-attribute: - - match: (\[)([a-zA-Z@][!\w.-]*)(\]) - scope: meta.attribute-with-value.bind.html + 1: punctuation.definition.reference.ngx + 2: entity.other.attribute-name.reference.ngx + push: ng-directive-assignment + # bind + - match: (\[)(?:(ngSwitch)|([a-zA-Z@][!\w.-]*))(\]) + scope: meta.directive.bind.ngx captures: - 1: punctuation.section.bind.begin.html - 2: entity.other.attribute-name.bind.html - 3: punctuation.section.bind.end.html - push: - - tag-event-attribute-meta - - tag-event-attribute-assignment - - tag-ng-on-attribute: + 1: punctuation.definition.bind.begin.ngx + 2: keyword.control.conditional.switch.ngx + 3: entity.other.attribute-name.bind.ngx + 4: punctuation.definition.bind.end.ngx + push: ng-directive-assignment + # on - match: (\()([a-zA-Z@][\w:.]*)(\)) - scope: meta.attribute-with-value.on.html + scope: meta.directive.on.ngx captures: - 1: punctuation.section.on.begin.html - 2: entity.other.attribute-name.on.html - 3: punctuation.section.on.end.html - push: - - tag-event-attribute-meta - - tag-event-attribute-assignment - - tag-ng-bindon-attribute: + 1: punctuation.definition.on.begin.ngx + 2: entity.other.attribute-name.on.ngx + 3: punctuation.definition.on.end.ngx + push: ng-directive-assignment + # bindon - match: (\[\()([a-zA-Z][\w.]*)(\)\]) - scope: meta.attribute-with-value.bindon.html + scope: meta.directive.bindon.ngx captures: - 1: punctuation.section.bindon.begin.html - 2: entity.other.attribute-name.bindon.html - 3: punctuation.section.bindon.end.html - push: - - tag-event-attribute-meta - - tag-event-attribute-assignment + 1: punctuation.definition.bindon.begin.ngx + 2: entity.other.attribute-name.bindon.ngx + 3: punctuation.definition.bindon.end.ngx + push: ng-directive-assignment + + ng-directive-assignment: + - meta_include_prototype: false + - meta_content_scope: meta.directive.ngx + - match: = + scope: meta.directive.ngx punctuation.separator.key-value.ngx + set: + - immediately-pop # workaround https://github.com/sublimehq/sublime_text/issues/4069 + - ng-directive-value + - include: else-pop + + ng-directive-value: + - meta_content_scope: meta.directive.value.ngx + - match: \" + scope: meta.string.ngx string.quoted.double.ngx punctuation.definition.string.begin.ngx + embed: ng-directive-expressions + embed_scope: meta.directive.value.ngx meta.string.ngx meta.interpolation.ngx source.ngx.embedded.html + escape: \" + escape_captures: + 0: meta.string.ngx string.quoted.double.ngx punctuation.definition.string.end.ngx + pop: 1 + - match: \' + scope: meta.string.ngx string.quoted.single.ngx punctuation.definition.string.begin.ngx + embed: ng-directive-expressions + embed_scope: meta.directive.value.ngx meta.string.ngx meta.interpolation.ngx source.ngx.embedded.html + escape: \' + escape_captures: + 0: meta.string.ngx string.quoted.single.ngx punctuation.definition.string.end.ngx + pop: 1 + - include: else-pop + + ng-directive-expressions: + - match: (trackBy)\s*(:) + captures: + 1: keyword.control.flow.ngx + 2: punctuation.separator.key-value.ngx + - include: ng-conditional-keywords + - include: ng-defer-keywords + - include: ng-for-keywords + - include: ng-expressions ###[ ANGULAR DECLARATIONS ]#################################################### @@ -240,9 +267,12 @@ contexts: - match: \) scope: punctuation.section.group.end.ngx pop: 1 + - include: ng-conditional-keywords + - include: ng-expressions + + ng-conditional-keywords: - match: as{{ident_break}} scope: keyword.operator.assignment.as.ngx - - include: ng-expressions ng-defer-group: - meta_include_prototype: false @@ -256,15 +286,22 @@ contexts: - match: \) scope: punctuation.section.group.end.ngx pop: 1 - - match: (?:idle|viewport|interaction|hover|immediatetimer){{ident_break}} - scope: constant.language.event.ngx + - include: ng-defer-keywords + - include: ng-expressions + + ng-defer-keywords: - match: (?:prefetch on|on|prefetch when|when){{ident_break}} scope: keyword.control.flow.ngx + push: ng-defer-event - match: (minimum|after)(\?) captures: 1: keyword.operator.word.ngx 2: keyword.control.question.ngx - - include: ng-expressions + + ng-defer-event: + - match: (?:idle|viewport|interaction|hover|immediatetimer){{ident_break}} + scope: constant.language.event.ngx + - include: else-pop ng-for-group: - meta_include_prototype: false @@ -278,13 +315,16 @@ contexts: - match: \) scope: punctuation.section.group.end.ngx pop: 1 + - include: ng-for-keywords + - include: ng-expressions + + ng-for-keywords: - match: track{{ident_break}} scope: keyword.control.flow.ngx - match: let{{ident_break}} scope: keyword.declation.variable.ngx - match: of{{ident_break}} scope: keyword.operator.iteration.ngx - - include: ng-expressions ###[ ANGULAR INTERPOLATIONS ]################################################## diff --git a/tests/syntax_test_scopes.component.html b/tests/syntax_test_scopes.component.html index d5fbd8e..0449ccb 100644 --- a/tests/syntax_test_scopes.component.html +++ b/tests/syntax_test_scopes.component.html @@ -740,3 +740,282 @@ + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
({{ item.id }}) {{ item.name }}
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f8abc9a02159b575fda84a71758c4040f8272039 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Mon, 16 Dec 2024 16:17:15 +0100 Subject: [PATCH 2/5] Move angular expressions section This commit moves angular expressions for a more logical order of sections, starting with... 1. HTML injections 2. angular directives 3. angular declarations (let statement) 4. angular control flow statements 5. angular interpolation followed by... 6. angular expressions with all following contexts being part of expressions. --- NgxHTML.sublime-syntax | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/NgxHTML.sublime-syntax b/NgxHTML.sublime-syntax index 6436839..d237f8f 100644 --- a/NgxHTML.sublime-syntax +++ b/NgxHTML.sublime-syntax @@ -42,21 +42,6 @@ contexts: - meta_prepend: true - include: ng-directives -###[ ANGULAR EXPRESSIONS ]##################################################### - - ng-expressions: - # https://angular.dev/guide/templates/expression-syntax - - include: ng-arrays - - include: ng-groups - - include: ng-objects - - include: ng-function-calls - - include: ng-filters - - include: ng-operators - - include: ng-constants - - include: ng-numbers - - include: ng-strings - - include: ng-variables - ###[ ANGULAR DIRECTIVES ]###################################################### ng-directives: @@ -341,7 +326,22 @@ contexts: pop: 1 - include: ng-expressions -###[ ANGULAR ARRAYS ]########################################################### +###[ ANGULAR EXPRESSIONS ]##################################################### + + ng-expressions: + # https://angular.dev/guide/templates/expression-syntax + - include: ng-arrays + - include: ng-groups + - include: ng-objects + - include: ng-function-calls + - include: ng-filters + - include: ng-operators + - include: ng-constants + - include: ng-numbers + - include: ng-strings + - include: ng-variables + +###[ ANGULAR ARRAYS ]########################################################## ng-arrays: - match: \[ From 7d992c13c63a18881876872ab562c604e398098f Mon Sep 17 00:00:00 2001 From: deathaxe Date: Mon, 16 Dec 2024 16:18:23 +0100 Subject: [PATCH 3/5] Move variables to bottom --- NgxHTML.sublime-syntax | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/NgxHTML.sublime-syntax b/NgxHTML.sublime-syntax index d237f8f..2fa7686 100644 --- a/NgxHTML.sublime-syntax +++ b/NgxHTML.sublime-syntax @@ -10,24 +10,6 @@ file_extensions: - ngx - component.html -variables: - - bin_digit: '[01_]' - oct_digit: '[0-7_]' - dec_digit: '[0-9_]' - hex_digit: '[\h_]' - dec_integer: (?:0|[1-9]{{dec_digit}}*) - dec_exponent: '[Ee](?:[-+]|(?![-+])){{dec_digit}}*' - - # JavaScript identifier - ident_name: (?:{{ident_start}}{{ident_part}}*{{ident_break}}) - ident_break: (?!{{ident_part}}) - ident_escape: (?:\\u(?:\h{4}|\{\h+\})) - ident_start: (?:[_$\p{L}\p{Nl}]|{{ident_escape}}) - ident_part: (?:[_$\p{L}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]|{{ident_escape}}) - - dot_accessor: (?:\??\.(?!\.)) - contexts: ###[ HTML CUSTOMIZATIONS ]##################################################### @@ -686,3 +668,23 @@ contexts: ng-block-pop: - match: (?=[;)}]) pop: 1 + +############################################################################### + +variables: + + bin_digit: '[01_]' + oct_digit: '[0-7_]' + dec_digit: '[0-9_]' + hex_digit: '[\h_]' + dec_integer: (?:0|[1-9]{{dec_digit}}*) + dec_exponent: '[Ee](?:[-+]|(?![-+])){{dec_digit}}*' + + # JavaScript identifier + ident_name: (?:{{ident_start}}{{ident_part}}*{{ident_break}}) + ident_break: (?!{{ident_part}}) + ident_escape: (?:\\u(?:\h{4}|\{\h+\})) + ident_start: (?:[_$\p{L}\p{Nl}]|{{ident_escape}}) + ident_part: (?:[_$\p{L}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]|{{ident_escape}}) + + dot_accessor: (?:\??\.(?!\.)) From 5c37b59763b2b43871ed7be990b5309b74db6f3f Mon Sep 17 00:00:00 2001 From: Po Chen Date: Tue, 17 Dec 2024 18:10:42 +1100 Subject: [PATCH 4/5] Create recent.txt --- messages/recent.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 messages/recent.txt diff --git a/messages/recent.txt b/messages/recent.txt new file mode 100644 index 0000000..c9fec05 --- /dev/null +++ b/messages/recent.txt @@ -0,0 +1,5 @@ +# Ngx HTML Syntax 1.0+ + +Huge thanks to @deathaxe for rewriting the whole syntax to properly incorporate Angular Expressions. + +Now we have highly accurate syntax highlighting in component html files. From 9023d19d4d1d20a76fa498c0d33e165b1a4df79d Mon Sep 17 00:00:00 2001 From: deathaxe Date: Tue, 17 Dec 2024 12:24:35 +0100 Subject: [PATCH 5/5] Extend meta.expression scope This commit adds `.expression` sub-scope name to distinguish embedded interpolation expressions from control flow statements. --- NgxHTML.sublime-syntax | 10 +-- tests/syntax_test_scopes.component.html | 100 ++++++++++++------------ 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/NgxHTML.sublime-syntax b/NgxHTML.sublime-syntax index 2fa7686..f1fea55 100644 --- a/NgxHTML.sublime-syntax +++ b/NgxHTML.sublime-syntax @@ -85,7 +85,7 @@ contexts: - match: \" scope: meta.string.ngx string.quoted.double.ngx punctuation.definition.string.begin.ngx embed: ng-directive-expressions - embed_scope: meta.directive.value.ngx meta.string.ngx meta.interpolation.ngx source.ngx.embedded.html + embed_scope: meta.directive.value.ngx meta.string.ngx meta.embedded.expression.ngx source.ngx.embedded.html escape: \" escape_captures: 0: meta.string.ngx string.quoted.double.ngx punctuation.definition.string.end.ngx @@ -93,7 +93,7 @@ contexts: - match: \' scope: meta.string.ngx string.quoted.single.ngx punctuation.definition.string.begin.ngx embed: ng-directive-expressions - embed_scope: meta.directive.value.ngx meta.string.ngx meta.interpolation.ngx source.ngx.embedded.html + embed_scope: meta.directive.value.ngx meta.string.ngx meta.embedded.expression.ngx source.ngx.embedded.html escape: \' escape_captures: 0: meta.string.ngx string.quoted.single.ngx punctuation.definition.string.end.ngx @@ -297,14 +297,14 @@ contexts: ng-interpolations: - match: '{{' - scope: meta.embedded.ngx.html punctuation.section.embedded.begin.ngx.html + scope: meta.embedded.expression.ngx.html punctuation.section.embedded.begin.ngx.html push: ng-interpolation-body ng-interpolation-body: - meta_include_prototype: false - - meta_content_scope: meta.embedded.ngx.html source.ngx.embedded.html + - meta_content_scope: meta.embedded.expression.ngx.html source.ngx.embedded.html - match: '}}' - scope: meta.embedded.ngx.html punctuation.section.embedded.end.ngx.html + scope: meta.embedded.expression.ngx.html punctuation.section.embedded.end.ngx.html pop: 1 - include: ng-expressions diff --git a/tests/syntax_test_scopes.component.html b/tests/syntax_test_scopes.component.html index 0449ccb..ef3ebe1 100644 --- a/tests/syntax_test_scopes.component.html +++ b/tests/syntax_test_scopes.component.html @@ -160,9 +160,9 @@ {{ a }} is greater than {{ b }} - - - + + + @@ -184,9 +184,9 @@ {{ a() }} is less than {{ b.c() }} - - - + + + @@ -206,9 +206,9 @@ {{ a }} is equal to {{ b }} - - - + + + @@ -235,7 +235,7 @@ {{ startDate }} - + @@ -357,12 +357,12 @@ Item #{{ idx }}: {{ item.name }} - + - + @@ -390,7 +390,7 @@ - + @@ -489,7 +489,7 @@ {{ "\xAF \u2AFF \n \"" }} - + @@ -534,7 +534,7 @@ {{ { name: 'Alice', 'object': { array + "name": [0, 2, 3] } } }} - + @@ -607,7 +607,7 @@ {{ foo ? bar : baz }} - + @@ -618,7 +618,7 @@ {{ foo = null ?? 'default' }} - + @@ -631,7 +631,7 @@ {{ person['name'][0] = "Mirabel" }} - + @@ -650,20 +650,20 @@ {{ obj?.member }} - - - - + + + + {{ obj.member [5] }} - - - - + + + + @@ -672,10 +672,10 @@ {{ obj.method() }} - - - - + + + + @@ -685,10 +685,10 @@ {{ orders.value()?.[0]?.$extra?.#currency }} - - - - + + + + @@ -709,7 +709,7 @@ {{ func(arg, "value") }} - + @@ -723,7 +723,7 @@ {{ var | filter | annimation ("forward") }} - + @@ -757,7 +757,7 @@ - + @@ -776,7 +776,7 @@ - + @@ -801,7 +801,7 @@ - + @@ -820,7 +820,7 @@ - + @@ -845,7 +845,7 @@ - + @@ -868,7 +868,7 @@ - + @@ -892,7 +892,7 @@ - + @@ -916,7 +916,7 @@ - + @@ -932,7 +932,7 @@ - + @@ -949,7 +949,7 @@ - + @@ -971,7 +971,7 @@ - + @@ -987,7 +987,7 @@ - + @@ -999,7 +999,7 @@ - + @@ -1016,6 +1016,6 @@ - +