From 6f1910e7f0af1736313e8d581ad3a6a9177981da Mon Sep 17 00:00:00 2001
From: Keith Hall <kingkeith+git@gmail.com>
Date: Wed, 12 Feb 2025 21:58:39 +0200
Subject: [PATCH] wip support C# code inside HTML attributes without
 lookbehinds

---
 Razor/Razor.sublime-syntax                    |  11 +-
 ...or C# Razor HTML attribute).sublime-syntax |  18 +++
 Razor/tests/syntax_test_cshtml.cshtml         | 139 ++++++++++++++++++
 3 files changed, 166 insertions(+), 2 deletions(-)
 create mode 100644 Razor/embeddings/C# (for C# Razor HTML attribute).sublime-syntax

diff --git a/Razor/Razor.sublime-syntax b/Razor/Razor.sublime-syntax
index e28c255..eb00a86 100644
--- a/Razor/Razor.sublime-syntax
+++ b/Razor/Razor.sublime-syntax
@@ -274,6 +274,10 @@ contexts:
     - meta_prepend: true
     - include: csharp-interpolations
 
+  tag-generic-attribute-value-content:
+    - meta_prepend: true
+    - include: csharp-interpolations
+
   strings-common-content:
     - meta_prepend: true
     - include: csharp-interpolations
@@ -303,8 +307,11 @@ contexts:
     - meta_include_prototype: false
     - match: '@@'
       scope: constant.character.escape.cs-razor
-    - match: (?={{csharp_tag_interpolation_bare}})
-      push: csharp-interpolation-body
+    - match: '\w+@\w+' # prevent email addresses being caught etc
+    - match: '{{csharp_tag_interpolation_bare}}'
+      scope: punctuation.section.interpolation.begin.razor
+      push: Packages/HTML (C#)/Razor/embeddings/C# (for C# Razor HTML attribute).sublime-syntax
+      #push: csharp-interpolation-body
 
   csharp-interpolation-body:
     # - clear_scopes: 1
diff --git a/Razor/embeddings/C# (for C# Razor HTML attribute).sublime-syntax b/Razor/embeddings/C# (for C# Razor HTML attribute).sublime-syntax
new file mode 100644
index 0000000..d37be7e
--- /dev/null
+++ b/Razor/embeddings/C# (for C# Razor HTML attribute).sublime-syntax	
@@ -0,0 +1,18 @@
+%YAML 1.2
+---
+scope: source.cs.embedded.html-attribute-string.razor
+version: 1
+hidden: true
+
+extends: Packages/C#/C#.sublime-syntax
+
+contexts:
+  main:
+    - meta_prepend: true
+    - match: (?=")
+      pop: 1
+
+  line_of_code_in:
+    - meta_prepend: true
+    - match: (?=")
+      pop: 1
diff --git a/Razor/tests/syntax_test_cshtml.cshtml b/Razor/tests/syntax_test_cshtml.cshtml
index eae238a..1096e5b 100644
--- a/Razor/tests/syntax_test_cshtml.cshtml
+++ b/Razor/tests/syntax_test_cshtml.cshtml
@@ -134,6 +134,145 @@ else
 
 <p>@quote</p>
 
+<div class="grid-mvc" data-lang="@Model.Language" data-gridname="@Model.RenderOptions.GridName" data-selectable="@Model.RenderOptions.Selectable.ToString().ToLower()" data-multiplefilters ="@Model.RenderOptions.AllowMultipleFilters.ToString().ToLower()">
+<!--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.block.any.html -->
+<!-- ^^^^^^^^^^^^^^^^ meta.attribute-with-value.class.html -->
+<!-- ^^^^^ entity.other.attribute-name.class.html -->
+<!--      ^ punctuation.separator.key-value.html -->
+<!--       ^ meta.string.html string.quoted.double.html punctuation.definition.string.begin.html -->
+<!--        ^^^^^^^^ meta.class-name.html meta.string.html string.quoted.double.html -->
+<!--                ^ meta.string.html string.quoted.double.html punctuation.definition.string.end.html -->
+<!--                  ^^^^^^^^^ entity.other.attribute-name.html -->
+<!--                           ^ punctuation.separator.key-value.html -->
+<!--                            ^^^^^^^^^^^^^^^^^ meta.string.html string.quoted.double.html -->
+<!--                            ^ punctuation.definition.string.begin.html -->
+<!--                             ^ punctuation.section.interpolation.begin.razor -->
+<!--                              ^^^^^^^^^^^^^^ source.cs.embedded.html-attribute-string.razor -->
+<!--                              ^^^^^ variable.other.cs -->
+<!--                                   ^ punctuation.accessor.dot.cs -->
+<!--                                    ^^^^^^^^ variable.other.cs -->
+<!--                                            ^ punctuation.definition.string.end.html -->
+<!--                                              ^^^^^^^^^^^^^ entity.other.attribute-name.html -->
+<!--                                                           ^ punctuation.separator.key-value.html -->
+<!--                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.html string.quoted.double.html -->
+<!--                                                            ^ punctuation.definition.string.begin.html -->
+<!--                                                             ^ punctuation.section.interpolation.begin.razor -->
+<!--                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.cs.embedded.html-attribute-string.razor -->
+<!--                                                              ^^^^^ variable.other.cs -->
+<!--                                                                   ^ punctuation.accessor.dot.cs -->
+<!--                                                                    ^^^^^^^^^^^^^ variable.other.cs -->
+<!--                                                                                 ^ punctuation.accessor.dot.cs -->
+<!--                                                                                  ^^^^^^^^ variable.other.cs -->
+<!--                                                                                          ^ punctuation.definition.string.end.html -->
+<!--                                                                                            ^^^^^^^^^^^^^^^ entity.other.attribute-name.html -->
+<!--                                                                                                           ^ punctuation.separator.key-value.html -->
+<!--                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.html string.quoted.double.html -->
+<!--                                                                                                            ^ punctuation.definition.string.begin.html -->
+<!--                                                                                                             ^ punctuation.section.interpolation.begin.razor -->
+<!--                                                                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.cs.embedded.html-attribute-string.razor -->
+<!--                                                                                                              ^^^^^ variable.other.cs -->
+<!--                                                                                                                   ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                    ^^^^^^^^^^^^^ variable.other.cs -->
+<!--                                                                                                                                 ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                  ^^^^^^^^^^ variable.other.cs -->
+<!--                                                                                                                                            ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                             ^^^^^^^^^^ meta.function-call.cs -->
+<!--                                                                                                                                             ^^^^^^^^ variable.function.cs -->
+<!--                                                                                                                                                     ^^ meta.group.cs -->
+<!--                                                                                                                                                     ^ punctuation.section.group.begin.cs -->
+<!--                                                                                                                                                      ^ punctuation.section.group.end.cs -->
+<!--                                                                                                                                                       ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                                        ^^^^^^^^^ meta.function-call.cs -->
+<!--                                                                                                                                                        ^^^^^^^ variable.function.cs -->
+<!--                                                                                                                                                               ^^ meta.group.cs -->
+<!--                                                                                                                                                               ^ punctuation.section.group.begin.cs -->
+<!--                                                                                                                                                                ^ punctuation.section.group.end.cs -->
+<!--                                                                                                                                                                 ^ punctuation.definition.string.end.html -->
+<!--                                                                                                                                                                   ^^^^^^^^^^^^^^^^^^^^ entity.other.attribute-name.html -->
+<!--                                                                                                                                                                                        ^ punctuation.separator.key-value.html -->
+<!--                                                                                                                                                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.html string.quoted.double.html -->
+<!--                                                                                                                                                                                         ^ punctuation.definition.string.begin.html -->
+<!--                                                                                                                                                                                          ^ punctuation.section.interpolation.begin.razor -->
+<!--                                                                                                                                                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.cs.embedded.html-attribute-string.razor -->
+<!--                                                                                                                                                                                           ^^^^^ variable.other.cs -->
+<!--                                                                                                                                                                                                ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                                                                                 ^^^^^^^^^^^^^ variable.other.cs -->
+<!--                                                                                                                                                                                                              ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                                                                                               ^^^^^^^^^^^^^^^^^^^^ variable.other.cs -->
+<!--                                                                                                                                                                                                                                   ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                                                                                                                    ^^^^^^^^^^ meta.function-call.cs -->
+<!--                                                                                                                                                                                                                                    ^^^^^^^^ variable.function.cs -->
+<!--                                                                                                                                                                                                                                            ^^ meta.group.cs -->
+<!--                                                                                                                                                                                                                                            ^ punctuation.section.group.begin.cs -->
+<!--                                                                                                                                                                                                                                             ^ punctuation.section.group.end.cs -->
+<!--                                                                                                                                                                                                                                              ^ punctuation.accessor.dot.cs -->
+<!--                                                                                                                                                                                                                                               ^^^^^^^^^ meta.function-call.cs -->
+<!--                                                                                                                                                                                                                                               ^^^^^^^ variable.function.cs -->
+<!--                                                                                                                                                                                                                                                      ^^ meta.group.cs -->
+<!--                                                                                                                                                                                                                                                      ^ punctuation.section.group.begin.cs -->
+<!--                                                                                                                                                                                                                                                       ^ punctuation.section.group.end.cs -->
+<!--                                                                                                                                                                                                                                                        ^ punctuation.definition.string.end.html -->
+<!--                                                                                                                                                                                                                                                         ^ punctuation.definition.tag.end.html -->
+
+<li>
+    <a href="@Model.GetLinkForPage(Model.CurrentPage - 1)">«</a>
+<!--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.inline.any.html -->
+<!--^ punctuation.definition.tag.begin.html -->
+<!-- ^ entity.name.tag.inline.any.html -->
+<!--   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.attribute-with-value.href.html -->
+<!--   ^^^^ entity.other.attribute-name.href.html -->
+<!--       ^ punctuation.separator.key-value.html -->
+<!--        ^ meta.string.html string.quoted.double.html punctuation.definition.string.begin.html -->
+<!--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.path.url.html meta.string.html string.quoted.double.html -->
+<!--         ^ punctuation.section.interpolation.begin.razor -->
+<!--          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.cs.embedded.html-attribute-string.razor -->
+<!--          ^^^^^ variable.other.cs -->
+<!--               ^ punctuation.accessor.dot.cs -->
+<!--                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.cs -->
+<!--                ^^^^^^^^^^^^^^ variable.function.cs -->
+<!--                              ^^^^^^^^^^^^^^^^^^^^^^^ meta.group.cs -->
+<!--                              ^ punctuation.section.group.begin.cs -->
+<!--                               ^^^^^ variable.other.cs -->
+<!--                                    ^ punctuation.accessor.dot.cs -->
+<!--                                     ^^^^^^^^^^^ variable.other.cs -->
+<!--                                                 ^ keyword.operator.cs -->
+<!--                                                   ^ meta.number.integer.decimal.cs constant.numeric.value.cs -->
+<!--                                                    ^ punctuation.section.group.end.cs -->
+<!--                                                     ^ meta.string.html string.quoted.double.html punctuation.definition.string.end.html -->
+<!--                                                      ^ punctuation.definition.tag.end.html -->
+<!--                                                        ^^ punctuation.definition.tag.begin.html -->
+<!--                                                          ^ entity.name.tag.inline.any.html -->
+<!--                                                           ^ punctuation.definition.tag.end.html -->
+</li>
+<li>
+    <a href="@Model.FunctionCall("embedded string")">"quotes" everywhere</a>
+<!--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.inline.any.html -->
+<!--^ punctuation.definition.tag.begin.html -->
+<!-- ^ entity.name.tag.inline.any.html -->
+<!--   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.attribute-with-value.href.html -->
+<!--   ^^^^ entity.other.attribute-name.href.html -->
+<!--       ^ punctuation.separator.key-value.html -->
+<!--        ^ meta.string.html string.quoted.double.html punctuation.definition.string.begin.html -->
+<!--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.path.url.html meta.string.html string.quoted.double.html -->
+<!--         ^ punctuation.section.interpolation.begin.razor -->
+<!--          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.cs.embedded.html-attribute-string.razor -->
+<!--          ^^^^^ variable.other.cs -->
+<!--               ^ punctuation.accessor.dot.cs -->
+<!--                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.cs -->
+<!--                ^^^^^^^^^^^^ variable.function.cs -->
+<!--                            ^^^^^^^^^^^^^^^^^^^ meta.group.cs -->
+<!--                            ^ punctuation.section.group.begin.cs -->
+<!--                             ^^^^^^^^^^^^^^^^^ meta.string.cs string.quoted.double.cs -->
+<!--                             ^ punctuation.definition.string.begin.cs -->
+<!--                                             ^ punctuation.definition.string.end.cs -->
+<!--                                              ^ punctuation.section.group.end.cs -->
+<!--                                               ^ meta.string.html string.quoted.double.html punctuation.definition.string.end.html -->
+<!--                                                ^ punctuation.definition.tag.end.html -->
+<!--                                                                    ^^ punctuation.definition.tag.begin.html -->
+<!--                                                                      ^ entity.name.tag.inline.any.html -->
+<!--                                                                       ^ punctuation.definition.tag.end.html -->
+</li>
+
 @using (Html.BeginForm())
 {
     <div>