Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--book/src/generated/lang-support.md2
-rw-r--r--languages.toml2
-rw-r--r--runtime/queries/svelte/folds.scm20
-rw-r--r--runtime/queries/svelte/highlights.scm147
-rw-r--r--runtime/queries/svelte/indents.scm28
-rw-r--r--runtime/queries/svelte/injections.scm186
-rw-r--r--runtime/queries/svelte/locals.scm9
-rw-r--r--runtime/queries/svelte/rainbows.scm47
-rw-r--r--runtime/queries/svelte/tags.scm11
-rw-r--r--runtime/queries/svelte/textobjects.scm11
10 files changed, 366 insertions, 97 deletions
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index a3294acd..3accd33f 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -277,7 +277,7 @@
| strictdoc | ✓ | | | ✓ | | |
| styx | ✓ | ✓ | ✓ | | ✓ | `styx` |
| supercollider | ✓ | | | | | |
-| svelte | ✓ | ✓ | ✓ | | ✓ | `svelteserver` |
+| svelte | ✓ | ✓ | ✓ | ✓ | ✓ | `svelteserver` |
| sway | ✓ | ✓ | ✓ | | | `forc` |
| swift | ✓ | ✓ | ✓ | | ✓ | `sourcekit-lsp` |
| systemd | ✓ | | | ✓ | | `systemd-lsp` |
diff --git a/languages.toml b/languages.toml
index 9de6c04e..edbf7f6b 100644
--- a/languages.toml
+++ b/languages.toml
@@ -1649,7 +1649,7 @@ language-servers = [ "svelteserver" ]
[[grammar]]
name = "svelte"
-source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-svelte", rev = "ae5199db47757f785e43a14b332118a5474de1a2" }
+source = { git = "https://github.com/themixednuts/tree-sitter-htmlx", rev = "3be6db3dc94478b089a64e59e4d855fc3041a7be", subpath = "crates/tree-sitter-svelte" }
[[language]]
name = "vue"
diff --git a/runtime/queries/svelte/folds.scm b/runtime/queries/svelte/folds.scm
index 6440301a..e50b368b 100644
--- a/runtime/queries/svelte/folds.scm
+++ b/runtime/queries/svelte/folds.scm
@@ -1,13 +1,11 @@
-; inherits: html
-
[
- (if_statement)
- (else_if_block)
- (else_block)
- (each_statement)
- (await_statement)
- (then_block)
- (catch_block)
- (key_statement)
- (snippet_statement)
+ (element)
+ (if_block)
+ (else_if_clause)
+ (else_clause)
+ (each_block)
+ (await_block)
+ (await_branch)
+ (key_block)
+ (snippet_block)
] @fold
diff --git a/runtime/queries/svelte/highlights.scm b/runtime/queries/svelte/highlights.scm
index 12e1bcd0..141cbb89 100644
--- a/runtime/queries/svelte/highlights.scm
+++ b/runtime/queries/svelte/highlights.scm
@@ -1,40 +1,139 @@
-; inherits: html
+; Tag names
+(tag_name) @tag
+; Erroneous/mismatched end tags
+(erroneous_end_tag_name) @error
+
+; DOCTYPE declaration
+(doctype) @constant
+
+; Attribute names
+(attribute_name) @attribute
+
+; Attribute values
+(attribute_value) @string
+(quoted_attribute_value) @string
+
+; Comments
+(comment) @comment
+
+; Character entities
+(entity) @string.special.symbol
+
+; Text content
+(text) @text
+
+; Raw text in script/style
(raw_text) @none
+; HTML punctuation
[
- "as"
- "key"
- "html"
- "debug"
- "snippet"
- "render"
-] @keyword
+ "<"
+ ">"
+ "</"
+ "/>"
+ "<!"
+] @punctuation.bracket
-"const" @keyword.storage.modifier
+"=" @punctuation.delimiter
-[
- "if"
- "else if"
- "else"
- "then"
- "await"
-] @keyword.control.conditional
+; Component tags (PascalCase)
+((tag_name) @type (#match? @type "^[A-Z]"))
+
+; Namespaced tags (svelte:component, svelte:self, etc.)
+(tag_name
+ namespace: (tag_namespace) @keyword
+ ":" @punctuation.delimiter
+ name: (tag_local_name) @tag)
+
+; Tag member access (Foo.Bar)
+(tag_name
+ object: (tag_member) @type
+ "." @punctuation.delimiter
+ property: (tag_member) @tag)
-"each" @keyword.control.repeat
+; Directives (on:click, bind:value, etc.)
+(attribute_directive) @keyword
+(attribute_name ":" @punctuation.delimiter)
+(attribute_identifier) @property
+(attribute_modifier) @attribute
+(attribute_modifiers "|" @punctuation.delimiter)
-"catch" @keyword.control.exception
+; Expressions
+(expression) @embedded
+(expression_value) @embedded
+; Shorthand/spread attributes
+(shorthand_attribute content: (_) @variable)
+
+; Curly braces (expression context)
[
"{"
"}"
] @punctuation.bracket
+"|" @punctuation.delimiter
+
+; Comments inside tag attribute lists
+(tag_comment kind: (line_comment) @comment)
+(tag_comment kind: (block_comment) @comment)
+
+; Block keywords
[
- "#"
- ":"
- "/"
- "@"
-] @punctuation.delimiter
+ "if"
+ "each"
+ "await"
+ "key"
+ "snippet"
+ "else"
+ "html"
+ "debug"
+ "const"
+ "render"
+ "attach"
+ "as"
+] @keyword.control
-(snippet_name) @function
+; Block end keywords ({/if}, {/each}, etc.)
+(block_keyword) @keyword.control
+
+; Block delimiters
+(block_open) @punctuation.bracket
+(block_close) @punctuation.bracket
+
+(shorthand_kind) @keyword.control
+(branch_kind) @keyword.control
+
+; If block
+(if_block expression: (expression) @embedded)
+(else_if_clause expression: (expression_value) @embedded)
+
+; Each block
+(each_block expression: (expression) @embedded)
+(each_block binding: (pattern) @variable)
+(each_block index: (pattern) @variable)
+(each_block key: (expression) @embedded)
+
+; Await block
+(await_block expression: (expression) @embedded)
+(await_branch (pattern) @variable)
+(await_block (pattern) @variable)
+(orphan_branch (pattern) @variable)
+
+; Key block
+(key_block expression: (expression) @embedded)
+
+; Snippet block
+(snippet_block name: (snippet_name) @function)
+(snippet_parameters parameter: (pattern) @variable)
+(snippet_type_parameters) @type
+
+; Malformed blocks
+(block_sigil) @keyword.control
+
+; Snippet/render punctuation
+[
+ "("
+ ")"
+ ","
+] @punctuation.delimiter
diff --git a/runtime/queries/svelte/indents.scm b/runtime/queries/svelte/indents.scm
index 4bb103d7..4e4e0904 100644
--- a/runtime/queries/svelte/indents.scm
+++ b/runtime/queries/svelte/indents.scm
@@ -1,24 +1,20 @@
[
(element)
- (start_tag)
- (if_statement)
- (else_if_block)
- (else_block)
- (then_block)
- (each_statement)
- (key_statement)
- (snippet_statement)
- (await_statement)
- (style_element)
- (script_element)
+ (if_block)
+ (else_if_clause)
+ (else_clause)
+ (await_branch)
+ (each_block)
+ (key_block)
+ (snippet_block)
+ (await_block)
(expression)
] @indent
[
(end_tag)
- (if_end)
- (each_end)
- (await_end)
- (key_end)
- (snippet_end)
+ (block_end)
+ (else_if_clause)
+ (else_clause)
+ (await_branch)
] @outdent
diff --git a/runtime/queries/svelte/injections.scm b/runtime/queries/svelte/injections.scm
index c94373c1..d40ae322 100644
--- a/runtime/queries/svelte/injections.scm
+++ b/runtime/queries/svelte/injections.scm
@@ -1,46 +1,182 @@
-; inherits html
-((style_element
+; Script elements with TypeScript aliases
+((element
(start_tag
+ (tag_name) @_tag
(attribute
- (attribute_name) @_attr
(quoted_attribute_value
- (attribute_value) @_lang)))
+ (attribute_value) @_value)))
(raw_text) @injection.content)
- (#eq? @_attr "lang")
- (#any-of? @_lang "scss" "postcss" "less")
- (#set! injection.language "scss"))
-
-((svelte_raw_text) @injection.content
+ (#match? @_tag "^[Ss][Cc][Rr][Ii][Pp][Tt]$")
+ (#any-of? @_value "ts" "typescript" "text/typescript")
(#set! injection.language "typescript"))
-((script_element
+; Script elements with explicit language
+((element
(start_tag
+ (tag_name) @_tag
(attribute
- (attribute_name) @_attr
+ (attribute_name) @_lang
(quoted_attribute_value
- (attribute_value) @_lang)))
+ (attribute_value) @injection.language)))
(raw_text) @injection.content)
- (#eq? @_attr "lang")
- (#any-of? @_lang "ts" "typescript")
- (#set! injection.language "typescript"))
+ (#eq? @_tag "script")
+ (#eq? @_lang "lang")
+ (#not-any-of? @injection.language "ts" "typescript" "text/typescript"))
+
+; Script content defaults to JavaScript
+((element
+ (start_tag (tag_name) @_tag)
+ (raw_text) @injection.content)
+ (#eq? @_tag "script")
+ (#set! injection.language "javascript"))
-((script_element
+; Style with lang="scss"
+((element
(start_tag
+ (tag_name) @_tag
(attribute
- (attribute_name) @_attr
(quoted_attribute_value
- (attribute_value) @_lang)))
+ (attribute_value) @_scss)))
(raw_text) @injection.content)
- (#eq? @_attr "lang")
- (#any-of? @_lang "js" "javascript")
- (#set! injection.language "javascript"))
+ (#eq? @_tag "style")
+ (#eq? @_scss "scss")
+ (#set! injection.language "scss"))
+
+; Style with lang="sass"
+((element
+ (start_tag
+ (tag_name) @_tag
+ (attribute
+ (quoted_attribute_value
+ (attribute_value) @_sass)))
+ (raw_text) @injection.content)
+ (#eq? @_tag "style")
+ (#eq? @_sass "sass")
+ (#set! injection.language "sass"))
+; Style with lang="less"
((element
(start_tag
+ (tag_name) @_tag
(attribute
- (attribute_name) @_attr
+ (quoted_attribute_value
+ (attribute_value) @_less)))
+ (raw_text) @injection.content)
+ (#eq? @_tag "style")
+ (#eq? @_less "less")
+ (#set! injection.language "less"))
+
+; Style with explicit language
+((element
+ (start_tag
+ (tag_name) @_tag
+ (attribute
+ (attribute_name) @_lang
(quoted_attribute_value
(attribute_value) @injection.language)))
- (text) @injection.content)
- (#eq? @_attr "lang")
- (#eq? @injection.language "pug"))
+ (raw_text) @injection.content)
+ (#eq? @_tag "style")
+ (#eq? @_lang "lang")
+ (#not-any-of? @injection.language "scss" "sass" "less"))
+
+; Style content defaults to CSS when no lang attribute is present
+((element
+ (start_tag
+ (tag_name) @_tag
+ (attribute
+ (attribute_name) @_style_attr)*)
+ (raw_text) @injection.content)
+ (#eq? @_tag "style")
+ (#not-any-of? @_style_attr "lang")
+ (#set! injection.language "css"))
+
+; Inline style attribute
+((attribute
+ (attribute_name) @_style_name
+ (quoted_attribute_value (attribute_value) @injection.content))
+ (#eq? @_style_name "style")
+ (#set! injection.language "css"))
+
+; Typed expression content
+((expression content: (js) @injection.content)
+ (#set! injection.language "javascript"))
+((expression content: (ts) @injection.content)
+ (#set! injection.language "typescript"))
+
+; Shorthand attributes ({foo})
+((shorthand_attribute content: (js) @injection.content)
+ (#set! injection.language "javascript"))
+((shorthand_attribute content: (ts) @injection.content)
+ (#set! injection.language "typescript"))
+
+; Tag expressions ({@const}, {@render}, {@html}, {@debug}, {@attach}, {:else if})
+((expression_value content: (js) @injection.content)
+ (#set! injection.language "javascript"))
+((expression_value content: (ts) @injection.content)
+ (#set! injection.language "typescript"))
+
+; Else-if clause
+((else_if_clause expression: (expression_value content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((else_if_clause expression: (expression_value content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+
+; If block expressions
+((if_block expression: (expression content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((if_block expression: (expression content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+
+; Each block expressions and bindings
+((each_block expression: (expression content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((each_block expression: (expression content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((each_block binding: (pattern content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((each_block binding: (pattern content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((each_block index: (pattern content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((each_block index: (pattern content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((each_block key: (expression content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((each_block key: (expression content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+
+; Await block expressions and bindings
+((await_block expression: (expression content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((await_block expression: (expression content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((await_block (pattern content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((await_block (pattern content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((await_branch (pattern content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((await_branch (pattern content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((orphan_branch (pattern content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((orphan_branch (pattern content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+
+; Key block expressions
+((key_block expression: (expression content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((key_block expression: (expression content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+
+; Snippet parameters and type parameters
+((snippet_parameters parameter: (pattern content: (js) @injection.content))
+ (#set! injection.language "javascript"))
+((snippet_parameters parameter: (pattern content: (ts) @injection.content))
+ (#set! injection.language "typescript"))
+((snippet_block type_parameters: (snippet_type_parameters) @injection.content)
+ (#set! injection.language "typescript"))
+
+; Comments
+((comment) @injection.content
+ (#set! injection.language "comment"))
diff --git a/runtime/queries/svelte/locals.scm b/runtime/queries/svelte/locals.scm
index 1f2129cf..14f11b09 100644
--- a/runtime/queries/svelte/locals.scm
+++ b/runtime/queries/svelte/locals.scm
@@ -1 +1,8 @@
-; inherits: html
+(snippet_block) @local.scope
+
+(snippet_parameters
+ parameter: (pattern) @local.definition.variable.parameter)
+
+(snippet_name) @local.definition.function
+
+(tag_name) @local.reference
diff --git a/runtime/queries/svelte/rainbows.scm b/runtime/queries/svelte/rainbows.scm
index d05058e2..ce95ffd3 100644
--- a/runtime/queries/svelte/rainbows.scm
+++ b/runtime/queries/svelte/rainbows.scm
@@ -1,25 +1,38 @@
-; inherits: html
+[
+ (doctype)
+ (erroneous_end_tag)
+] @rainbow.scope
+
+([
+ (element)
+ ] @rainbow.scope
+ (#set! rainbow.include-children))
[
- (if_start)
- (else_if_start)
- (else_start)
- (if_end)
- (each_start)
- (each_end)
- (await_start)
- (then_start)
- (catch_start)
- (await_end)
- (key_start)
- (key_end)
- (snippet_start)
- (snippet_end)
- (expression)
+ (if_block)
+ (else_if_clause)
+ (else_clause)
+ (each_block)
+ (await_block)
+ (await_branch)
+ (attach_tag)
(html_tag)
(const_tag)
(debug_tag)
(render_tag)
+ (key_block)
+ (snippet_block)
+ (expression)
] @rainbow.scope
-["{" "}"] @rainbow.bracket
+[
+ "<"
+ ">"
+ "<!"
+ "</"
+ "/>"
+ (block_open)
+ (block_close)
+ "{"
+ "}"
+] @rainbow.bracket
diff --git a/runtime/queries/svelte/tags.scm b/runtime/queries/svelte/tags.scm
new file mode 100644
index 00000000..c2fcb1c2
--- /dev/null
+++ b/runtime/queries/svelte/tags.scm
@@ -0,0 +1,11 @@
+; Snippet declarations
+(snippet_block
+ name: (snippet_name) @name) @definition.function
+
+; Component references
+((tag_name) @name @reference.class
+ (#match? @name "^[A-Z]"))
+
+(tag_name
+ object: (tag_member) @name
+ property: (tag_member) @name) @reference.class
diff --git a/runtime/queries/svelte/textobjects.scm b/runtime/queries/svelte/textobjects.scm
index 1f2129cf..12fa8b77 100644
--- a/runtime/queries/svelte/textobjects.scm
+++ b/runtime/queries/svelte/textobjects.scm
@@ -1 +1,10 @@
-; inherits: html
+(element (start_tag) (_)* @xml-element.inside (end_tag))
+
+(element) @xml-element.around
+
+(comment) @comment.around
+
+(snippet_block
+ parameters: (snippet_parameters) @parameter.inside) @function.around
+
+(snippet_name) @function.inside