diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..2bde098 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,16 @@ +name: Syntax Tests + +on: [push, pull_request] + +jobs: + st4_syntax_tests: + name: Run ST4 Syntax Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: SublimeText/syntax-test-action@v2 + with: + build: 4152 + default_packages: v4152 + package_name: Ngx HTML diff --git a/NgxHTML.sublime-syntax b/NgxHTML.sublime-syntax index f9937b3..49a9ca8 100644 --- a/NgxHTML.sublime-syntax +++ b/NgxHTML.sublime-syntax @@ -8,10 +8,14 @@ version: 2 extends: Packages/HTML/HTML.sublime-syntax +variables: + angular_blocks: (?<=\@)\b(?xi:for | if | else | else if | switch | case | empty | placeholder | defer | default | error | loading)\b + contexts: main: - meta_prepend: true - include: interpolation + - include: angular-blocks interpolation: - match: '{{' @@ -82,3 +86,34 @@ contexts: push: - tag-event-attribute-meta - tag-event-attribute-assignment + + + angular-blocks: + - match: '(@){{angular_blocks}}' + scope: keyword.control.control-flow.html + captures: + 1: punctuation.definition.keyword.html + push: + - match: \{ + scope: punctuation.section.block.begin.html + push: + - meta_scope: meta.block.html + - include: main + - match: \} + scope: punctuation.section.block.end.html + pop: 2 + - match: \( + scope: punctuation.section.group.begin.html + push: + - meta_scope: meta.group.html + - match: \b(async)\b + scope: keyword.control.html + - match: \b(track|of|prefetch on|on|prefetch when|when|as)\b + scope: keyword.operator.word.html + - match: \b(minimum|after)\b(\?) + captures: + 1: keyword.operator.word.html + 2: keyword.control.question.html + - match: \) + scope: punctuation.section.group.end.html + pop: 1 diff --git a/README.md b/README.md index 55469b6..54ab69c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,48 @@ Highlighting the JS part as JS. So, - in `a && b` within an Angular expression, you should see `&&` correctly highlighted as the JS operator instead of an error you would see in normal HTML syntax. - in `{{1 + 2}}` interpolations, you should see JS syntax highlighting as well +## And... + +Now it supports Angular control flow. + +``` +@for (item of items) { + {{item.title}} +} @empty { +

No Items

+} +``` + +``` +@if (users$ | async; as users) { + {{ users.length }} +} +``` + +``` +@if (a > b) { + {{a}} is greater than {{b}} +} @else if (b > a) { + {{a}} is less than {{b}} +} @else { + {{a}} is equal to {{b}} +} +``` + +``` +@switch (condition) { + @case (caseA) { + Case A. + } + @case (caseB) { + Case B. + } + @default { + Default case. + } +} +``` + ## How to use The syntax is listed as `Ngx HTML` in Sublime syntax selection list. diff --git a/tests/syntax_test_control_flow.component.html b/tests/syntax_test_control_flow.component.html new file mode 100644 index 0000000..6aec2da --- /dev/null +++ b/tests/syntax_test_control_flow.component.html @@ -0,0 +1,136 @@ + + +@if (loggedIn) { + + + + + The user is logged in +} @else { + + + + + + + + The user is not logged in +} + + +@if (a > b) { + {{ a }} is greater than {{ b }} + + + + +} + +@if (a > b) { + {{ a }} is greater than {{ b }} +} @else if (b > a) { + {{ a }} is less than {{ b }} +} @else { + {{ a }} is equal to {{ b }} +} + +@switch (accessLevel) { + @case ('admin') { + + + + + + } + @case ('moderator') { + + } + @default { + + } +} + +@for (user of users; track user.id) { + {{ user.name }} +} @empty { + Empty list of users +} + +@defer { + +} + +@defer (on viewport) { + +} @placeholder { + + +} + +@defer (on viewport) { + +} @loading { + Loading… +} @error { + Loading failed :( +} @placeholder { + +} + +@defer (on viewport; prefetch on idle) { + +} + +@for (item of items; track item.id; let idx = $index, e = $even) { + Item #{{ idx }}: {{ item.name }} +} + +@for (item of items) { + {{ item.title }} +} + +@for (item of items) { + {{ item.title }} +} @empty { +

No Items

+} + +@for (item of items; track item.name) { +
  • {{ item.name }}
  • +} @empty { +
  • There are no items.
  • +} + +@if (users$ | async; as users) { + {{ users.length }} +} + +@for (item of items; track item.id) { + {{ item.name }} +} + +@switch (condition) { + @case (caseA) { + Case A. + } + @case (caseB) { + Case B. + } + @default { + Default case. + } +} + +@defer (on ; when ; prefetch on ; prefetch when ) { + + +} @placeholder (minimum? ) { + +

    Placeholder

    +} @loading (minimum? ; after? ) { + + loading image +} @error { + +

    An loading error occured

    +}