Simplify grammar patterns for tree-sitter compatibility

- Use simple regex patterns for comments, raw blocks, embedded languages
- Add support for unquoted import paths
- Use string literals for keyword highlighting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Netshipise 2026-01-19 20:32:14 +02:00
parent 7c37d0b3bc
commit 769d8bfc51
2 changed files with 25 additions and 260 deletions

View File

@ -40,9 +40,11 @@ module.exports = grammar({
),
),
// Template imports
// Template imports - supports both quoted "path" and unquoted /path
import_statement: ($) =>
seq("@import", $.string_literal, "as", $.identifier),
seq("@import", choice($.string_literal, $.import_path), "as", $.identifier),
import_path: ($) => /\/[^\s]+/,
// Struct definition
struct_definition: ($) =>
@ -100,7 +102,7 @@ module.exports = grammar({
// Function definition
function_definition: ($) =>
seq("@func", $.identifier, $.parameter_list, $.content_block),
seq("@fn", $.identifier, $.parameter_list, $.content_block),
parameter_list: ($) =>
seq(
@ -128,6 +130,7 @@ module.exports = grammar({
$.template_control_flow,
$.template_expression,
$.comment,
$.raw_block,
$.embedded_language,
$.escape_at,
$.text_content,
@ -223,7 +226,7 @@ module.exports = grammar({
),
expression_path: ($) =>
prec.left(seq(
seq(
$.identifier,
repeat(
choice(
@ -232,7 +235,7 @@ module.exports = grammar({
seq("(", optional($.argument_list), ")"),
),
),
)),
),
// Control flow
template_control_flow: ($) =>
@ -564,259 +567,25 @@ module.exports = grammar({
// Comments
comment: ($) => choice($.template_comment, $.html_comment),
// Template comments support variable asterisk counts: @* *@, @** **@, @*** ***@
// Template comments: @* ... *@ (simple form only for syntax highlighting)
template_comment: ($) =>
choice($.template_comment_1, $.template_comment_2, $.template_comment_3),
// Single asterisk: @* ... *@
template_comment_1: ($) =>
seq("@*", optional($.comment_content_1), "*@"),
comment_content_1: ($) => /([^*]|\*[^@])*/,
// Double asterisk: @** ... **@
template_comment_2: ($) =>
seq("@**", optional($.comment_content_2), "**@"),
comment_content_2: ($) => /([^*]|\*[^*]|\*\*[^@])*/,
// Triple asterisk: @*** ... ***@
template_comment_3: ($) =>
seq("@***", optional($.comment_content_3), "***@"),
comment_content_3: ($) => /([^*]|\*[^*]|\*\*[^*]|\*\*\*[^@])*/,
seq("@", /\*+/, optional(/([^*]|\*+[^@])*/), /\*+/, "@"),
// HTML comment: <!-- ... -->
html_comment: ($) => seq("<!--", optional($.html_comment_content), "-->"),
html_comment_content: ($) => /([^-]|-[^-]|--[^>])*/,
// Raw blocks: @#...#@ (simple form only for syntax highlighting)
raw_block: ($) =>
seq("@", /#+/, optional(/([^#]|#+[^@])*/), /#+/, "@"),
// Embedded language blocks: @```lang ... ```@
embedded_language: ($) =>
choice(
// JSON/Alpine blocks with structured parsing
seq("@```", choice("json", "alpine"), optional($.json_content), "```@"),
// JS blocks with structured parsing
seq("@```", choice("js", "javascript"), optional($.js_content), "```@"),
// CSS blocks with structured parsing
seq("@```", choice("css", "style"), optional($.css_content), "```@"),
// HTML blocks (less common, use simple content)
seq("@```", "html", optional($.embedded_content_simple), "```@"),
),
// Simple embedded content fallback
embedded_content_simple: ($) => /([^`]|`[^`]|``[^`])*/,
seq("@", /`+/, $.language_name, optional(/([^`]|`+[^@])*/), /`+/, "@"),
language_name: ($) =>
choice("html", "css", "js", "javascript", "json", "alpine", "style"),
// JSON content with template support
json_content: ($) =>
choice(
$.json_object,
$.json_array,
),
json_object: ($) =>
seq(
"{",
optional($.json_object_content),
"}",
),
json_object_content: ($) =>
seq(
$.json_member_or_control,
repeat(seq(optional(","), $.json_member_or_control)),
optional(","),
),
json_member_or_control: ($) =>
choice(
$.json_member,
$.json_control_flow,
),
json_member: ($) =>
seq(
choice($.json_key, $.template_expression),
":",
$.json_value,
),
json_key: ($) =>
choice(
$.string_literal,
$.identifier, // Allow unquoted keys for JS object shorthand
),
json_value: ($) =>
choice(
$.json_object,
$.json_array,
$.string_literal,
$.number_literal,
$.boolean_literal,
"null",
$.template_expression,
$.json_method, // For Alpine.js method shorthand
),
json_array: ($) =>
seq(
"[",
optional($.json_array_content),
"]",
),
json_array_content: ($) =>
seq(
$.json_array_element,
repeat(seq(optional(","), $.json_array_element)),
optional(","),
),
json_array_element: ($) =>
choice(
$.json_value,
$.json_control_flow,
),
// Control flow in JSON context
json_control_flow: ($) =>
choice(
$.json_if_statement,
$.json_for_loop,
),
json_if_statement: ($) =>
seq(
"@if",
$.expression,
"{",
optional($.json_if_body),
"}",
optional(seq("else", "{", optional($.json_if_body), "}")),
),
// Body of @if in JSON can contain members or array elements
json_if_body: ($) =>
seq(
$.json_if_element,
repeat(seq(optional(","), $.json_if_element)),
optional(","),
),
json_if_element: ($) =>
choice(
$.json_member,
$.json_value,
$.json_control_flow,
),
json_for_loop: ($) =>
seq(
"@for",
$.simple_pattern,
"in",
$.expression,
"{",
optional($.json_if_body),
"}",
),
// Alpine.js method shorthand: toggle() { this.open = !this.open; }
json_method: ($) =>
seq(
$.identifier,
"(",
optional($.json_method_params),
")",
"{",
optional($.js_content),
"}",
),
json_method_params: ($) =>
seq($.identifier, repeat(seq(",", $.identifier))),
// JavaScript content with template support
js_content: ($) => repeat1($.js_element),
js_element: ($) =>
choice(
$.js_control_flow,
$.template_expression,
$.js_code,
),
js_control_flow: ($) =>
choice(
$.js_if_statement,
$.js_for_loop,
),
js_if_statement: ($) =>
seq(
"@if",
$.expression,
"{",
optional($.js_content),
"}",
optional(seq("else", "{", optional($.js_content), "}")),
),
js_for_loop: ($) =>
seq(
"@for",
$.simple_pattern,
"in",
$.expression,
"{",
optional($.js_content),
"}",
),
// Raw JS code (anything that's not @expression or @control_flow)
js_code: ($) => token(prec(-1, /[^@`]+/)),
// CSS content with template support
css_content: ($) => repeat1($.css_element),
css_element: ($) =>
choice(
$.css_control_flow,
$.template_expression,
$.css_code,
),
css_control_flow: ($) =>
choice(
$.css_if_statement,
$.css_for_loop,
),
css_if_statement: ($) =>
seq(
"@if",
$.expression,
"{",
optional($.css_content),
"}",
optional(seq("else", "{", optional($.css_content), "}")),
),
css_for_loop: ($) =>
seq(
"@for",
$.simple_pattern,
"in",
$.expression,
"{",
optional($.css_content),
"}",
),
// Raw CSS code
css_code: ($) => token(prec(-1, /[^@`]+/)),
// Escape sequence for literal @
escape_at: ($) => "@@",

View File

@ -1,18 +1,20 @@
; Waltzing Template Highlights
; Comments (all template comment variants)
(template_comment) @comment
(template_comment_1) @comment
(template_comment_2) @comment
(template_comment_3) @comment
; Comments
(html_comment) @comment
; Raw blocks (verbatim content)
(raw_block) @string.special
; Template comments
(template_comment) @comment
; Keywords
"@use" @keyword
"@import" @keyword
"@struct" @keyword
"@enum" @keyword
"@func" @keyword
"@fn" @keyword
"@let" @keyword
"@if" @keyword
"@for" @keyword
@ -97,14 +99,8 @@
(escape_sequence) @escape
(escape_at) @escape
; Embedded language names
"json" @label
"alpine" @label
"js" @label
"javascript" @label
"css" @label
"style" @label
"html" @label
; Embedded
(language_name) @label
; Variables (fallback)
(identifier) @variable