aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Davis2022-04-13 01:57:07 +0000
committerBlaž Hrastnik2022-04-13 05:28:51 +0000
commit4836bb38d3c13c9f1ebd3533bc35a54f80c7e118 (patch)
treef39037bc640054e67da289caa9bf433122d2f429
parent9d095e0fdc78ad42c033193dd980b6218c9484d6 (diff)
add tree-sitter-heex
HEEx is a templating engine on top of Elixir's EEx templating language specific to HTML that is included in Phoenix.LiveView (though I think the plan is to eventually include it in base Phoenix). It's a superset of EEx with some additional features like components and slots. The injections don't work perfectly because the Elixir grammar is newline sensitive (the _terminator rule). See https://github.com/elixir-lang/tree-sitter-elixir/issues/24 for more information.
-rw-r--r--book/src/generated/lang-support.md1
-rw-r--r--languages.toml12
-rw-r--r--runtime/queries/elixir/injections.scm7
-rw-r--r--runtime/queries/heex/highlights.scm58
-rw-r--r--runtime/queries/heex/injections.scm21
5 files changed, 99 insertions, 0 deletions
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index a58c1595..63f02d84 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -26,6 +26,7 @@
| graphql | ✓ | | | |
| haskell | ✓ | | | `haskell-language-server-wrapper` |
| hcl | ✓ | | ✓ | `terraform-ls` |
+| heex | ✓ | | | |
| html | ✓ | | | `vscode-html-language-server` |
| iex | ✓ | | | |
| java | ✓ | | | |
diff --git a/languages.toml b/languages.toml
index 79738db1..7f2a17ab 100644
--- a/languages.toml
+++ b/languages.toml
@@ -1125,3 +1125,15 @@ indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "eex"
source = { git = "https://github.com/connorlay/tree-sitter-eex", rev = "f742f2fe327463335e8671a87c0b9b396905d1d1" }
+
+[[language]]
+name = "heex"
+scope = "source.heex"
+injection-regex = "heex"
+file-types = ["heex"]
+roots = []
+indent = { tab-width = 2, unit = " " }
+
+[[grammar]]
+name = "heex"
+source = { git = "https://github.com/connorlay/tree-sitter-heex", rev = "592e22292a367312c35e13de7fdb888f029981d6" }
diff --git a/runtime/queries/elixir/injections.scm b/runtime/queries/elixir/injections.scm
index 8370a0d8..c8882534 100644
--- a/runtime/queries/elixir/injections.scm
+++ b/runtime/queries/elixir/injections.scm
@@ -7,3 +7,10 @@
(#match? @_sigil_name "^(r|R)$")
(#set! injection.language "regex")
(#set! injection.combined))
+
+((sigil
+ (sigil_name) @_sigil_name
+ (quoted_content) @injection.content)
+ (#match? @_sigil_name "^(h|H)$")
+ (#set! injection.language "heex")
+ (#set! injection.combined))
diff --git a/runtime/queries/heex/highlights.scm b/runtime/queries/heex/highlights.scm
new file mode 100644
index 00000000..301f57c8
--- /dev/null
+++ b/runtime/queries/heex/highlights.scm
@@ -0,0 +1,58 @@
+; https://github.com/connorlay/tree-sitter-heex/blob/592e22292a367312c35e13de7fdb888f029981d6/queries/highlights.scm
+; HEEx delimiters
+[
+ "<!"
+ "<!--"
+ "<"
+ "<%!--"
+ "<%#"
+ ">"
+ "</"
+ "--%>"
+ "-->"
+ "/>"
+ "{"
+ "}"
+ ; These could be `@keyword`s but the closing `>` wouldn't be highlighted
+ ; as `@keyword`
+ "<:"
+ "</:"
+] @punctuation.bracket
+
+; Non-comment or tag delimiters
+[
+ "<%"
+ "<%="
+ "<%%="
+ "%>"
+] @keyword
+
+; HEEx operators are highlighted as such
+"=" @operator
+
+; HEEx inherits the DOCTYPE tag from HTML
+(doctype) @constant
+
+; HEEx comments are highlighted as such
+(comment) @comment
+
+; HEEx tags are highlighted as HTML
+(tag_name) @tag
+
+; HEEx slots are highlighted as atoms (symbols)
+(slot_name) @string.special.symbol
+
+; HEEx attributes are highlighted as HTML attributes
+(attribute_name) @attribute
+[
+ (attribute_value)
+ (quoted_attribute_value)
+] @string
+
+; HEEx components are highlighted as Elixir modules and functions
+(component_name
+ [
+ (module) @module
+ (function) @function
+ "." @punctuation.delimiter
+ ])
diff --git a/runtime/queries/heex/injections.scm b/runtime/queries/heex/injections.scm
new file mode 100644
index 00000000..ad4e4faa
--- /dev/null
+++ b/runtime/queries/heex/injections.scm
@@ -0,0 +1,21 @@
+; https://github.com/connorlay/tree-sitter-heex/blob/592e22292a367312c35e13de7fdb888f029981d6/queries/injections.scm
+; directives are standalone tags like '<%= @x %>'
+;
+; partial_expression_values are elixir code that is part of an expression that
+; spans multiple directive nodes, so they must be combined. For example:
+; <%= if true do %>
+; <p>hello, tree-sitter!</p>
+; <% end %>
+((directive (partial_expression_value) @injection.content)
+ (#set! injection.language "elixir")
+ (#set! injection.include-children)
+ (#set! injection.combined))
+
+; Regular expression_values do not need to be combined
+((directive (expression_value) @injection.content)
+ (#set! injection.language "elixir"))
+
+; expressions live within HTML tags, and do not need to be combined
+; <link href={ Routes.static_path(..) } />
+((expression (expression_value) @injection.content)
+ (#set! injection.language "elixir"))