diff --git a/.changeset/brave-suns-knock.md b/.changeset/brave-suns-knock.md new file mode 100644 index 000000000000..a08c36240509 --- /dev/null +++ b/.changeset/brave-suns-knock.md @@ -0,0 +1,15 @@ +--- +"@biomejs/biome": patch +--- + +Added support for parsing and formatting the Svelte `{#await}` syntax, when `html.experimentalFullSupportEnabled` is set to `true`. + +```diff +-{#await promise then name } ++{#await promise then name} + +-{:catch name} ++{:catch name} + +{/await} +``` diff --git a/.changeset/silver-needles-flow.md b/.changeset/silver-needles-flow.md new file mode 100644 index 000000000000..e0ea5ee30c2f --- /dev/null +++ b/.changeset/silver-needles-flow.md @@ -0,0 +1,12 @@ +--- +"@biomejs/biome": patch +--- + +Added support for parsing and formatting the Svelte `{#snippet}` syntax, when `html.experimentalFullSupportEnabled` is set to `true`. + +```diff +-{#snippet foo() } ++{#snippet foo()} + +{/snippe} +``` diff --git a/crates/biome_html_factory/src/generated/node_factory.rs b/crates/biome_html_factory/src/generated/node_factory.rs index 4a780da313fa..84c558f2a850 100644 --- a/crates/biome_html_factory/src/generated/node_factory.rs +++ b/crates/biome_html_factory/src/generated/node_factory.rs @@ -363,6 +363,146 @@ pub fn svelte_attach_attribute( ], )) } +pub fn svelte_await_block( + opening_block: SvelteAwaitOpeningBlock, + clauses: SvelteAwaitClausesList, + closing_block: SvelteAwaitClosingBlock, +) -> SvelteAwaitBlock { + SvelteAwaitBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_BLOCK, + [ + Some(SyntaxElement::Node(opening_block.into_syntax())), + Some(SyntaxElement::Node(clauses.into_syntax())), + Some(SyntaxElement::Node(closing_block.into_syntax())), + ], + )) +} +pub fn svelte_await_catch_block( + sv_curly_colon_token: SyntaxToken, + catch_token: SyntaxToken, + name: HtmlTextExpression, + r_curly_token: SyntaxToken, + children: HtmlElementList, +) -> SvelteAwaitCatchBlock { + SvelteAwaitCatchBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_CATCH_BLOCK, + [ + Some(SyntaxElement::Token(sv_curly_colon_token)), + Some(SyntaxElement::Token(catch_token)), + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Token(r_curly_token)), + Some(SyntaxElement::Node(children.into_syntax())), + ], + )) +} +pub fn svelte_await_catch_clause( + catch_token: SyntaxToken, + name: HtmlTextExpression, +) -> SvelteAwaitCatchClause { + SvelteAwaitCatchClause::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_CATCH_CLAUSE, + [ + Some(SyntaxElement::Token(catch_token)), + Some(SyntaxElement::Node(name.into_syntax())), + ], + )) +} +pub fn svelte_await_closing_block( + sv_curly_slash_token: SyntaxToken, + await_token: SyntaxToken, + r_curly_token: SyntaxToken, +) -> SvelteAwaitClosingBlock { + SvelteAwaitClosingBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_CLOSING_BLOCK, + [ + Some(SyntaxElement::Token(sv_curly_slash_token)), + Some(SyntaxElement::Token(await_token)), + Some(SyntaxElement::Token(r_curly_token)), + ], + )) +} +pub fn svelte_await_opening_block( + sv_curly_hash_token: SyntaxToken, + await_token: SyntaxToken, + expression: HtmlTextExpression, + r_curly_token: SyntaxToken, + children: HtmlElementList, +) -> SvelteAwaitOpeningBlockBuilder { + SvelteAwaitOpeningBlockBuilder { + sv_curly_hash_token, + await_token, + expression, + r_curly_token, + children, + then_clause: None, + catch_clause: None, + } +} +pub struct SvelteAwaitOpeningBlockBuilder { + sv_curly_hash_token: SyntaxToken, + await_token: SyntaxToken, + expression: HtmlTextExpression, + r_curly_token: SyntaxToken, + children: HtmlElementList, + then_clause: Option, + catch_clause: Option, +} +impl SvelteAwaitOpeningBlockBuilder { + pub fn with_then_clause(mut self, then_clause: SvelteAwaitThenClause) -> Self { + self.then_clause = Some(then_clause); + self + } + pub fn with_catch_clause(mut self, catch_clause: SvelteAwaitCatchClause) -> Self { + self.catch_clause = Some(catch_clause); + self + } + pub fn build(self) -> SvelteAwaitOpeningBlock { + SvelteAwaitOpeningBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_OPENING_BLOCK, + [ + Some(SyntaxElement::Token(self.sv_curly_hash_token)), + Some(SyntaxElement::Token(self.await_token)), + Some(SyntaxElement::Node(self.expression.into_syntax())), + self.then_clause + .map(|token| SyntaxElement::Node(token.into_syntax())), + self.catch_clause + .map(|token| SyntaxElement::Node(token.into_syntax())), + Some(SyntaxElement::Token(self.r_curly_token)), + Some(SyntaxElement::Node(self.children.into_syntax())), + ], + )) + } +} +pub fn svelte_await_then_block( + sv_curly_colon_token: SyntaxToken, + then_token: SyntaxToken, + name: HtmlTextExpression, + r_curly_token: SyntaxToken, + children: HtmlElementList, +) -> SvelteAwaitThenBlock { + SvelteAwaitThenBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_THEN_BLOCK, + [ + Some(SyntaxElement::Token(sv_curly_colon_token)), + Some(SyntaxElement::Token(then_token)), + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Token(r_curly_token)), + Some(SyntaxElement::Node(children.into_syntax())), + ], + )) +} +pub fn svelte_await_then_clause( + then_token: SyntaxToken, + name: HtmlTextExpression, +) -> SvelteAwaitThenClause { + SvelteAwaitThenClause::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_THEN_CLAUSE, + [ + Some(SyntaxElement::Token(then_token)), + Some(SyntaxElement::Node(name.into_syntax())), + ], + )) +} pub fn svelte_const_block( sv_curly_at_token: SyntaxToken, const_token: SyntaxToken, @@ -754,6 +894,50 @@ pub fn svelte_render_block( ], )) } +pub fn svelte_snippet_block( + opening_block: SvelteSnippetOpeningBlock, + closing_block: SvelteSnippetClosingBlock, +) -> SvelteSnippetBlock { + SvelteSnippetBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_SNIPPET_BLOCK, + [ + Some(SyntaxElement::Node(opening_block.into_syntax())), + Some(SyntaxElement::Node(closing_block.into_syntax())), + ], + )) +} +pub fn svelte_snippet_closing_block( + sv_curly_slash_token: SyntaxToken, + snippet_token: SyntaxToken, + r_curly_token: SyntaxToken, +) -> SvelteSnippetClosingBlock { + SvelteSnippetClosingBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_SNIPPET_CLOSING_BLOCK, + [ + Some(SyntaxElement::Token(sv_curly_slash_token)), + Some(SyntaxElement::Token(snippet_token)), + Some(SyntaxElement::Token(r_curly_token)), + ], + )) +} +pub fn svelte_snippet_opening_block( + sv_curly_hash_token: SyntaxToken, + snippet_token: SyntaxToken, + expression: HtmlTextExpression, + r_curly_token: SyntaxToken, + children: HtmlElementList, +) -> SvelteSnippetOpeningBlock { + SvelteSnippetOpeningBlock::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_SNIPPET_OPENING_BLOCK, + [ + Some(SyntaxElement::Token(sv_curly_hash_token)), + Some(SyntaxElement::Token(snippet_token)), + Some(SyntaxElement::Node(expression.into_syntax())), + Some(SyntaxElement::Token(r_curly_token)), + Some(SyntaxElement::Node(children.into_syntax())), + ], + )) +} pub fn vue_directive(name_token: SyntaxToken, modifiers: VueModifierList) -> VueDirectiveBuilder { VueDirectiveBuilder { name_token, @@ -960,6 +1144,18 @@ where .map(|item| Some(item.into_syntax().into())), )) } +pub fn svelte_await_clauses_list(items: I) -> SvelteAwaitClausesList +where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, +{ + SvelteAwaitClausesList::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::SVELTE_AWAIT_CLAUSES_LIST, + items + .into_iter() + .map(|item| Some(item.into_syntax().into())), + )) +} pub fn svelte_binding_list(items: I, separators: S) -> SvelteBindingList where I: IntoIterator, diff --git a/crates/biome_html_factory/src/generated/syntax_factory.rs b/crates/biome_html_factory/src/generated/syntax_factory.rs index b66e8256316f..efe1463d5f9a 100644 --- a/crates/biome_html_factory/src/generated/syntax_factory.rs +++ b/crates/biome_html_factory/src/generated/syntax_factory.rs @@ -656,6 +656,279 @@ impl SyntaxFactory for HtmlSyntaxFactory { } slots.into_node(SVELTE_ATTACH_ATTRIBUTE, children) } + SVELTE_AWAIT_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && SvelteAwaitOpeningBlock::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && SvelteAwaitClausesList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && SvelteAwaitClosingBlock::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_BLOCK, children) + } + SVELTE_AWAIT_CATCH_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<5usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T!["{:"] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T![catch] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlTextExpression::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T!['}'] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlElementList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_CATCH_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_CATCH_BLOCK, children) + } + SVELTE_AWAIT_CATCH_CLAUSE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T![catch] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlTextExpression::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_CATCH_CLAUSE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_CATCH_CLAUSE, children) + } + SVELTE_AWAIT_CLOSING_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T!["{/"] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T![await] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T!['}'] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_CLOSING_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_CLOSING_BLOCK, children) + } + SVELTE_AWAIT_OPENING_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<7usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T!["{#"] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T![await] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlTextExpression::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && SvelteAwaitThenClause::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && SvelteAwaitCatchClause::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T!['}'] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlElementList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_OPENING_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_OPENING_BLOCK, children) + } + SVELTE_AWAIT_THEN_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<5usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T!["{:"] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T![then] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlTextExpression::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T!['}'] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlElementList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_THEN_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_THEN_BLOCK, children) + } + SVELTE_AWAIT_THEN_CLAUSE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T![then] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlTextExpression::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_AWAIT_THEN_CLAUSE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_AWAIT_THEN_CLAUSE, children) + } SVELTE_CONST_BLOCK => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); @@ -1393,6 +1666,112 @@ impl SyntaxFactory for HtmlSyntaxFactory { } slots.into_node(SVELTE_RENDER_BLOCK, children) } + SVELTE_SNIPPET_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && SvelteSnippetOpeningBlock::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && SvelteSnippetClosingBlock::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_SNIPPET_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_SNIPPET_BLOCK, children) + } + SVELTE_SNIPPET_CLOSING_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T!["{/"] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T![snippet] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T!['}'] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_SNIPPET_CLOSING_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_SNIPPET_CLOSING_BLOCK, children) + } + SVELTE_SNIPPET_OPENING_BLOCK => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<5usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && element.kind() == T!["{#"] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T![snippet] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlTextExpression::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && element.kind() == T!['}'] + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if let Some(element) = ¤t_element + && HtmlElementList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + SVELTE_SNIPPET_OPENING_BLOCK.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(SVELTE_SNIPPET_OPENING_BLOCK, children) + } VUE_DIRECTIVE => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); @@ -1656,6 +2035,9 @@ impl SyntaxFactory for HtmlSyntaxFactory { HTML_ELEMENT_LIST => { Self::make_node_list_syntax(kind, children, AnyHtmlElement::can_cast) } + SVELTE_AWAIT_CLAUSES_LIST => { + Self::make_node_list_syntax(kind, children, AnySvelteAwaitClauses::can_cast) + } SVELTE_BINDING_LIST => Self::make_separated_list_syntax( kind, children, diff --git a/crates/biome_html_formatter/src/generated.rs b/crates/biome_html_formatter/src/generated.rs index 887911f3a9f0..196ebbe7f7b7 100644 --- a/crates/biome_html_formatter/src/generated.rs +++ b/crates/biome_html_formatter/src/generated.rs @@ -754,6 +754,272 @@ impl IntoFormat for biome_html_syntax::SvelteAttachAttribute ) } } +impl FormatRule + for crate::svelte::auxiliary::await_block::FormatSvelteAwaitBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitBlock, + crate::svelte::auxiliary::await_block::FormatSvelteAwaitBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_block::FormatSvelteAwaitBlock::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitBlock, + crate::svelte::auxiliary::await_block::FormatSvelteAwaitBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_block::FormatSvelteAwaitBlock::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::await_catch_block::FormatSvelteAwaitCatchBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitCatchBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitCatchBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitCatchBlock, + crate::svelte::auxiliary::await_catch_block::FormatSvelteAwaitCatchBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_catch_block::FormatSvelteAwaitCatchBlock::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitCatchBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitCatchBlock, + crate::svelte::auxiliary::await_catch_block::FormatSvelteAwaitCatchBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_catch_block::FormatSvelteAwaitCatchBlock::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::await_catch_clause::FormatSvelteAwaitCatchClause +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitCatchClause, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitCatchClause { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitCatchClause, + crate::svelte::auxiliary::await_catch_clause::FormatSvelteAwaitCatchClause, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_catch_clause::FormatSvelteAwaitCatchClause::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitCatchClause { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitCatchClause, + crate::svelte::auxiliary::await_catch_clause::FormatSvelteAwaitCatchClause, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_catch_clause::FormatSvelteAwaitCatchClause::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::await_closing_block::FormatSvelteAwaitClosingBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitClosingBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitClosingBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitClosingBlock, + crate::svelte::auxiliary::await_closing_block::FormatSvelteAwaitClosingBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_closing_block::FormatSvelteAwaitClosingBlock::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitClosingBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitClosingBlock, + crate::svelte::auxiliary::await_closing_block::FormatSvelteAwaitClosingBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_closing_block::FormatSvelteAwaitClosingBlock::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::await_opening_block::FormatSvelteAwaitOpeningBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitOpeningBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitOpeningBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitOpeningBlock, + crate::svelte::auxiliary::await_opening_block::FormatSvelteAwaitOpeningBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_opening_block::FormatSvelteAwaitOpeningBlock::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitOpeningBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitOpeningBlock, + crate::svelte::auxiliary::await_opening_block::FormatSvelteAwaitOpeningBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_opening_block::FormatSvelteAwaitOpeningBlock::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::await_then_block::FormatSvelteAwaitThenBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitThenBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitThenBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitThenBlock, + crate::svelte::auxiliary::await_then_block::FormatSvelteAwaitThenBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_then_block::FormatSvelteAwaitThenBlock::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitThenBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitThenBlock, + crate::svelte::auxiliary::await_then_block::FormatSvelteAwaitThenBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_then_block::FormatSvelteAwaitThenBlock::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::await_then_clause::FormatSvelteAwaitThenClause +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteAwaitThenClause, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteAwaitThenClause { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitThenClause, + crate::svelte::auxiliary::await_then_clause::FormatSvelteAwaitThenClause, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::await_then_clause::FormatSvelteAwaitThenClause::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitThenClause { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitThenClause, + crate::svelte::auxiliary::await_then_clause::FormatSvelteAwaitThenClause, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::await_then_clause::FormatSvelteAwaitThenClause::default(), + ) + } +} impl FormatRule for crate::svelte::auxiliary::const_block::FormatSvelteConstBlock { @@ -1510,6 +1776,108 @@ impl IntoFormat for biome_html_syntax::SvelteRenderBlock { ) } } +impl FormatRule + for crate::svelte::auxiliary::snippet_block::FormatSvelteSnippetBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteSnippetBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteSnippetBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteSnippetBlock, + crate::svelte::auxiliary::snippet_block::FormatSvelteSnippetBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::auxiliary::snippet_block::FormatSvelteSnippetBlock::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteSnippetBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteSnippetBlock, + crate::svelte::auxiliary::snippet_block::FormatSvelteSnippetBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::auxiliary::snippet_block::FormatSvelteSnippetBlock::default(), + ) + } +} +impl FormatRule + for crate::svelte::auxiliary::snippet_closing_block::FormatSvelteSnippetClosingBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteSnippetClosingBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteSnippetClosingBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteSnippetClosingBlock, + crate::svelte::auxiliary::snippet_closing_block::FormatSvelteSnippetClosingBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule :: new (self , crate :: svelte :: auxiliary :: snippet_closing_block :: FormatSvelteSnippetClosingBlock :: default ()) + } +} +impl IntoFormat for biome_html_syntax::SvelteSnippetClosingBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteSnippetClosingBlock, + crate::svelte::auxiliary::snippet_closing_block::FormatSvelteSnippetClosingBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule :: new (self , crate :: svelte :: auxiliary :: snippet_closing_block :: FormatSvelteSnippetClosingBlock :: default ()) + } +} +impl FormatRule + for crate::svelte::auxiliary::snippet_opening_block::FormatSvelteSnippetOpeningBlock +{ + type Context = HtmlFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_html_syntax::SvelteSnippetOpeningBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_html_syntax::SvelteSnippetOpeningBlock { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteSnippetOpeningBlock, + crate::svelte::auxiliary::snippet_opening_block::FormatSvelteSnippetOpeningBlock, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule :: new (self , crate :: svelte :: auxiliary :: snippet_opening_block :: FormatSvelteSnippetOpeningBlock :: default ()) + } +} +impl IntoFormat for biome_html_syntax::SvelteSnippetOpeningBlock { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteSnippetOpeningBlock, + crate::svelte::auxiliary::snippet_opening_block::FormatSvelteSnippetOpeningBlock, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule :: new (self , crate :: svelte :: auxiliary :: snippet_opening_block :: FormatSvelteSnippetOpeningBlock :: default ()) + } +} impl FormatRule for crate::vue::auxiliary::directive::FormatVueDirective { @@ -1846,6 +2214,31 @@ impl IntoFormat for biome_html_syntax::HtmlElementList { ) } } +impl AsFormat for biome_html_syntax::SvelteAwaitClausesList { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::SvelteAwaitClausesList, + crate::svelte::lists::await_clauses_list::FormatSvelteAwaitClausesList, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::lists::await_clauses_list::FormatSvelteAwaitClausesList::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::SvelteAwaitClausesList { + type Format = FormatOwnedWithRule< + biome_html_syntax::SvelteAwaitClausesList, + crate::svelte::lists::await_clauses_list::FormatSvelteAwaitClausesList, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::lists::await_clauses_list::FormatSvelteAwaitClausesList::default(), + ) + } +} impl AsFormat for biome_html_syntax::SvelteBindingList { type Format<'a> = FormatRefWithRule< 'a, @@ -2363,6 +2756,31 @@ impl IntoFormat for biome_html_syntax::AnyHtmlTextExpression ) } } +impl AsFormat for biome_html_syntax::AnySvelteAwaitClauses { + type Format<'a> = FormatRefWithRule< + 'a, + biome_html_syntax::AnySvelteAwaitClauses, + crate::svelte::any::await_clauses::FormatAnySvelteAwaitClauses, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::svelte::any::await_clauses::FormatAnySvelteAwaitClauses::default(), + ) + } +} +impl IntoFormat for biome_html_syntax::AnySvelteAwaitClauses { + type Format = FormatOwnedWithRule< + biome_html_syntax::AnySvelteAwaitClauses, + crate::svelte::any::await_clauses::FormatAnySvelteAwaitClauses, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::svelte::any::await_clauses::FormatAnySvelteAwaitClauses::default(), + ) + } +} impl AsFormat for biome_html_syntax::AnySvelteBlock { type Format<'a> = FormatRefWithRule< 'a, diff --git a/crates/biome_html_formatter/src/svelte/any/await_clauses.rs b/crates/biome_html_formatter/src/svelte/any/await_clauses.rs new file mode 100644 index 000000000000..62901de25a4f --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/any/await_clauses.rs @@ -0,0 +1,16 @@ +//! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. + +use crate::prelude::*; +use biome_html_syntax::AnySvelteAwaitClauses; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatAnySvelteAwaitClauses; +impl FormatRule for FormatAnySvelteAwaitClauses { + type Context = HtmlFormatContext; + fn fmt(&self, node: &AnySvelteAwaitClauses, f: &mut HtmlFormatter) -> FormatResult<()> { + match node { + AnySvelteAwaitClauses::SvelteAwaitCatchBlock(node) => node.format().fmt(f), + AnySvelteAwaitClauses::SvelteAwaitThenBlock(node) => node.format().fmt(f), + AnySvelteAwaitClauses::SvelteBogusBlock(node) => node.format().fmt(f), + } + } +} diff --git a/crates/biome_html_formatter/src/svelte/any/block.rs b/crates/biome_html_formatter/src/svelte/any/block.rs index f04e8ac58155..9680ca862e95 100644 --- a/crates/biome_html_formatter/src/svelte/any/block.rs +++ b/crates/biome_html_formatter/src/svelte/any/block.rs @@ -8,6 +8,7 @@ impl FormatRule for FormatAnySvelteBlock { type Context = HtmlFormatContext; fn fmt(&self, node: &AnySvelteBlock, f: &mut HtmlFormatter) -> FormatResult<()> { match node { + AnySvelteBlock::SvelteAwaitBlock(node) => node.format().fmt(f), AnySvelteBlock::SvelteBogusBlock(node) => node.format().fmt(f), AnySvelteBlock::SvelteConstBlock(node) => node.format().fmt(f), AnySvelteBlock::SvelteDebugBlock(node) => node.format().fmt(f), @@ -16,6 +17,7 @@ impl FormatRule for FormatAnySvelteBlock { AnySvelteBlock::SvelteIfBlock(node) => node.format().fmt(f), AnySvelteBlock::SvelteKeyBlock(node) => node.format().fmt(f), AnySvelteBlock::SvelteRenderBlock(node) => node.format().fmt(f), + AnySvelteBlock::SvelteSnippetBlock(node) => node.format().fmt(f), } } } diff --git a/crates/biome_html_formatter/src/svelte/any/mod.rs b/crates/biome_html_formatter/src/svelte/any/mod.rs index 7c9c4f36c31a..01ea508d642d 100644 --- a/crates/biome_html_formatter/src/svelte/any/mod.rs +++ b/crates/biome_html_formatter/src/svelte/any/mod.rs @@ -1,4 +1,5 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. +pub(crate) mod await_clauses; pub(crate) mod block; pub(crate) mod block_item; diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_block.rs new file mode 100644 index 000000000000..05b596c8cc5f --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_block.rs @@ -0,0 +1,23 @@ +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitBlock, SvelteAwaitBlockFields}; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitBlock; +impl FormatNodeRule for FormatSvelteAwaitBlock { + fn fmt_fields(&self, node: &SvelteAwaitBlock, f: &mut HtmlFormatter) -> FormatResult<()> { + let SvelteAwaitBlockFields { + opening_block, + closing_block, + clauses, + } = node.as_fields(); + + write!( + f, + [ + opening_block.format(), + clauses.format(), + closing_block.format(), + ] + ) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_catch_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_catch_block.rs new file mode 100644 index 000000000000..fc526a9a2c26 --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_catch_block.rs @@ -0,0 +1,37 @@ +use crate::html::lists::element_list::FormatHtmlElementList; +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitCatchBlock, SvelteAwaitCatchBlockFields}; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitCatchBlock; +impl FormatNodeRule for FormatSvelteAwaitCatchBlock { + fn fmt_fields(&self, node: &SvelteAwaitCatchBlock, f: &mut HtmlFormatter) -> FormatResult<()> { + let SvelteAwaitCatchBlockFields { + name, + r_curly_token, + children, + catch_token, + sv_curly_colon_token, + } = node.as_fields(); + + write!( + f, + [ + sv_curly_colon_token.format(), + catch_token.format(), + space(), + name.format(), + r_curly_token.format() + ] + )?; + + // The order here is important. First, we must check if we can delegate the formatting + // of embedded nodes, then we check if we should format them verbatim. + let format_children = FormatHtmlElementList::default() + .with_group_id(f.group_id("svelte-catch-group")) + .fmt_children(&children, f)?; + + write!(f, [format_children, hard_line_break()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_catch_clause.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_catch_clause.rs new file mode 100644 index 000000000000..e95323e2d07e --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_catch_clause.rs @@ -0,0 +1,12 @@ +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitCatchClause, SvelteAwaitCatchClauseFields}; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitCatchClause; +impl FormatNodeRule for FormatSvelteAwaitCatchClause { + fn fmt_fields(&self, node: &SvelteAwaitCatchClause, f: &mut HtmlFormatter) -> FormatResult<()> { + let SvelteAwaitCatchClauseFields { name, catch_token } = node.as_fields(); + + write!(f, [catch_token.format(), space(), name.format()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_closing_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_closing_block.rs new file mode 100644 index 000000000000..ff41e1b25b82 --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_closing_block.rs @@ -0,0 +1,27 @@ +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitClosingBlock, SvelteAwaitClosingBlockFields}; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitClosingBlock; +impl FormatNodeRule for FormatSvelteAwaitClosingBlock { + fn fmt_fields( + &self, + node: &SvelteAwaitClosingBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + let SvelteAwaitClosingBlockFields { + r_curly_token, + await_token, + sv_curly_slash_token, + } = node.as_fields(); + + write!( + f, + [ + sv_curly_slash_token.format(), + await_token.format(), + r_curly_token.format() + ] + ) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_opening_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_opening_block.rs new file mode 100644 index 000000000000..31411773bbaa --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_opening_block.rs @@ -0,0 +1,52 @@ +use crate::html::lists::element_list::FormatHtmlElementList; +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitOpeningBlock, SvelteAwaitOpeningBlockFields}; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitOpeningBlock; +impl FormatNodeRule for FormatSvelteAwaitOpeningBlock { + fn fmt_fields( + &self, + node: &SvelteAwaitOpeningBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + let SvelteAwaitOpeningBlockFields { + expression, + r_curly_token, + sv_curly_hash_token, + await_token, + catch_clause, + children, + then_clause, + } = node.as_fields(); + + write!( + f, + [ + sv_curly_hash_token.format(), + await_token.format(), + space(), + expression.format(), + ] + )?; + + if let Some(then_clause) = then_clause { + write!(f, [space(), then_clause.format()])?; + } + + if let Some(catch_clause) = catch_clause { + write!(f, [space(), catch_clause.format()])?; + } + + write!(f, [r_curly_token.format()])?; + + // The order here is important. First, we must check if we can delegate the formatting + // of embedded nodes, then we check if we should format them verbatim. + let format_children = FormatHtmlElementList::default() + .with_group_id(f.group_id("svelte-await-group")) + .fmt_children(&children, f)?; + + write!(f, [format_children, hard_line_break()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_then_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_then_block.rs new file mode 100644 index 000000000000..38cb36558fe9 --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_then_block.rs @@ -0,0 +1,36 @@ +use crate::html::lists::element_list::FormatHtmlElementList; +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitThenBlock, SvelteAwaitThenBlockFields}; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitThenBlock; +impl FormatNodeRule for FormatSvelteAwaitThenBlock { + fn fmt_fields(&self, node: &SvelteAwaitThenBlock, f: &mut HtmlFormatter) -> FormatResult<()> { + let SvelteAwaitThenBlockFields { + name, + sv_curly_colon_token, + r_curly_token, + children, + then_token, + } = node.as_fields(); + + write!( + f, + [ + sv_curly_colon_token.format(), + then_token.format(), + space(), + name.format(), + r_curly_token.format() + ] + )?; + // The order here is important. First, we must check if we can delegate the formatting + // of embedded nodes, then we check if we should format them verbatim. + let format_children = FormatHtmlElementList::default() + .with_group_id(f.group_id("svelte-then-group")) + .fmt_children(&children, f)?; + + write!(f, [format_children, hard_line_break()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/await_then_clause.rs b/crates/biome_html_formatter/src/svelte/auxiliary/await_then_clause.rs new file mode 100644 index 000000000000..43e29ac8d8be --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/await_then_clause.rs @@ -0,0 +1,12 @@ +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteAwaitThenClause, SvelteAwaitThenClauseFields}; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitThenClause; +impl FormatNodeRule for FormatSvelteAwaitThenClause { + fn fmt_fields(&self, node: &SvelteAwaitThenClause, f: &mut HtmlFormatter) -> FormatResult<()> { + let SvelteAwaitThenClauseFields { name, then_token } = node.as_fields(); + + write!(f, [then_token.format(), space(), name.format()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/mod.rs b/crates/biome_html_formatter/src/svelte/auxiliary/mod.rs index 70f5348a158f..9c3374b2be40 100644 --- a/crates/biome_html_formatter/src/svelte/auxiliary/mod.rs +++ b/crates/biome_html_formatter/src/svelte/auxiliary/mod.rs @@ -1,6 +1,13 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. pub(crate) mod attach_attribute; +pub(crate) mod await_block; +pub(crate) mod await_catch_block; +pub(crate) mod await_catch_clause; +pub(crate) mod await_closing_block; +pub(crate) mod await_opening_block; +pub(crate) mod await_then_block; +pub(crate) mod await_then_clause; pub(crate) mod const_block; pub(crate) mod debug_block; pub(crate) mod each_as_keyed_item; @@ -21,3 +28,6 @@ pub(crate) mod key_closing_block; pub(crate) mod key_opening_block; pub(crate) mod name; pub(crate) mod render_block; +pub(crate) mod snippet_block; +pub(crate) mod snippet_closing_block; +pub(crate) mod snippet_opening_block; diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/snippet_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/snippet_block.rs new file mode 100644 index 000000000000..b4907bf7c32e --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/snippet_block.rs @@ -0,0 +1,15 @@ +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteSnippetBlock, SvelteSnippetBlockFields}; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteSnippetBlock; +impl FormatNodeRule for FormatSvelteSnippetBlock { + fn fmt_fields(&self, node: &SvelteSnippetBlock, f: &mut HtmlFormatter) -> FormatResult<()> { + let SvelteSnippetBlockFields { + opening_block, + closing_block, + } = node.as_fields(); + + write!(f, [opening_block.format(), closing_block.format()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/snippet_closing_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/snippet_closing_block.rs new file mode 100644 index 000000000000..9de294700c94 --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/snippet_closing_block.rs @@ -0,0 +1,27 @@ +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteSnippetClosingBlock, SvelteSnippetClosingBlockFields}; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteSnippetClosingBlock; +impl FormatNodeRule for FormatSvelteSnippetClosingBlock { + fn fmt_fields( + &self, + node: &SvelteSnippetClosingBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + let SvelteSnippetClosingBlockFields { + sv_curly_slash_token, + r_curly_token, + snippet_token, + } = node.as_fields(); + + write!( + f, + [ + sv_curly_slash_token.format(), + snippet_token.format(), + r_curly_token.format() + ] + ) + } +} diff --git a/crates/biome_html_formatter/src/svelte/auxiliary/snippet_opening_block.rs b/crates/biome_html_formatter/src/svelte/auxiliary/snippet_opening_block.rs new file mode 100644 index 000000000000..c40b20f5cdd8 --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/auxiliary/snippet_opening_block.rs @@ -0,0 +1,41 @@ +use crate::html::lists::element_list::FormatHtmlElementList; +use crate::prelude::*; +use biome_formatter::write; +use biome_html_syntax::{SvelteSnippetOpeningBlock, SvelteSnippetOpeningBlockFields}; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteSnippetOpeningBlock; +impl FormatNodeRule for FormatSvelteSnippetOpeningBlock { + fn fmt_fields( + &self, + node: &SvelteSnippetOpeningBlock, + f: &mut HtmlFormatter, + ) -> FormatResult<()> { + let SvelteSnippetOpeningBlockFields { + r_curly_token, + sv_curly_hash_token, + children, + snippet_token, + expression, + } = node.as_fields(); + + write!( + f, + [ + sv_curly_hash_token.format(), + snippet_token.format(), + space(), + expression.format(), + r_curly_token.format() + ] + )?; + + // The order here is important. First, we must check if we can delegate the formatting + // of embedded nodes, then we check if we should format them verbatim. + let format_children = FormatHtmlElementList::default() + .with_group_id(f.group_id("svelte-snippet-group")) + .fmt_children(&children, f)?; + + write!(f, [format_children, hard_line_break()]) + } +} diff --git a/crates/biome_html_formatter/src/svelte/lists/await_clauses_list.rs b/crates/biome_html_formatter/src/svelte/lists/await_clauses_list.rs new file mode 100644 index 000000000000..66145ce428ba --- /dev/null +++ b/crates/biome_html_formatter/src/svelte/lists/await_clauses_list.rs @@ -0,0 +1,10 @@ +use crate::prelude::*; +use biome_html_syntax::SvelteAwaitClausesList; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatSvelteAwaitClausesList; +impl FormatRule for FormatSvelteAwaitClausesList { + type Context = HtmlFormatContext; + fn fmt(&self, node: &SvelteAwaitClausesList, f: &mut HtmlFormatter) -> FormatResult<()> { + f.join().entries(node.iter().formatted()).finish() + } +} diff --git a/crates/biome_html_formatter/src/svelte/lists/mod.rs b/crates/biome_html_formatter/src/svelte/lists/mod.rs index 706761390719..bec2c70015a3 100644 --- a/crates/biome_html_formatter/src/svelte/lists/mod.rs +++ b/crates/biome_html_formatter/src/svelte/lists/mod.rs @@ -1,4 +1,5 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. +pub(crate) mod await_clauses_list; pub(crate) mod binding_list; pub(crate) mod else_if_clause_list; diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_array_destructuring.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_array_destructuring.svelte new file mode 100644 index 000000000000..e461efdc2bca --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_array_destructuring.svelte @@ -0,0 +1,4 @@ +{#await promise then [first, second, ...rest]} +

First: {first}, Second: {second}

+

Rest: {rest.join(', ')}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_array_destructuring.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_array_destructuring.svelte.snap new file mode 100644 index 000000000000..78aa2a4b7c1e --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_array_destructuring.svelte.snap @@ -0,0 +1,39 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_array_destructuring.svelte +--- +# Input + +```svelte +{#await promise then [first, second, ...rest]} +

First: {first}, Second: {second}

+

Rest: {rest.join(', ')}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise then [first, second, ...rest]} +

First: {first}, Second: {second}

+

Rest: {rest.join(', ')}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_basic.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_basic.svelte new file mode 100644 index 000000000000..cb53241176fc --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_basic.svelte @@ -0,0 +1,7 @@ +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{:catch error} +

Something went wrong: {error.message}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_basic.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_basic.svelte.snap new file mode 100644 index 000000000000..f541c9f40a7b --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_basic.svelte.snap @@ -0,0 +1,45 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_basic.svelte +--- +# Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{:catch error} +

Something went wrong: {error.message}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{:catch error} +

Something went wrong: {error.message}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_catch_only.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_catch_only.svelte new file mode 100644 index 000000000000..17e7d543a63d --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_catch_only.svelte @@ -0,0 +1,3 @@ +{#await promise catch error} +

Error: {error.message}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_catch_only.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_catch_only.svelte.snap new file mode 100644 index 000000000000..d410ad7864c5 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_catch_only.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_catch_only.svelte +--- +# Input + +```svelte +{#await promise catch error} +

Error: {error.message}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise catch error} +

Error: {error.message}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_complex_expression.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_complex_expression.svelte new file mode 100644 index 000000000000..c3de20f2048b --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_complex_expression.svelte @@ -0,0 +1,10 @@ +{#await fetchUser(userId).then(u => u.profile)} +

Loading user profile...

+{:then profile} +
+

{profile.name}

+

{profile.bio}

+
+{:catch error} +

Failed to load profile: {error.message}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_complex_expression.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_complex_expression.svelte.snap new file mode 100644 index 000000000000..a4cc81c3f10a --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_complex_expression.svelte.snap @@ -0,0 +1,51 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_complex_expression.svelte +--- +# Input + +```svelte +{#await fetchUser(userId).then(u => u.profile)} +

Loading user profile...

+{:then profile} +
+

{profile.name}

+

{profile.bio}

+
+{:catch error} +

Failed to load profile: {error.message}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await fetchUser(userId).then(u => u.profile)} +

Loading user profile...

+{:then profile} +
+

{profile.name}

+

{profile.bio}

+
+{:catch error} +

Failed to load profile: {error.message}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_destructuring.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_destructuring.svelte new file mode 100644 index 000000000000..f97f4c813133 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_destructuring.svelte @@ -0,0 +1,7 @@ +{#await promise then { name, age, address }} +
+

Name: {name}

+

Age: {age}

+

Address: {address}

+
+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_destructuring.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_destructuring.svelte.snap new file mode 100644 index 000000000000..015fd7f76a34 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_destructuring.svelte.snap @@ -0,0 +1,45 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_destructuring.svelte +--- +# Input + +```svelte +{#await promise then { name, age, address }} +
+

Name: {name}

+

Age: {age}

+

Address: {address}

+
+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise then { name, age, address }} +
+

Name: {name}

+

Age: {age}

+

Address: {address}

+
+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_dynamic_import.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_dynamic_import.svelte new file mode 100644 index 000000000000..eaec0f651419 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_dynamic_import.svelte @@ -0,0 +1,3 @@ +{#await import('./Component.svelte') then { default: Component }} + +{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_dynamic_import.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_dynamic_import.svelte.snap new file mode 100644 index 000000000000..b7fdce1d61b3 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_dynamic_import.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_dynamic_import.svelte +--- +# Input + +```svelte +{#await import('./Component.svelte') then { default: Component }} + +{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await import('./Component.svelte') then { default: Component }} + +{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_inline.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_inline.svelte new file mode 100644 index 000000000000..07acea41ca34 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_inline.svelte @@ -0,0 +1 @@ +
{#await promise then value}{value}{/await}
diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_inline.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_inline.svelte.snap new file mode 100644 index 000000000000..aad40bcbbd53 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_inline.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_inline.svelte +--- +# Input + +```svelte +
{#await promise then value}{value}{/await}
+ +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +
+ {#await promise then value} + {value} + {/await} +
+``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_long_expression.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_long_expression.svelte new file mode 100644 index 000000000000..adf6cc790cff --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_long_expression.svelte @@ -0,0 +1,5 @@ +{#await fetch('/api/users/' + userId).then(res => res.json()).then(data => data.profile).catch(err => handleError(err))} +

Loading...

+{:then profile} +
{profile.name}
+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_long_expression.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_long_expression.svelte.snap new file mode 100644 index 000000000000..a9939f30eafd --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_long_expression.svelte.snap @@ -0,0 +1,46 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_long_expression.svelte +--- +# Input + +```svelte +{#await fetch('/api/users/' + userId).then(res => res.json()).then(data => data.profile).catch(err => handleError(err))} +

Loading...

+{:then profile} +
{profile.name}
+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await fetch('/api/users/' + userId).then(res => res.json()).then(data => data.profile).catch(err => handleError(err))} +

Loading...

+{:then profile} +
{profile.name}
+{/await} +``` + +# Lines exceeding max width of 80 characters +``` + 1: {#await fetch('/api/users/' + userId).then(res => res.json()).then(data => data.profile).catch(err => handleError(err))} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_multiline.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiline.svelte new file mode 100644 index 000000000000..cfd25e5b6be4 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiline.svelte @@ -0,0 +1,17 @@ +{#await promise} +
+ +

Please wait while we load your data...

+
+{:then data} +
+

Success!

+
{JSON.stringify(data, null, 2)}
+
+{:catch error} +
+

Error

+

{error.message}

+ +
+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_multiline.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiline.svelte.snap new file mode 100644 index 000000000000..bd66de8c6aa1 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiline.svelte.snap @@ -0,0 +1,71 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_multiline.svelte +--- +# Input + +```svelte +{#await promise} +
+ +

Please wait while we load your data...

+
+{:then data} +
+

Success!

+
{JSON.stringify(data, null, 2)}
+
+{:catch error} +
+

Error

+

{error.message}

+ +
+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise} +
+ +

Please wait while we load your data...

+
+{:then data} +
+

Success!

+
{JSON.stringify(data, null, 2)}
+
+{:catch error} +
+

Error

+

{error.message}

+ +
+{/await} +``` + + + +## Unimplemented nodes/tokens + +"{JSON.stringify(data, null, 2)}" => 191..222 diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_multiple.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiple.svelte new file mode 100644 index 000000000000..1b39e30a4afa --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiple.svelte @@ -0,0 +1,21 @@ +{#await userPromise then user} +

{user.name}

+{/await} + +{#await postsPromise then posts} +
    + {#each posts as post} +
  • {post.title}
  • + {/each} +
+{/await} + +{#await commentsPromise} +

Loading comments...

+{:then comments} +
+ {#each comments as comment} +

{comment.text}

+ {/each} +
+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_multiple.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiple.svelte.snap new file mode 100644 index 000000000000..6cd5a42d92c4 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_multiple.svelte.snap @@ -0,0 +1,73 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_multiple.svelte +--- +# Input + +```svelte +{#await userPromise then user} +

{user.name}

+{/await} + +{#await postsPromise then posts} +
    + {#each posts as post} +
  • {post.title}
  • + {/each} +
+{/await} + +{#await commentsPromise} +

Loading comments...

+{:then comments} +
+ {#each comments as comment} +

{comment.text}

+ {/each} +
+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await userPromise then user} +

{user.name}

+{/await} + +{#await postsPromise then posts} +
    + {#each posts as post} +
  • {post.title}
  • + {/each} +
+{/await} + +{#await commentsPromise} +

Loading comments...

+{:then comments} +
+ {#each comments as comment} +

{comment.text}

+ {/each} +
+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_nested.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_nested.svelte new file mode 100644 index 000000000000..e90e7869cd83 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_nested.svelte @@ -0,0 +1,16 @@ +{#await userPromise} +

Loading user...

+{:then user} +
+

{user.name}

+{#await user.postsPromise then posts} +
    +{#each posts as post} +
  • {post.title}
  • +{/each} +
+{/await} +
+{:catch error} +

Error: {error.message}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_nested.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_nested.svelte.snap new file mode 100644 index 000000000000..5cfb9cf0aa70 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_nested.svelte.snap @@ -0,0 +1,63 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_nested.svelte +--- +# Input + +```svelte +{#await userPromise} +

Loading user...

+{:then user} +
+

{user.name}

+{#await user.postsPromise then posts} +
    +{#each posts as post} +
  • {post.title}
  • +{/each} +
+{/await} +
+{:catch error} +

Error: {error.message}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await userPromise} +

Loading user...

+{:then user} +
+

{user.name}

+ {#await user.postsPromise then posts} +
    + {#each posts as post} +
  • {post.title}
  • + {/each} +
+ {/await} +
+{:catch error} +

Error: {error.message}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_no_catch.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_no_catch.svelte new file mode 100644 index 000000000000..7418370c57d7 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_no_catch.svelte @@ -0,0 +1,5 @@ +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_no_catch.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_no_catch.svelte.snap new file mode 100644 index 000000000000..f66ab54002f5 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_no_catch.svelte.snap @@ -0,0 +1,41 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_no_catch.svelte +--- +# Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_one_liner.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_one_liner.svelte new file mode 100644 index 000000000000..1a9cbb552a9a --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_one_liner.svelte @@ -0,0 +1 @@ +{#await expression}

{:then name}

{:catch name}

{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_one_liner.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_one_liner.svelte.snap new file mode 100644 index 000000000000..7809d6be175a --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_one_liner.svelte.snap @@ -0,0 +1,39 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_one_liner.svelte +--- +# Input + +```svelte +{#await expression}

{:then name}

{:catch name}

{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await expression} +

+{:then name} +

+{:catch name} +

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_shorthand.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_shorthand.svelte new file mode 100644 index 000000000000..212b31c8daba --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_shorthand.svelte @@ -0,0 +1,3 @@ +{#await promise then value} +

The value is {value}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_shorthand.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_shorthand.svelte.snap new file mode 100644 index 000000000000..a02760cf5207 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_shorthand.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_shorthand.svelte +--- +# Input + +```svelte +{#await promise then value} +

The value is {value}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise then value} +

The value is {value}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_with_comments.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_comments.svelte new file mode 100644 index 000000000000..3af6e6005c91 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_comments.svelte @@ -0,0 +1,11 @@ + +{#await promise} + +

Loading...

+{:then value} + +

Value: {value}

+{:catch error} + +

Error: {error.message}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_with_comments.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_comments.svelte.snap new file mode 100644 index 000000000000..6a2765690018 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_comments.svelte.snap @@ -0,0 +1,53 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_with_comments.svelte +--- +# Input + +```svelte + +{#await promise} + +

Loading...

+{:then value} + +

Value: {value}

+{:catch error} + +

Error: {error.message}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte + +{#await promise} + +

Loading...

+{:then value} + +

Value: {value}

+{:catch error} + +

Error: {error.message}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_with_whitespace.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_whitespace.svelte new file mode 100644 index 000000000000..43281047f53a --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_whitespace.svelte @@ -0,0 +1,7 @@ +{#await promise } +

Loading...

+{:then value } +

The value is {value}

+{:catch error } +

Error: {error.message}

+{/await} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/await_with_whitespace.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_whitespace.svelte.snap new file mode 100644 index 000000000000..092dad326f6e --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/await_with_whitespace.svelte.snap @@ -0,0 +1,45 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/await_with_whitespace.svelte +--- +# Input + +```svelte +{#await promise } +

Loading...

+{:then value } +

The value is {value}

+{:catch error } +

Error: {error.message}

+{/await} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{:catch error} +

Error: {error.message}

+{/await} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/each_one_liner.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/each_one_liner.svelte new file mode 100644 index 000000000000..1c32a80e8f77 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/each_one_liner.svelte @@ -0,0 +1 @@ +{#each items as item, i (item.id)}
{i}: {item.name}
{:else}
Empty list
{/each} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/each_one_liner.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/each_one_liner.svelte.snap new file mode 100644 index 000000000000..75ec2660afdf --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/each_one_liner.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/each_one_liner.svelte +--- +# Input + +```svelte +{#each items as item, i (item.id)}
{i}: {item.name}
{:else}
Empty list
{/each} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#each items as item, i (item.id)} +
{i}: {item.name}
+{:else} +
Empty list
+{/each} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/snippet_basic.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_basic.svelte new file mode 100644 index 000000000000..587fadcea5e7 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_basic.svelte @@ -0,0 +1,3 @@ +{#snippet greeting()} +

Hello!

+{/snippet} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/snippet_basic.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_basic.svelte.snap new file mode 100644 index 000000000000..ad2da63617b6 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_basic.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/snippet_basic.svelte +--- +# Input + +```svelte +{#snippet greeting()} +

Hello!

+{/snippet} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#snippet greeting()} +

Hello!

+{/snippet} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/snippet_nested.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_nested.svelte new file mode 100644 index 000000000000..c10091980e67 --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_nested.svelte @@ -0,0 +1,7 @@ +{#snippet outer()} +
+{#snippet inner()} +

Inner content

+{/snippet} +
+{/snippet} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/snippet_nested.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_nested.svelte.snap new file mode 100644 index 000000000000..622bfaa5af7f --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_nested.svelte.snap @@ -0,0 +1,45 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/snippet_nested.svelte +--- +# Input + +```svelte +{#snippet outer()} +
+{#snippet inner()} +

Inner content

+{/snippet} +
+{/snippet} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#snippet outer()} +
+ {#snippet inner()} +

Inner content

+ {/snippet} +
+{/snippet} +``` diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/snippet_with_whitespace.svelte b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_with_whitespace.svelte new file mode 100644 index 000000000000..6cc28cec3dbe --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_with_whitespace.svelte @@ -0,0 +1,3 @@ +{#snippet greeting( name ) } +

Hello, {name}!

+{/snippet} diff --git a/crates/biome_html_formatter/tests/specs/html/svelte/snippet_with_whitespace.svelte.snap b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_with_whitespace.svelte.snap new file mode 100644 index 000000000000..695b4610879c --- /dev/null +++ b/crates/biome_html_formatter/tests/specs/html/svelte/snippet_with_whitespace.svelte.snap @@ -0,0 +1,37 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: svelte/snippet_with_whitespace.svelte +--- +# Input + +```svelte +{#snippet greeting( name ) } +

Hello, {name}!

+{/snippet} + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Attribute Position: Auto +Bracket same line: false +Whitespace sensitivity: css +Indent script and style: false +Self close void elements: never +----- + +```svelte +{#snippet greeting( name )} +

Hello, {name}!

+{/snippet} +``` diff --git a/crates/biome_html_parser/src/lexer/mod.rs b/crates/biome_html_parser/src/lexer/mod.rs index f05401c65b66..fb77546c0cb2 100644 --- a/crates/biome_html_parser/src/lexer/mod.rs +++ b/crates/biome_html_parser/src/lexer/mod.rs @@ -5,9 +5,9 @@ use crate::token_source::{ TextExpressionKind, }; use biome_html_syntax::HtmlSyntaxKind::{ - AS_KW, ATTACH_KW, COMMENT, CONST_KW, DEBUG_KW, DOCTYPE_KW, EACH_KW, ELSE_KW, EOF, ERROR_TOKEN, - HTML_KW, HTML_LITERAL, HTML_STRING_LITERAL, IDENT, IF_KW, KEY_KW, NEWLINE, RENDER_KW, - TOMBSTONE, UNICODE_BOM, WHITESPACE, + AS_KW, ATTACH_KW, AWAIT_KW, CATCH_KW, COMMENT, CONST_KW, DEBUG_KW, DOCTYPE_KW, EACH_KW, + ELSE_KW, EOF, ERROR_TOKEN, HTML_KW, HTML_LITERAL, HTML_STRING_LITERAL, IDENT, IF_KW, KEY_KW, + NEWLINE, RENDER_KW, SNIPPET_KW, THEN_KW, TOMBSTONE, UNICODE_BOM, WHITESPACE, }; use biome_html_syntax::{HtmlSyntaxKind, T, TextLen, TextSize}; use biome_parser::diagnostic::ParseDiagnostic; @@ -345,7 +345,6 @@ impl<'src> HtmlLexer<'src> { ) -> HtmlSyntaxKind { let start_pos = self.position; let mut brackets_stack = 0; - while let Some(current) = self.current_byte() { match current { b'}' => { @@ -368,6 +367,7 @@ impl<'src> HtmlLexer<'src> { current == b'(' || current == b',' } RestrictedExpressionStopAt::ClosingParen => current == b')', + RestrictedExpressionStopAt::ThenOrCatch => false, }; if should_stop { break; @@ -377,10 +377,17 @@ impl<'src> HtmlLexer<'src> { _ if brackets_stack == 0 && is_at_start_identifier(current) => { // Check if we're at a stop keyword let checkpoint_pos = self.position; + let prev_byte = self.prev_byte(); if let Some(keyword_kind) = self.consume_language_identifier(current) { // Check if this keyword is in our stop list let should_stop = match kind { - RestrictedExpressionStopAt::AsOrComma => keyword_kind == AS_KW, + RestrictedExpressionStopAt::AsOrComma => { + keyword_kind == AS_KW && prev_byte == Some(b' ') + } + RestrictedExpressionStopAt::ThenOrCatch => { + (keyword_kind == THEN_KW || keyword_kind == CATCH_KW) + && prev_byte == Some(b' ') + } RestrictedExpressionStopAt::OpeningParenOrComma => false, RestrictedExpressionStopAt::ClosingParen => false, }; @@ -559,6 +566,10 @@ impl<'src> HtmlLexer<'src> { b"else" => ELSE_KW, b"each" => EACH_KW, b"as" => AS_KW, + b"await" => AWAIT_KW, + b"then" => THEN_KW, + b"catch" => CATCH_KW, + b"snippet" => SNIPPET_KW, _ => { self.position = starting_position; return None; diff --git a/crates/biome_html_parser/src/syntax/parse_error.rs b/crates/biome_html_parser/src/syntax/parse_error.rs index 8cf510f855b7..3703689afa20 100644 --- a/crates/biome_html_parser/src/syntax/parse_error.rs +++ b/crates/biome_html_parser/src/syntax/parse_error.rs @@ -112,3 +112,8 @@ pub(crate) fn disabled_vue(p: &HtmlParser, range: TextRange) -> ParseDiagnostic pub(crate) fn expected_vue_directive_argument(p: &HtmlParser, range: TextRange) -> ParseDiagnostic { expected_node("vue directive argument", range, p).into_diagnostic(p) } + +pub(crate) fn expected_expression(p: &HtmlParser, range: TextRange) -> ParseDiagnostic { + p.err_builder("Expected an expression, instead none was found.", range) + .into_diagnostic(p) +} diff --git a/crates/biome_html_parser/src/syntax/svelte.rs b/crates/biome_html_parser/src/syntax/svelte.rs index e08fe5ad9298..2f10ecaf631f 100644 --- a/crates/biome_html_parser/src/syntax/svelte.rs +++ b/crates/biome_html_parser/src/syntax/svelte.rs @@ -1,17 +1,22 @@ use crate::parser::HtmlParser; use crate::syntax::parse_error::{ - expected_child_or_block, expected_svelte_closing_block, expected_text_expression, + expected_child_or_block, expected_expression, expected_svelte_closing_block, + expected_text_expression, }; use crate::syntax::{parse_html_element, parse_single_text_expression_content}; use crate::token_source::{HtmlLexContext, HtmlReLexContext, RestrictedExpressionStopAt}; use biome_html_syntax::HtmlSyntaxKind::{ - EOF, HTML_BOGUS_ELEMENT, HTML_ELEMENT_LIST, IDENT, SVELTE_ATTACH_ATTRIBUTE, - SVELTE_BINDING_LIST, SVELTE_BOGUS_BLOCK, SVELTE_CONST_BLOCK, SVELTE_DEBUG_BLOCK, - SVELTE_EACH_AS_KEYED_ITEM, SVELTE_EACH_BLOCK, SVELTE_EACH_CLOSING_BLOCK, SVELTE_EACH_INDEX, - SVELTE_EACH_KEY, SVELTE_EACH_KEYED_ITEM, SVELTE_EACH_OPENING_BLOCK, SVELTE_ELSE_CLAUSE, - SVELTE_ELSE_IF_CLAUSE, SVELTE_ELSE_IF_CLAUSE_LIST, SVELTE_HTML_BLOCK, SVELTE_IF_BLOCK, - SVELTE_IF_CLOSING_BLOCK, SVELTE_IF_OPENING_BLOCK, SVELTE_KEY_BLOCK, SVELTE_KEY_CLOSING_BLOCK, - SVELTE_KEY_OPENING_BLOCK, SVELTE_NAME, SVELTE_RENDER_BLOCK, + EOF, HTML_BOGUS_ELEMENT, HTML_ELEMENT_LIST, HTML_LITERAL, IDENT, SVELTE_ATTACH_ATTRIBUTE, + SVELTE_AWAIT_BLOCK, SVELTE_AWAIT_CATCH_BLOCK, SVELTE_AWAIT_CATCH_CLAUSE, + SVELTE_AWAIT_CLAUSES_LIST, SVELTE_AWAIT_CLOSING_BLOCK, SVELTE_AWAIT_OPENING_BLOCK, + SVELTE_AWAIT_THEN_BLOCK, SVELTE_AWAIT_THEN_CLAUSE, SVELTE_BINDING_LIST, SVELTE_BOGUS_BLOCK, + SVELTE_CONST_BLOCK, SVELTE_DEBUG_BLOCK, SVELTE_EACH_AS_KEYED_ITEM, SVELTE_EACH_BLOCK, + SVELTE_EACH_CLOSING_BLOCK, SVELTE_EACH_INDEX, SVELTE_EACH_KEY, SVELTE_EACH_KEYED_ITEM, + SVELTE_EACH_OPENING_BLOCK, SVELTE_ELSE_CLAUSE, SVELTE_ELSE_IF_CLAUSE, + SVELTE_ELSE_IF_CLAUSE_LIST, SVELTE_HTML_BLOCK, SVELTE_IF_BLOCK, SVELTE_IF_CLOSING_BLOCK, + SVELTE_IF_OPENING_BLOCK, SVELTE_KEY_BLOCK, SVELTE_KEY_CLOSING_BLOCK, SVELTE_KEY_OPENING_BLOCK, + SVELTE_NAME, SVELTE_RENDER_BLOCK, SVELTE_SNIPPET_BLOCK, SVELTE_SNIPPET_CLOSING_BLOCK, + SVELTE_SNIPPET_OPENING_BLOCK, }; use biome_html_syntax::{HtmlSyntaxKind, T}; use biome_parser::parse_lists::{ParseNodeList, ParseSeparatedList}; @@ -19,6 +24,7 @@ use biome_parser::parse_recovery::{ParseRecoveryTokenSet, RecoveryResult}; use biome_parser::prelude::ParsedSyntax; use biome_parser::prelude::ParsedSyntax::{Absent, Present}; use biome_parser::{Marker, Parser, TokenSet, token_set}; +use biome_rowan::TextRange; use std::ops::Sub; pub(crate) fn parse_svelte_hash_block(p: &mut HtmlParser) -> ParsedSyntax { @@ -31,13 +37,13 @@ pub(crate) fn parse_svelte_hash_block(p: &mut HtmlParser) -> ParsedSyntax { T![key] => parse_key_block(p, m), T![if] => parse_if_block(p, m), T![each] => parse_each_block(p, m), + T![await] => parse_await_block(p, m), + T![snippet] => parse_snippet_block(p, m), _ => { m.abandon(p); Absent } } - // NOTE: use or_else chain here to parse - // other possible hash blocks } pub(crate) fn parse_key_block(p: &mut HtmlParser, parent_marker: Marker) -> ParsedSyntax { @@ -87,10 +93,7 @@ fn parse_if_opening_block(p: &mut HtmlParser, parent_marker: Marker) -> ParsedSy p.bump_with_context(T![if], HtmlLexContext::single_expression()); parse_single_text_expression_content(p).or_add_diagnostic(p, |p, range| { - p.err_builder( - "Expected an expression, instead none was found.", - range.sub_start(parent_marker.start()), - ) + expected_expression(p, range.sub_start(parent_marker.start())) }); p.expect(T!['}']); @@ -123,10 +126,7 @@ pub(crate) fn parse_else_if_clause(p: &mut HtmlParser) -> ParsedSyntax { p.expect_with_context(T![if], HtmlLexContext::single_expression()); parse_single_text_expression_content(p).or_add_diagnostic(p, |p, range| { - p.err_builder( - "Expected an expression, instead none was found.", - range.sub_start(m.start()), - ) + expected_expression(p, range.sub_start(m.start())) }); p.expect(T!['}']); @@ -166,7 +166,7 @@ fn parse_each_block(p: &mut HtmlParser, parent_marker: Marker) -> ParsedSyntax { .parse_list(p); // Parse optional {:else} clause - if at_else_opening_block(p) { + if is_at_else_opening_block(p) { parse_else_clause(p).ok(); } @@ -312,6 +312,14 @@ fn parse_each_opening_block(p: &mut HtmlParser, parent_marker: Marker) -> (Parse ) }); + if p.at(T!['}']) { + has_errors |= true; + p.error(p.err_builder( + "Expected 'as' keyword for item binding or ',' for index-only syntax", + p.cur_range(), + )); + } + // In case there's nothing parsed, it's possible we have whitespaces or noice. // We consume any possible token, so we can recover and resume normal parsing. if result.is_none() { @@ -324,7 +332,9 @@ fn parse_each_opening_block(p: &mut HtmlParser, parent_marker: Marker) -> (Parse p.re_lex(HtmlReLexContext::Svelte); // Parse the optional item binding (either 'as item...' or ', index') - parse_svelte_block_item(p).ok(); + if p.at(T![as]) || p.at(T![,]) { + parse_svelte_block_item(p).ok(); + } p.expect(T!['}']); @@ -334,6 +344,366 @@ fn parse_each_opening_block(p: &mut HtmlParser, parent_marker: Marker) -> (Parse ) } +// #region await parse functions + +fn parse_await_block(p: &mut HtmlParser, parent_marker: Marker) -> ParsedSyntax { + if !p.at(T![await]) { + parent_marker.abandon(p); + return Absent; + } + let ParseAwaitResult { + result, + has_then_clause, + has_catch_clause, + } = parse_await_opening_block(p, parent_marker); + let m = result.precede(p); + + AwaitClausesList { + has_then_clause, + has_catch_clause, + seen_then_block: None, + seen_catch_block: None, + } + .parse_list(p); + + parse_closing_block(p, T![await], SVELTE_AWAIT_CLOSING_BLOCK).or_add_diagnostic( + p, + |p, range| { + expected_svelte_closing_block(p, range) + .with_detail(range.sub(m.start()), "This is where the block started.") + }, + ); + + Present(m.complete(p, SVELTE_AWAIT_BLOCK)) +} + +struct ParseAwaitResult { + result: ParsedSyntax, + /// Used to signal possible parse errors in case there's a then block + has_then_clause: Option, + /// Used to signal possible parse errors in case there's a catch block + has_catch_clause: Option, +} + +/// Parses a `{#await expression}` block. +fn parse_await_opening_block(p: &mut HtmlParser, parent_marker: Marker) -> ParseAwaitResult { + if !p.at(T![await]) { + parent_marker.abandon(p); + return ParseAwaitResult { + result: Absent, + has_then_clause: None, + has_catch_clause: None, + }; + } + let mut has_then_clause = None; + let mut has_catch_clause = None; + + p.bump_with_context( + T![await], + HtmlLexContext::restricted_expression(RestrictedExpressionStopAt::ThenOrCatch), + ); + + parse_single_text_expression_content(p).or_add_diagnostic(p, |p, range| { + expected_expression(p, range.sub_start(parent_marker.start())) + }); + + if p.cur_text().is_empty() { + p.bump_remap(HTML_LITERAL); + p.error(p.err_builder("Expected an expression after 'await'", p.cur_range())); + } + + if p.at(T![then]) + && let Present(m) = parse_await_then_clause(p) + { + has_then_clause = Some(m.range(p)); + } + if p.at(T![catch]) + && let Present(m) = parse_await_catch_clause(p) + { + has_catch_clause = Some(m.range(p)); + } + + p.expect(T!['}']); + + SvelteElementList::new() + .with_stop_at_curly_colon() + .parse_list(p); + + ParseAwaitResult { + result: Present(parent_marker.complete(p, SVELTE_AWAIT_OPENING_BLOCK)), + has_catch_clause, + has_then_clause, + } +} + +fn parse_await_then_clause(p: &mut HtmlParser) -> ParsedSyntax { + if !p.at(T![then]) { + return Absent; + } + let m = p.start(); + p.bump_with_context(T![then], HtmlLexContext::single_expression()); + + parse_single_text_expression_content(p) + .or_add_diagnostic(p, |p, range| expected_expression(p, range)); + + if p.cur_text().is_empty() { + p.bump_remap(HTML_LITERAL); + } + + Present(m.complete(p, SVELTE_AWAIT_THEN_CLAUSE)) +} + +fn parse_await_catch_clause(p: &mut HtmlParser) -> ParsedSyntax { + if !p.at(T![catch]) { + return Absent; + } + let m = p.start(); + p.bump_with_context(T![catch], HtmlLexContext::single_expression()); + + parse_single_text_expression_content(p) + .or_add_diagnostic(p, |p, range| expected_expression(p, range)); + if p.cur_text().is_empty() { + p.bump_remap(HTML_LITERAL); + } + Present(m.complete(p, SVELTE_AWAIT_CATCH_CLAUSE)) +} + +struct AwaitClausesList { + has_then_clause: Option, + has_catch_clause: Option, + seen_catch_block: Option, + seen_then_block: Option, +} + +impl ParseNodeList for AwaitClausesList { + type Kind = HtmlSyntaxKind; + type Parser<'source> = HtmlParser<'source>; + const LIST_KIND: Self::Kind = SVELTE_AWAIT_CLAUSES_LIST; + + fn parse_element(&mut self, p: &mut Self::Parser<'_>) -> ParsedSyntax { + let (result, block_parsed) = + parse_await_then_or_catch_block(p, self.has_then_clause, self.has_catch_clause); + + result + .and_then(|parsed| { + let range = parsed.range(p); + + if self.seen_then_block.is_none() && block_parsed == BlockParsed::Catch { + p.error( + p.err_builder("{:catch} cannot appear before the {:then} block.", range) + .with_detail(p.cur_range(), "This is where the {:then} block starts."), + ) + } + + if let Some(seen_catch_block) = self.seen_catch_block + && block_parsed == BlockParsed::Catch + { + p.error( + p.err_builder( + "{:catch} cannot appear more than once within a block.", + p.cur_range(), + ) + .with_detail(seen_catch_block, "This is where the block started."), + ) + } else if let Some(seen_then_block) = self.seen_then_block + && block_parsed == BlockParsed::Then + { + p.error( + p.err_builder( + "{:then} cannot appear more than once within a block.", + p.cur_range(), + ) + .with_detail(seen_then_block, "This is where the block started."), + ) + } + + if block_parsed == BlockParsed::Catch { + self.seen_catch_block = Some(range); + } else if block_parsed == BlockParsed::Then { + self.seen_then_block = Some(range); + } + + Present(parsed) + }) + .or_else(|| Absent) + } + + fn is_at_list_end(&self, p: &mut Self::Parser<'_>) -> bool { + !is_at_then_or_catch_block(p) + } + + fn recover( + &mut self, + p: &mut Self::Parser<'_>, + parsed_element: ParsedSyntax, + ) -> RecoveryResult { + parsed_element.or_recover_with_token_set( + p, + &ParseRecoveryTokenSet::new(SVELTE_BOGUS_BLOCK, BLOCK_RECOVER), + expected_svelte_closing_block, + ) + } +} + +#[derive(Default, Eq, PartialEq)] +enum BlockParsed { + #[default] + None, + Catch, + Then, +} + +fn parse_await_then_or_catch_block( + p: &mut HtmlParser, + seen_then_clause: Option, + seen_catch_clause: Option, +) -> (ParsedSyntax, BlockParsed) { + if !is_at_then_or_catch_block(p) { + return (Absent, BlockParsed::None); + } + let m = p.start(); + p.bump(T!["{:"]); + + if p.at(T![then]) { + ( + parse_await_then_block(p, m, seen_then_clause), + BlockParsed::Then, + ) + } else if p.at(T![catch]) { + ( + parse_await_catch_block(p, m, seen_catch_clause), + BlockParsed::Catch, + ) + } else { + m.abandon(p); + (Absent, BlockParsed::None) + } +} + +fn parse_await_then_block( + p: &mut HtmlParser, + m: Marker, + has_then_clause: Option, +) -> ParsedSyntax { + if !p.at(T![then]) { + m.abandon(p); + return Absent; + } + p.bump_with_context(T![then], HtmlLexContext::single_expression()); + + parse_single_text_expression_content(p) + .or_add_diagnostic(p, |p, range| expected_expression(p, range)); + + if p.cur_text().is_empty() { + p.bump_remap(HTML_LITERAL); + p.error(p.err_builder("Expected an expression after 'then'", p.cur_range())); + } + + p.expect(T!['}']); + + SvelteElementList::new() + .with_stop_at_curly_colon() + .parse_list(p); + + if let Some(range) = has_then_clause { + p.error( + p.err_builder( + "{:then} cannot appear more than once within a block.", + p.cur_range(), + ) + .with_detail(range, "This is where the block started."), + ) + } + + Present(m.complete(p, SVELTE_AWAIT_THEN_BLOCK)) +} + +fn parse_await_catch_block( + p: &mut HtmlParser, + m: Marker, + has_catch_clause: Option, +) -> ParsedSyntax { + if !p.at(T![catch]) { + m.abandon(p); + return Absent; + } + p.bump_with_context(T![catch], HtmlLexContext::single_expression()); + + parse_single_text_expression_content(p) + .or_add_diagnostic(p, |p, range| expected_expression(p, range)); + + if p.cur_text().is_empty() { + p.bump_remap(HTML_LITERAL); + p.error(p.err_builder("Expected an expression after 'catch'", p.cur_range())); + } + + p.expect(T!['}']); + + SvelteElementList::new() + .with_stop_at_curly_colon() + .parse_list(p); + + if let Some(range) = has_catch_clause { + p.error( + p.err_builder( + "{:catch} cannot appear more than once within a block.", + p.cur_range(), + ) + .with_detail(range, "This is where the block started."), + ); + } + + Present(m.complete(p, SVELTE_AWAIT_CATCH_BLOCK)) +} + +// #endregion + +// #region snippet parsing functions +fn parse_snippet_block(p: &mut HtmlParser, parent_marker: Marker) -> ParsedSyntax { + if !p.at(T![snippet]) { + parent_marker.abandon(p); + return Absent; + } + let result = parse_snippet_opening_block(p, parent_marker); + let m = result.precede(p); + + parse_closing_block(p, T![snippet], SVELTE_SNIPPET_CLOSING_BLOCK).or_add_diagnostic( + p, + |p, range| { + expected_svelte_closing_block(p, range) + .with_detail(range.sub(m.start()), "This is where the block started.") + }, + ); + + Present(m.complete(p, SVELTE_SNIPPET_BLOCK)) +} + +fn parse_snippet_opening_block(p: &mut HtmlParser, parent_marker: Marker) -> ParsedSyntax { + if !p.at(T![snippet]) { + parent_marker.abandon(p); + return Absent; + } + p.bump_with_context(T![snippet], HtmlLexContext::single_expression()); + + parse_single_text_expression_content(p).or_add_diagnostic(p, |p, range| { + expected_expression(p, range.sub_start(parent_marker.start())) + }); + + if p.cur_text().is_empty() { + p.bump_remap(HTML_LITERAL); + p.error(p.err_builder("Expected an expression after 'snippet'", p.cur_range())); + } + + p.expect(T!['}']); + + SvelteElementList::new() + .with_stop_at_curly_colon() + .parse_list(p); + + Present(parent_marker.complete(p, SVELTE_SNIPPET_OPENING_BLOCK)) +} + +// #endregion /// Parses a `{# expression }` block. /// /// `node` is the name of the node to emit @@ -350,10 +720,7 @@ pub(crate) fn parse_opening_block( p.bump_with_context(keyword, HtmlLexContext::single_expression()); parse_single_text_expression_content(p).or_add_diagnostic(p, |p, range| { - p.err_builder( - "Expected an expression, instead none was found.", - range.sub_start(m.start()), - ) + expected_expression(p, range.sub_start(m.start())) }); p.expect(T!['}']); @@ -618,9 +985,17 @@ pub(crate) fn is_at_svelte_keyword(p: &HtmlParser) -> bool { | T![render] | T![key] | T![as] + | T![await] + | T![catch] + | T![then] + | T![snippet] ) } -fn at_else_opening_block(p: &mut HtmlParser) -> bool { +fn is_at_else_opening_block(p: &mut HtmlParser) -> bool { p.at(T!["{:"]) && p.nth_at(1, T![else]) } + +fn is_at_then_or_catch_block(p: &mut HtmlParser) -> bool { + p.at(T!["{:"]) && (p.nth_at(1, T![then]) || p.nth_at(1, T![catch])) +} diff --git a/crates/biome_html_parser/src/token_source.rs b/crates/biome_html_parser/src/token_source.rs index ac3bb8c5ae99..4e1ecad298a7 100644 --- a/crates/biome_html_parser/src/token_source.rs +++ b/crates/biome_html_parser/src/token_source.rs @@ -90,6 +90,8 @@ pub(crate) enum RestrictedExpressionStopAt { OpeningParenOrComma, /// Stops at `)` ClosingParen, + /// Stops at `then` or `catch` keywords + ThenOrCatch, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte new file mode 100644 index 000000000000..a9e10ffa89e3 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte @@ -0,0 +1,7 @@ +{#await promise} +

Loading...

+{:catch error} +

{error.message}

+{:then value} +

{value}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte.snap new file mode 100644 index 000000000000..db44051a89ca --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte.snap @@ -0,0 +1,270 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:catch error} +

{error.message}

+{:then value} +

{value}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@39..44 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@44..50 " error" [] [], + }, + r_curly_token: R_CURLY@50..51 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@51..55 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@55..56 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@56..57 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@57..58 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@58..71 "error.message" [] [], + }, + r_curly_token: R_CURLY@71..72 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@72..73 "<" [] [], + slash_token: SLASH@73..74 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@74..75 "p" [] [], + }, + r_angle_token: R_ANGLE@75..76 ">" [] [], + }, + }, + ], + }, + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@76..79 "{:" [Newline("\n")] [], + then_token: THEN_KW@79..83 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@83..89 " value" [] [], + }, + r_curly_token: R_CURLY@89..90 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@90..94 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@94..95 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@95..96 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@96..97 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@97..102 "value" [] [], + }, + r_curly_token: R_CURLY@102..103 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@103..104 "<" [] [], + slash_token: SLASH@104..105 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@105..106 "p" [] [], + }, + r_angle_token: R_ANGLE@106..107 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@107..110 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@110..115 "await" [] [], + r_curly_token: R_CURLY@115..116 "}" [] [], + }, + }, + ], + eof_token: EOF@116..117 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..117 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..116 + 0: SVELTE_AWAIT_BLOCK@0..116 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..107 + 0: SVELTE_AWAIT_CATCH_BLOCK@36..76 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: CATCH_KW@39..44 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@44..50 + 0: HTML_LITERAL@44..50 " error" [] [] + 3: R_CURLY@50..51 "}" [] [] + 4: HTML_ELEMENT_LIST@51..76 + 0: HTML_ELEMENT@51..76 + 0: HTML_OPENING_ELEMENT@51..57 + 0: L_ANGLE@51..55 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@55..56 + 0: HTML_LITERAL@55..56 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@56..56 + 3: R_ANGLE@56..57 ">" [] [] + 1: HTML_ELEMENT_LIST@57..72 + 0: HTML_SINGLE_TEXT_EXPRESSION@57..72 + 0: L_CURLY@57..58 "{" [] [] + 1: HTML_TEXT_EXPRESSION@58..71 + 0: HTML_LITERAL@58..71 "error.message" [] [] + 2: R_CURLY@71..72 "}" [] [] + 2: HTML_CLOSING_ELEMENT@72..76 + 0: L_ANGLE@72..73 "<" [] [] + 1: SLASH@73..74 "/" [] [] + 2: HTML_TAG_NAME@74..75 + 0: HTML_LITERAL@74..75 "p" [] [] + 3: R_ANGLE@75..76 ">" [] [] + 1: SVELTE_AWAIT_THEN_BLOCK@76..107 + 0: SV_CURLY_COLON@76..79 "{:" [Newline("\n")] [] + 1: THEN_KW@79..83 "then" [] [] + 2: HTML_TEXT_EXPRESSION@83..89 + 0: HTML_LITERAL@83..89 " value" [] [] + 3: R_CURLY@89..90 "}" [] [] + 4: HTML_ELEMENT_LIST@90..107 + 0: HTML_ELEMENT@90..107 + 0: HTML_OPENING_ELEMENT@90..96 + 0: L_ANGLE@90..94 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@94..95 + 0: HTML_LITERAL@94..95 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@95..95 + 3: R_ANGLE@95..96 ">" [] [] + 1: HTML_ELEMENT_LIST@96..103 + 0: HTML_SINGLE_TEXT_EXPRESSION@96..103 + 0: L_CURLY@96..97 "{" [] [] + 1: HTML_TEXT_EXPRESSION@97..102 + 0: HTML_LITERAL@97..102 "value" [] [] + 2: R_CURLY@102..103 "}" [] [] + 2: HTML_CLOSING_ELEMENT@103..107 + 0: L_ANGLE@103..104 "<" [] [] + 1: SLASH@104..105 "/" [] [] + 2: HTML_TAG_NAME@105..106 + 0: HTML_LITERAL@105..106 "p" [] [] + 3: R_ANGLE@106..107 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@107..116 + 0: SV_CURLY_SLASH@107..110 "{/" [Newline("\n")] [] + 1: AWAIT_KW@110..115 "await" [] [] + 2: R_CURLY@115..116 "}" [] [] + 4: EOF@116..117 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_catch_before_then.svelte:3:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × {:catch} cannot appear before the {:then} block. + + 1 │ {#await promise} + 2 │

Loading...

+ > 3 │ {:catch error} + │ ^^^^^^^^^^^^^^ + > 4 │

{error.message}

+ │ ^^^^^^^^^^^^^^^^^^^^^^ + 5 │ {:then value} + 6 │

{value}

+ + i This is where the {:then} block starts. + + 3 │ {:catch error} + 4 │

{error.message}

+ > 5 │ {:then value} + │ ^^ + 6 │

{value}

+ 7 │ {/await} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte new file mode 100644 index 000000000000..674ff0a1c8e3 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte @@ -0,0 +1,3 @@ +{#await promise catch} +

Error!

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte.snap new file mode 100644 index 000000000000..7a2c3152e82a --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte.snap @@ -0,0 +1,135 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise catch} +

Error!

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + HtmlBogusElement { + items: [ + HtmlBogus { + items: [ + SV_CURLY_HASH@0..2 "{#" [] [], + AWAIT_KW@2..7 "await" [] [], + HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + HtmlBogus { + items: [ + CATCH_KW@16..21 "catch" [] [], + HTML_LITERAL@21..21 "" [] [], + ], + }, + R_CURLY@21..22 "}" [] [], + HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@22..26 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@26..27 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@27..28 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@28..34 "Error!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@34..35 "<" [] [], + slash_token: SLASH@35..36 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@36..37 "p" [] [], + }, + r_angle_token: R_ANGLE@37..38 ">" [] [], + }, + }, + ], + ], + }, + SvelteAwaitClausesList [], + SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@38..41 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@41..46 "await" [] [], + r_curly_token: R_CURLY@46..47 "}" [] [], + }, + ], + }, + ], + eof_token: EOF@47..48 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..48 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..47 + 0: HTML_BOGUS_ELEMENT@0..47 + 0: HTML_BOGUS@0..38 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: HTML_BOGUS@16..21 + 0: CATCH_KW@16..21 "catch" [] [] + 1: HTML_LITERAL@21..21 "" [] [] + 4: R_CURLY@21..22 "}" [] [] + 5: HTML_ELEMENT_LIST@22..38 + 0: HTML_ELEMENT@22..38 + 0: HTML_OPENING_ELEMENT@22..28 + 0: L_ANGLE@22..26 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@26..27 + 0: HTML_LITERAL@26..27 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@27..27 + 3: R_ANGLE@27..28 ">" [] [] + 1: HTML_ELEMENT_LIST@28..34 + 0: HTML_CONTENT@28..34 + 0: HTML_LITERAL@28..34 "Error!" [] [] + 2: HTML_CLOSING_ELEMENT@34..38 + 0: L_ANGLE@34..35 "<" [] [] + 1: SLASH@35..36 "/" [] [] + 2: HTML_TAG_NAME@36..37 + 0: HTML_LITERAL@36..37 "p" [] [] + 3: R_ANGLE@37..38 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@38..38 + 2: SVELTE_AWAIT_CLOSING_BLOCK@38..47 + 0: SV_CURLY_SLASH@38..41 "{/" [Newline("\n")] [] + 1: AWAIT_KW@41..46 "await" [] [] + 2: R_CURLY@46..47 "}" [] [] + 4: EOF@47..48 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_catch_only_missing_binding.svelte:1:22 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an expression, instead none was found. + + > 1 │ {#await promise catch} + │ + 2 │

Error!

+ 3 │ {/await} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte new file mode 100644 index 000000000000..0fc702c24361 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte @@ -0,0 +1,9 @@ +{#await promise} +

Loading...

+{:then value} +

{value}

+{:catch error} +

{error.message}

+{:catch anotherError} +

{anotherError.message}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte.snap new file mode 100644 index 000000000000..f50ffe2ec57b --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte.snap @@ -0,0 +1,334 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

{value}

+{:catch error} +

{error.message}

+{:catch anotherError} +

{anotherError.message}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + then_token: THEN_KW@39..43 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@43..49 " value" [] [], + }, + r_curly_token: R_CURLY@49..50 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@54..55 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@55..56 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@56..57 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@57..62 "value" [] [], + }, + r_curly_token: R_CURLY@62..63 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@63..64 "<" [] [], + slash_token: SLASH@64..65 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@65..66 "p" [] [], + }, + r_angle_token: R_ANGLE@66..67 ">" [] [], + }, + }, + ], + }, + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@67..70 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@70..75 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@75..81 " error" [] [], + }, + r_curly_token: R_CURLY@81..82 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@82..86 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@86..87 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@87..88 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@88..89 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@89..102 "error.message" [] [], + }, + r_curly_token: R_CURLY@102..103 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@103..104 "<" [] [], + slash_token: SLASH@104..105 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@105..106 "p" [] [], + }, + r_angle_token: R_ANGLE@106..107 ">" [] [], + }, + }, + ], + }, + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@107..110 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@110..115 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@115..128 " anotherError" [] [], + }, + r_curly_token: R_CURLY@128..129 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@129..133 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@133..134 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@134..135 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@135..136 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@136..156 "anotherError.message" [] [], + }, + r_curly_token: R_CURLY@156..157 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@157..158 "<" [] [], + slash_token: SLASH@158..159 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@159..160 "p" [] [], + }, + r_angle_token: R_ANGLE@160..161 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@161..164 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@164..169 "await" [] [], + r_curly_token: R_CURLY@169..170 "}" [] [], + }, + }, + ], + eof_token: EOF@170..171 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..171 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..170 + 0: SVELTE_AWAIT_BLOCK@0..170 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..161 + 0: SVELTE_AWAIT_THEN_BLOCK@36..67 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: THEN_KW@39..43 "then" [] [] + 2: HTML_TEXT_EXPRESSION@43..49 + 0: HTML_LITERAL@43..49 " value" [] [] + 3: R_CURLY@49..50 "}" [] [] + 4: HTML_ELEMENT_LIST@50..67 + 0: HTML_ELEMENT@50..67 + 0: HTML_OPENING_ELEMENT@50..56 + 0: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@54..55 + 0: HTML_LITERAL@54..55 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@55..55 + 3: R_ANGLE@55..56 ">" [] [] + 1: HTML_ELEMENT_LIST@56..63 + 0: HTML_SINGLE_TEXT_EXPRESSION@56..63 + 0: L_CURLY@56..57 "{" [] [] + 1: HTML_TEXT_EXPRESSION@57..62 + 0: HTML_LITERAL@57..62 "value" [] [] + 2: R_CURLY@62..63 "}" [] [] + 2: HTML_CLOSING_ELEMENT@63..67 + 0: L_ANGLE@63..64 "<" [] [] + 1: SLASH@64..65 "/" [] [] + 2: HTML_TAG_NAME@65..66 + 0: HTML_LITERAL@65..66 "p" [] [] + 3: R_ANGLE@66..67 ">" [] [] + 1: SVELTE_AWAIT_CATCH_BLOCK@67..107 + 0: SV_CURLY_COLON@67..70 "{:" [Newline("\n")] [] + 1: CATCH_KW@70..75 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@75..81 + 0: HTML_LITERAL@75..81 " error" [] [] + 3: R_CURLY@81..82 "}" [] [] + 4: HTML_ELEMENT_LIST@82..107 + 0: HTML_ELEMENT@82..107 + 0: HTML_OPENING_ELEMENT@82..88 + 0: L_ANGLE@82..86 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@86..87 + 0: HTML_LITERAL@86..87 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@87..87 + 3: R_ANGLE@87..88 ">" [] [] + 1: HTML_ELEMENT_LIST@88..103 + 0: HTML_SINGLE_TEXT_EXPRESSION@88..103 + 0: L_CURLY@88..89 "{" [] [] + 1: HTML_TEXT_EXPRESSION@89..102 + 0: HTML_LITERAL@89..102 "error.message" [] [] + 2: R_CURLY@102..103 "}" [] [] + 2: HTML_CLOSING_ELEMENT@103..107 + 0: L_ANGLE@103..104 "<" [] [] + 1: SLASH@104..105 "/" [] [] + 2: HTML_TAG_NAME@105..106 + 0: HTML_LITERAL@105..106 "p" [] [] + 3: R_ANGLE@106..107 ">" [] [] + 2: SVELTE_AWAIT_CATCH_BLOCK@107..161 + 0: SV_CURLY_COLON@107..110 "{:" [Newline("\n")] [] + 1: CATCH_KW@110..115 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@115..128 + 0: HTML_LITERAL@115..128 " anotherError" [] [] + 3: R_CURLY@128..129 "}" [] [] + 4: HTML_ELEMENT_LIST@129..161 + 0: HTML_ELEMENT@129..161 + 0: HTML_OPENING_ELEMENT@129..135 + 0: L_ANGLE@129..133 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@133..134 + 0: HTML_LITERAL@133..134 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@134..134 + 3: R_ANGLE@134..135 ">" [] [] + 1: HTML_ELEMENT_LIST@135..157 + 0: HTML_SINGLE_TEXT_EXPRESSION@135..157 + 0: L_CURLY@135..136 "{" [] [] + 1: HTML_TEXT_EXPRESSION@136..156 + 0: HTML_LITERAL@136..156 "anotherError.message" [] [] + 2: R_CURLY@156..157 "}" [] [] + 2: HTML_CLOSING_ELEMENT@157..161 + 0: L_ANGLE@157..158 "<" [] [] + 1: SLASH@158..159 "/" [] [] + 2: HTML_TAG_NAME@159..160 + 0: HTML_LITERAL@159..160 "p" [] [] + 3: R_ANGLE@160..161 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@161..170 + 0: SV_CURLY_SLASH@161..164 "{/" [Newline("\n")] [] + 1: AWAIT_KW@164..169 "await" [] [] + 2: R_CURLY@169..170 "}" [] [] + 4: EOF@170..171 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_duplicate_catch.svelte:9:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × {:catch} cannot appear more than once within a block. + + 7 │ {:catch anotherError} + 8 │

{anotherError.message}

+ > 9 │ {/await} + │ ^^ + 10 │ + + i This is where the block started. + + 3 │ {:then value} + 4 │

{value}

+ > 5 │ {:catch error} + │ ^^^^^^^^^^^^^^ + > 6 │

{error.message}

+ │ ^^^^^^^^^^^^^^^^^^^^^^ + 7 │ {:catch anotherError} + 8 │

{anotherError.message}

+ +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte new file mode 100644 index 000000000000..6387d5b0916c --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte @@ -0,0 +1,7 @@ +{#await promise} +

Loading...

+{:then value} +

{value}

+{:then anotherValue} +

{anotherValue}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte.snap new file mode 100644 index 000000000000..a13dff89f82a --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte.snap @@ -0,0 +1,269 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

{value}

+{:then anotherValue} +

{anotherValue}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + then_token: THEN_KW@39..43 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@43..49 " value" [] [], + }, + r_curly_token: R_CURLY@49..50 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@54..55 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@55..56 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@56..57 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@57..62 "value" [] [], + }, + r_curly_token: R_CURLY@62..63 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@63..64 "<" [] [], + slash_token: SLASH@64..65 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@65..66 "p" [] [], + }, + r_angle_token: R_ANGLE@66..67 ">" [] [], + }, + }, + ], + }, + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@67..70 "{:" [Newline("\n")] [], + then_token: THEN_KW@70..74 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@74..87 " anotherValue" [] [], + }, + r_curly_token: R_CURLY@87..88 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@88..92 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@92..93 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@93..94 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@94..95 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@95..107 "anotherValue" [] [], + }, + r_curly_token: R_CURLY@107..108 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@108..109 "<" [] [], + slash_token: SLASH@109..110 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@110..111 "p" [] [], + }, + r_angle_token: R_ANGLE@111..112 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@112..115 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@115..120 "await" [] [], + r_curly_token: R_CURLY@120..121 "}" [] [], + }, + }, + ], + eof_token: EOF@121..122 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..122 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..121 + 0: SVELTE_AWAIT_BLOCK@0..121 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..112 + 0: SVELTE_AWAIT_THEN_BLOCK@36..67 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: THEN_KW@39..43 "then" [] [] + 2: HTML_TEXT_EXPRESSION@43..49 + 0: HTML_LITERAL@43..49 " value" [] [] + 3: R_CURLY@49..50 "}" [] [] + 4: HTML_ELEMENT_LIST@50..67 + 0: HTML_ELEMENT@50..67 + 0: HTML_OPENING_ELEMENT@50..56 + 0: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@54..55 + 0: HTML_LITERAL@54..55 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@55..55 + 3: R_ANGLE@55..56 ">" [] [] + 1: HTML_ELEMENT_LIST@56..63 + 0: HTML_SINGLE_TEXT_EXPRESSION@56..63 + 0: L_CURLY@56..57 "{" [] [] + 1: HTML_TEXT_EXPRESSION@57..62 + 0: HTML_LITERAL@57..62 "value" [] [] + 2: R_CURLY@62..63 "}" [] [] + 2: HTML_CLOSING_ELEMENT@63..67 + 0: L_ANGLE@63..64 "<" [] [] + 1: SLASH@64..65 "/" [] [] + 2: HTML_TAG_NAME@65..66 + 0: HTML_LITERAL@65..66 "p" [] [] + 3: R_ANGLE@66..67 ">" [] [] + 1: SVELTE_AWAIT_THEN_BLOCK@67..112 + 0: SV_CURLY_COLON@67..70 "{:" [Newline("\n")] [] + 1: THEN_KW@70..74 "then" [] [] + 2: HTML_TEXT_EXPRESSION@74..87 + 0: HTML_LITERAL@74..87 " anotherValue" [] [] + 3: R_CURLY@87..88 "}" [] [] + 4: HTML_ELEMENT_LIST@88..112 + 0: HTML_ELEMENT@88..112 + 0: HTML_OPENING_ELEMENT@88..94 + 0: L_ANGLE@88..92 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@92..93 + 0: HTML_LITERAL@92..93 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@93..93 + 3: R_ANGLE@93..94 ">" [] [] + 1: HTML_ELEMENT_LIST@94..108 + 0: HTML_SINGLE_TEXT_EXPRESSION@94..108 + 0: L_CURLY@94..95 "{" [] [] + 1: HTML_TEXT_EXPRESSION@95..107 + 0: HTML_LITERAL@95..107 "anotherValue" [] [] + 2: R_CURLY@107..108 "}" [] [] + 2: HTML_CLOSING_ELEMENT@108..112 + 0: L_ANGLE@108..109 "<" [] [] + 1: SLASH@109..110 "/" [] [] + 2: HTML_TAG_NAME@110..111 + 0: HTML_LITERAL@110..111 "p" [] [] + 3: R_ANGLE@111..112 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@112..121 + 0: SV_CURLY_SLASH@112..115 "{/" [Newline("\n")] [] + 1: AWAIT_KW@115..120 "await" [] [] + 2: R_CURLY@120..121 "}" [] [] + 4: EOF@121..122 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_duplicate_then.svelte:7:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × {:then} cannot appear more than once within a block. + + 5 │ {:then anotherValue} + 6 │

{anotherValue}

+ > 7 │ {/await} + │ ^^ + 8 │ + + i This is where the block started. + + 1 │ {#await promise} + 2 │

Loading...

+ > 3 │ {:then value} + │ ^^^^^^^^^^^^^ + > 4 │

{value}

+ │ ^^^^^^^^^^^^^^ + 5 │ {:then anotherValue} + 6 │

{anotherValue}

+ +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte new file mode 100644 index 000000000000..ef82ca1bd48a --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte @@ -0,0 +1,5 @@ +{#await promise catch error} +

{error.message}

+{:catch anotherError} +

{anotherError.message}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte.snap new file mode 100644 index 000000000000..6c2b15ce539c --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte.snap @@ -0,0 +1,236 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise catch error} +

{error.message}

+{:catch anotherError} +

{anotherError.message}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: missing (optional), + catch_clause: SvelteAwaitCatchClause { + catch_token: CATCH_KW@16..21 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@21..27 " error" [] [], + }, + }, + r_curly_token: R_CURLY@27..28 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@28..32 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@32..33 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@33..34 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@34..35 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@35..48 "error.message" [] [], + }, + r_curly_token: R_CURLY@48..49 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@49..50 "<" [] [], + slash_token: SLASH@50..51 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@51..52 "p" [] [], + }, + r_angle_token: R_ANGLE@52..53 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@53..56 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@56..61 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@61..74 " anotherError" [] [], + }, + r_curly_token: R_CURLY@74..75 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@75..79 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@79..80 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@80..81 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@81..82 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@82..102 "anotherError.message" [] [], + }, + r_curly_token: R_CURLY@102..103 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@103..104 "<" [] [], + slash_token: SLASH@104..105 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@105..106 "p" [] [], + }, + r_angle_token: R_ANGLE@106..107 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@107..110 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@110..115 "await" [] [], + r_curly_token: R_CURLY@115..116 "}" [] [], + }, + }, + ], + eof_token: EOF@116..117 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..117 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..116 + 0: SVELTE_AWAIT_BLOCK@0..116 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..53 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: (empty) + 4: SVELTE_AWAIT_CATCH_CLAUSE@16..27 + 0: CATCH_KW@16..21 "catch" [] [] + 1: HTML_TEXT_EXPRESSION@21..27 + 0: HTML_LITERAL@21..27 " error" [] [] + 5: R_CURLY@27..28 "}" [] [] + 6: HTML_ELEMENT_LIST@28..53 + 0: HTML_ELEMENT@28..53 + 0: HTML_OPENING_ELEMENT@28..34 + 0: L_ANGLE@28..32 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@32..33 + 0: HTML_LITERAL@32..33 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@33..33 + 3: R_ANGLE@33..34 ">" [] [] + 1: HTML_ELEMENT_LIST@34..49 + 0: HTML_SINGLE_TEXT_EXPRESSION@34..49 + 0: L_CURLY@34..35 "{" [] [] + 1: HTML_TEXT_EXPRESSION@35..48 + 0: HTML_LITERAL@35..48 "error.message" [] [] + 2: R_CURLY@48..49 "}" [] [] + 2: HTML_CLOSING_ELEMENT@49..53 + 0: L_ANGLE@49..50 "<" [] [] + 1: SLASH@50..51 "/" [] [] + 2: HTML_TAG_NAME@51..52 + 0: HTML_LITERAL@51..52 "p" [] [] + 3: R_ANGLE@52..53 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@53..107 + 0: SVELTE_AWAIT_CATCH_BLOCK@53..107 + 0: SV_CURLY_COLON@53..56 "{:" [Newline("\n")] [] + 1: CATCH_KW@56..61 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@61..74 + 0: HTML_LITERAL@61..74 " anotherError" [] [] + 3: R_CURLY@74..75 "}" [] [] + 4: HTML_ELEMENT_LIST@75..107 + 0: HTML_ELEMENT@75..107 + 0: HTML_OPENING_ELEMENT@75..81 + 0: L_ANGLE@75..79 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@79..80 + 0: HTML_LITERAL@79..80 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@80..80 + 3: R_ANGLE@80..81 ">" [] [] + 1: HTML_ELEMENT_LIST@81..103 + 0: HTML_SINGLE_TEXT_EXPRESSION@81..103 + 0: L_CURLY@81..82 "{" [] [] + 1: HTML_TEXT_EXPRESSION@82..102 + 0: HTML_LITERAL@82..102 "anotherError.message" [] [] + 2: R_CURLY@102..103 "}" [] [] + 2: HTML_CLOSING_ELEMENT@103..107 + 0: L_ANGLE@103..104 "<" [] [] + 1: SLASH@104..105 "/" [] [] + 2: HTML_TAG_NAME@105..106 + 0: HTML_LITERAL@105..106 "p" [] [] + 3: R_ANGLE@106..107 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@107..116 + 0: SV_CURLY_SLASH@107..110 "{/" [Newline("\n")] [] + 1: AWAIT_KW@110..115 "await" [] [] + 2: R_CURLY@115..116 "}" [] [] + 4: EOF@116..117 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_invalid_catch_only_with_clause.svelte:5:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × {:catch} cannot appear more than once within a block. + + 3 │ {:catch anotherError} + 4 │

{anotherError.message}

+ > 5 │ {/await} + │ ^^ + 6 │ + + i This is where the block started. + + > 1 │ {#await promise catch error} + │ ^^^^^^^^^^^ + 2 │

{error.message}

+ 3 │ {:catch anotherError} + +await_invalid_catch_only_with_clause.svelte:3:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × {:catch} cannot appear before the {:then} block. + + 1 │ {#await promise catch error} + 2 │

{error.message}

+ > 3 │ {:catch anotherError} + │ ^^^^^^^^^^^^^^^^^^^^^ + > 4 │

{anotherError.message}

+ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5 │ {/await} + 6 │ + + i This is where the {:then} block starts. + + 3 │ {:catch anotherError} + 4 │

{anotherError.message}

+ > 5 │ {/await} + │ ^^ + 6 │ + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte new file mode 100644 index 000000000000..e4460f4a7eff --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte @@ -0,0 +1,5 @@ +{#await promise then value} +

{value}

+{:then anotherValue} +

{anotherValue}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte.snap new file mode 100644 index 000000000000..e056cbee23cd --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte.snap @@ -0,0 +1,215 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise then value} +

{value}

+{:then anotherValue} +

{anotherValue}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@16..20 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@20..26 " value" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@26..27 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@27..31 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@31..32 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@32..33 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@33..34 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@34..39 "value" [] [], + }, + r_curly_token: R_CURLY@39..40 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@40..41 "<" [] [], + slash_token: SLASH@41..42 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@42..43 "p" [] [], + }, + r_angle_token: R_ANGLE@43..44 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@44..47 "{:" [Newline("\n")] [], + then_token: THEN_KW@47..51 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@51..64 " anotherValue" [] [], + }, + r_curly_token: R_CURLY@64..65 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@65..69 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@69..70 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@70..71 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@71..72 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@72..84 "anotherValue" [] [], + }, + r_curly_token: R_CURLY@84..85 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@85..86 "<" [] [], + slash_token: SLASH@86..87 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@87..88 "p" [] [], + }, + r_angle_token: R_ANGLE@88..89 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@89..92 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@92..97 "await" [] [], + r_curly_token: R_CURLY@97..98 "}" [] [], + }, + }, + ], + eof_token: EOF@98..99 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..99 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..98 + 0: SVELTE_AWAIT_BLOCK@0..98 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..44 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@16..26 + 0: THEN_KW@16..20 "then" [] [] + 1: HTML_TEXT_EXPRESSION@20..26 + 0: HTML_LITERAL@20..26 " value" [] [] + 4: (empty) + 5: R_CURLY@26..27 "}" [] [] + 6: HTML_ELEMENT_LIST@27..44 + 0: HTML_ELEMENT@27..44 + 0: HTML_OPENING_ELEMENT@27..33 + 0: L_ANGLE@27..31 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@31..32 + 0: HTML_LITERAL@31..32 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@32..32 + 3: R_ANGLE@32..33 ">" [] [] + 1: HTML_ELEMENT_LIST@33..40 + 0: HTML_SINGLE_TEXT_EXPRESSION@33..40 + 0: L_CURLY@33..34 "{" [] [] + 1: HTML_TEXT_EXPRESSION@34..39 + 0: HTML_LITERAL@34..39 "value" [] [] + 2: R_CURLY@39..40 "}" [] [] + 2: HTML_CLOSING_ELEMENT@40..44 + 0: L_ANGLE@40..41 "<" [] [] + 1: SLASH@41..42 "/" [] [] + 2: HTML_TAG_NAME@42..43 + 0: HTML_LITERAL@42..43 "p" [] [] + 3: R_ANGLE@43..44 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@44..89 + 0: SVELTE_AWAIT_THEN_BLOCK@44..89 + 0: SV_CURLY_COLON@44..47 "{:" [Newline("\n")] [] + 1: THEN_KW@47..51 "then" [] [] + 2: HTML_TEXT_EXPRESSION@51..64 + 0: HTML_LITERAL@51..64 " anotherValue" [] [] + 3: R_CURLY@64..65 "}" [] [] + 4: HTML_ELEMENT_LIST@65..89 + 0: HTML_ELEMENT@65..89 + 0: HTML_OPENING_ELEMENT@65..71 + 0: L_ANGLE@65..69 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@69..70 + 0: HTML_LITERAL@69..70 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@70..70 + 3: R_ANGLE@70..71 ">" [] [] + 1: HTML_ELEMENT_LIST@71..85 + 0: HTML_SINGLE_TEXT_EXPRESSION@71..85 + 0: L_CURLY@71..72 "{" [] [] + 1: HTML_TEXT_EXPRESSION@72..84 + 0: HTML_LITERAL@72..84 "anotherValue" [] [] + 2: R_CURLY@84..85 "}" [] [] + 2: HTML_CLOSING_ELEMENT@85..89 + 0: L_ANGLE@85..86 "<" [] [] + 1: SLASH@86..87 "/" [] [] + 2: HTML_TAG_NAME@87..88 + 0: HTML_LITERAL@87..88 "p" [] [] + 3: R_ANGLE@88..89 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@89..98 + 0: SV_CURLY_SLASH@89..92 "{/" [Newline("\n")] [] + 1: AWAIT_KW@92..97 "await" [] [] + 2: R_CURLY@97..98 "}" [] [] + 4: EOF@98..99 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_invalid_shorthand_with_clause.svelte:5:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × {:then} cannot appear more than once within a block. + + 3 │ {:then anotherValue} + 4 │

{anotherValue}

+ > 5 │ {/await} + │ ^^ + 6 │ + + i This is where the block started. + + > 1 │ {#await promise then value} + │ ^^^^^^^^^^ + 2 │

{value}

+ 3 │ {:then anotherValue} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte new file mode 100644 index 000000000000..dc272c9186ce --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte @@ -0,0 +1,7 @@ +{#await promise} +

Loading...

+{:then value} +

{value}

+{:catch} +

Error occurred

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte.snap new file mode 100644 index 000000000000..d8b3cffac3a2 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte.snap @@ -0,0 +1,255 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

{value}

+{:catch} +

Error occurred

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + HtmlBogusElement { + items: [ + SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + HtmlBogus { + items: [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + then_token: THEN_KW@39..43 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@43..49 " value" [] [], + }, + r_curly_token: R_CURLY@49..50 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@54..55 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@55..56 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@56..57 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@57..62 "value" [] [], + }, + r_curly_token: R_CURLY@62..63 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@63..64 "<" [] [], + slash_token: SLASH@64..65 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@65..66 "p" [] [], + }, + r_angle_token: R_ANGLE@66..67 ">" [] [], + }, + }, + ], + }, + HtmlBogus { + items: [ + SV_CURLY_COLON@67..70 "{:" [Newline("\n")] [], + CATCH_KW@70..75 "catch" [] [], + HTML_LITERAL@75..75 "" [] [], + R_CURLY@75..76 "}" [] [], + HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@76..80 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@80..81 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@81..82 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@82..96 "Error occurred" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@96..97 "<" [] [], + slash_token: SLASH@97..98 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@98..99 "p" [] [], + }, + r_angle_token: R_ANGLE@99..100 ">" [] [], + }, + }, + ], + ], + }, + ], + }, + SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@100..103 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@103..108 "await" [] [], + r_curly_token: R_CURLY@108..109 "}" [] [], + }, + ], + }, + ], + eof_token: EOF@109..110 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..110 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..109 + 0: HTML_BOGUS_ELEMENT@0..109 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: HTML_BOGUS@36..100 + 0: SVELTE_AWAIT_THEN_BLOCK@36..67 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: THEN_KW@39..43 "then" [] [] + 2: HTML_TEXT_EXPRESSION@43..49 + 0: HTML_LITERAL@43..49 " value" [] [] + 3: R_CURLY@49..50 "}" [] [] + 4: HTML_ELEMENT_LIST@50..67 + 0: HTML_ELEMENT@50..67 + 0: HTML_OPENING_ELEMENT@50..56 + 0: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@54..55 + 0: HTML_LITERAL@54..55 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@55..55 + 3: R_ANGLE@55..56 ">" [] [] + 1: HTML_ELEMENT_LIST@56..63 + 0: HTML_SINGLE_TEXT_EXPRESSION@56..63 + 0: L_CURLY@56..57 "{" [] [] + 1: HTML_TEXT_EXPRESSION@57..62 + 0: HTML_LITERAL@57..62 "value" [] [] + 2: R_CURLY@62..63 "}" [] [] + 2: HTML_CLOSING_ELEMENT@63..67 + 0: L_ANGLE@63..64 "<" [] [] + 1: SLASH@64..65 "/" [] [] + 2: HTML_TAG_NAME@65..66 + 0: HTML_LITERAL@65..66 "p" [] [] + 3: R_ANGLE@66..67 ">" [] [] + 1: HTML_BOGUS@67..100 + 0: SV_CURLY_COLON@67..70 "{:" [Newline("\n")] [] + 1: CATCH_KW@70..75 "catch" [] [] + 2: HTML_LITERAL@75..75 "" [] [] + 3: R_CURLY@75..76 "}" [] [] + 4: HTML_ELEMENT_LIST@76..100 + 0: HTML_ELEMENT@76..100 + 0: HTML_OPENING_ELEMENT@76..82 + 0: L_ANGLE@76..80 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@80..81 + 0: HTML_LITERAL@80..81 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@81..81 + 3: R_ANGLE@81..82 ">" [] [] + 1: HTML_ELEMENT_LIST@82..96 + 0: HTML_CONTENT@82..96 + 0: HTML_LITERAL@82..96 "Error occurred" [] [] + 2: HTML_CLOSING_ELEMENT@96..100 + 0: L_ANGLE@96..97 "<" [] [] + 1: SLASH@97..98 "/" [] [] + 2: HTML_TAG_NAME@98..99 + 0: HTML_LITERAL@98..99 "p" [] [] + 3: R_ANGLE@99..100 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@100..109 + 0: SV_CURLY_SLASH@100..103 "{/" [Newline("\n")] [] + 1: AWAIT_KW@103..108 "await" [] [] + 2: R_CURLY@108..109 "}" [] [] + 4: EOF@109..110 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_missing_catch_binding.svelte:5:8 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an expression, instead none was found. + + 3 │ {:then value} + 4 │

{value}

+ > 5 │ {:catch} + │ + 6 │

Error occurred

+ 7 │ {/await} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte new file mode 100644 index 000000000000..a6779f13e5c0 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte @@ -0,0 +1,2 @@ +{#await promise then value} +

The value is {value}

diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte.snap new file mode 100644 index 000000000000..fdbb3a1579ba --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte.snap @@ -0,0 +1,145 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise then value} +

The value is {value}

+ +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@16..20 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@20..26 " value" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@26..27 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@27..31 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@31..32 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@32..33 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@33..46 "The value is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@46..47 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@47..52 "value" [] [], + }, + r_curly_token: R_CURLY@52..53 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@53..54 "<" [] [], + slash_token: SLASH@54..55 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@55..56 "p" [] [], + }, + r_angle_token: R_ANGLE@56..57 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: missing (required), + }, + ], + eof_token: EOF@57..58 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..58 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..57 + 0: SVELTE_AWAIT_BLOCK@0..57 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..57 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@16..26 + 0: THEN_KW@16..20 "then" [] [] + 1: HTML_TEXT_EXPRESSION@20..26 + 0: HTML_LITERAL@20..26 " value" [] [] + 4: (empty) + 5: R_CURLY@26..27 "}" [] [] + 6: HTML_ELEMENT_LIST@27..57 + 0: HTML_ELEMENT@27..57 + 0: HTML_OPENING_ELEMENT@27..33 + 0: L_ANGLE@27..31 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@31..32 + 0: HTML_LITERAL@31..32 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@32..32 + 3: R_ANGLE@32..33 ">" [] [] + 1: HTML_ELEMENT_LIST@33..53 + 0: HTML_CONTENT@33..46 + 0: HTML_LITERAL@33..46 "The value is" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@46..53 + 0: L_CURLY@46..47 "{" [] [] + 1: HTML_TEXT_EXPRESSION@47..52 + 0: HTML_LITERAL@47..52 "value" [] [] + 2: R_CURLY@52..53 "}" [] [] + 2: HTML_CLOSING_ELEMENT@53..57 + 0: L_ANGLE@53..54 "<" [] [] + 1: SLASH@54..55 "/" [] [] + 2: HTML_TAG_NAME@55..56 + 0: HTML_LITERAL@55..56 "p" [] [] + 3: R_ANGLE@56..57 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@57..57 + 2: (empty) + 4: EOF@57..58 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_missing_close.svelte:3:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a closing block, instead found none. + + 1 │ {#await promise then value} + 2 │

The value is {value}

+ > 3 │ + │ + + i This is where the block started. + + 1 │ {#await promise then value} + 2 │

The value is {value}

+ > 3 │ + │ + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte new file mode 100644 index 000000000000..c29b98cc1193 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte @@ -0,0 +1,5 @@ +{#await} +

Loading...

+{:then value} +

The value is {value}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte.snap new file mode 100644 index 000000000000..2f4c80e83cb1 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte.snap @@ -0,0 +1,194 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await} +

Loading...

+{:then value} +

The value is {value}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + HtmlBogusElement { + items: [ + HtmlBogus { + items: [ + SV_CURLY_HASH@0..2 "{#" [] [], + AWAIT_KW@2..7 "await" [] [], + HTML_LITERAL@7..7 "" [] [], + R_CURLY@7..8 "}" [] [], + HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@8..12 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@12..13 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@13..14 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@14..24 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@24..25 "<" [] [], + slash_token: SLASH@25..26 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@26..27 "p" [] [], + }, + r_angle_token: R_ANGLE@27..28 ">" [] [], + }, + }, + ], + ], + }, + SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@28..31 "{:" [Newline("\n")] [], + then_token: THEN_KW@31..35 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@35..41 " value" [] [], + }, + r_curly_token: R_CURLY@41..42 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@42..46 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@46..47 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@47..48 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@48..61 "The value is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@61..62 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@62..67 "value" [] [], + }, + r_curly_token: R_CURLY@67..68 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@68..69 "<" [] [], + slash_token: SLASH@69..70 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@70..71 "p" [] [], + }, + r_angle_token: R_ANGLE@71..72 ">" [] [], + }, + }, + ], + }, + ], + SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@72..75 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@75..80 "await" [] [], + r_curly_token: R_CURLY@80..81 "}" [] [], + }, + ], + }, + ], + eof_token: EOF@81..82 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..82 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..81 + 0: HTML_BOGUS_ELEMENT@0..81 + 0: HTML_BOGUS@0..28 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_LITERAL@7..7 "" [] [] + 3: R_CURLY@7..8 "}" [] [] + 4: HTML_ELEMENT_LIST@8..28 + 0: HTML_ELEMENT@8..28 + 0: HTML_OPENING_ELEMENT@8..14 + 0: L_ANGLE@8..12 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@12..13 + 0: HTML_LITERAL@12..13 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@13..13 + 3: R_ANGLE@13..14 ">" [] [] + 1: HTML_ELEMENT_LIST@14..24 + 0: HTML_CONTENT@14..24 + 0: HTML_LITERAL@14..24 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@24..28 + 0: L_ANGLE@24..25 "<" [] [] + 1: SLASH@25..26 "/" [] [] + 2: HTML_TAG_NAME@26..27 + 0: HTML_LITERAL@26..27 "p" [] [] + 3: R_ANGLE@27..28 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@28..72 + 0: SVELTE_AWAIT_THEN_BLOCK@28..72 + 0: SV_CURLY_COLON@28..31 "{:" [Newline("\n")] [] + 1: THEN_KW@31..35 "then" [] [] + 2: HTML_TEXT_EXPRESSION@35..41 + 0: HTML_LITERAL@35..41 " value" [] [] + 3: R_CURLY@41..42 "}" [] [] + 4: HTML_ELEMENT_LIST@42..72 + 0: HTML_ELEMENT@42..72 + 0: HTML_OPENING_ELEMENT@42..48 + 0: L_ANGLE@42..46 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@46..47 + 0: HTML_LITERAL@46..47 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@47..47 + 3: R_ANGLE@47..48 ">" [] [] + 1: HTML_ELEMENT_LIST@48..68 + 0: HTML_CONTENT@48..61 + 0: HTML_LITERAL@48..61 "The value is" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@61..68 + 0: L_CURLY@61..62 "{" [] [] + 1: HTML_TEXT_EXPRESSION@62..67 + 0: HTML_LITERAL@62..67 "value" [] [] + 2: R_CURLY@67..68 "}" [] [] + 2: HTML_CLOSING_ELEMENT@68..72 + 0: L_ANGLE@68..69 "<" [] [] + 1: SLASH@69..70 "/" [] [] + 2: HTML_TAG_NAME@70..71 + 0: HTML_LITERAL@70..71 "p" [] [] + 3: R_ANGLE@71..72 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@72..81 + 0: SV_CURLY_SLASH@72..75 "{/" [Newline("\n")] [] + 1: AWAIT_KW@75..80 "await" [] [] + 2: R_CURLY@80..81 "}" [] [] + 4: EOF@81..82 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_missing_expression.svelte:1:8 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an expression, instead none was found. + + > 1 │ {#await} + │ + 2 │

Loading...

+ 3 │ {:then value} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte new file mode 100644 index 000000000000..11c243b0b5db --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte @@ -0,0 +1,5 @@ +{#await promise} +

Loading...

+{:then} +

Done!

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte.snap new file mode 100644 index 000000000000..59ce2d290ba5 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte.snap @@ -0,0 +1,190 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:then} +

Done!

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + HtmlBogusElement { + items: [ + SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + HtmlBogus { + items: [ + HtmlBogus { + items: [ + SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + THEN_KW@39..43 "then" [] [], + HTML_LITERAL@43..43 "" [] [], + R_CURLY@43..44 "}" [] [], + HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@44..48 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@48..49 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@49..50 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@50..55 "Done!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@55..56 "<" [] [], + slash_token: SLASH@56..57 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@57..58 "p" [] [], + }, + r_angle_token: R_ANGLE@58..59 ">" [] [], + }, + }, + ], + ], + }, + ], + }, + SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@59..62 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@62..67 "await" [] [], + r_curly_token: R_CURLY@67..68 "}" [] [], + }, + ], + }, + ], + eof_token: EOF@68..69 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..69 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..68 + 0: HTML_BOGUS_ELEMENT@0..68 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: HTML_BOGUS@36..59 + 0: HTML_BOGUS@36..59 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: THEN_KW@39..43 "then" [] [] + 2: HTML_LITERAL@43..43 "" [] [] + 3: R_CURLY@43..44 "}" [] [] + 4: HTML_ELEMENT_LIST@44..59 + 0: HTML_ELEMENT@44..59 + 0: HTML_OPENING_ELEMENT@44..50 + 0: L_ANGLE@44..48 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@48..49 + 0: HTML_LITERAL@48..49 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@49..49 + 3: R_ANGLE@49..50 ">" [] [] + 1: HTML_ELEMENT_LIST@50..55 + 0: HTML_CONTENT@50..55 + 0: HTML_LITERAL@50..55 "Done!" [] [] + 2: HTML_CLOSING_ELEMENT@55..59 + 0: L_ANGLE@55..56 "<" [] [] + 1: SLASH@56..57 "/" [] [] + 2: HTML_TAG_NAME@57..58 + 0: HTML_LITERAL@57..58 "p" [] [] + 3: R_ANGLE@58..59 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@59..68 + 0: SV_CURLY_SLASH@59..62 "{/" [Newline("\n")] [] + 1: AWAIT_KW@62..67 "await" [] [] + 2: R_CURLY@67..68 "}" [] [] + 4: EOF@68..69 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_missing_then_binding.svelte:3:7 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an expression, instead none was found. + + 1 │ {#await promise} + 2 │

Loading...

+ > 3 │ {:then} + │ + 4 │

Done!

+ 5 │ {/await} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte new file mode 100644 index 000000000000..d1b9411feb48 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte @@ -0,0 +1,3 @@ +{#await promise then} +

Done!

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte.snap new file mode 100644 index 000000000000..b43120c50e65 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte.snap @@ -0,0 +1,135 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise then} +

Done!

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + HtmlBogusElement { + items: [ + HtmlBogus { + items: [ + SV_CURLY_HASH@0..2 "{#" [] [], + AWAIT_KW@2..7 "await" [] [], + HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + HtmlBogus { + items: [ + THEN_KW@16..20 "then" [] [], + HTML_LITERAL@20..20 "" [] [], + ], + }, + R_CURLY@20..21 "}" [] [], + HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@25..26 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@26..27 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@27..32 "Done!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + ], + }, + SvelteAwaitClausesList [], + SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@36..39 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@39..44 "await" [] [], + r_curly_token: R_CURLY@44..45 "}" [] [], + }, + ], + }, + ], + eof_token: EOF@45..46 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..46 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..45 + 0: HTML_BOGUS_ELEMENT@0..45 + 0: HTML_BOGUS@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: HTML_BOGUS@16..20 + 0: THEN_KW@16..20 "then" [] [] + 1: HTML_LITERAL@20..20 "" [] [] + 4: R_CURLY@20..21 "}" [] [] + 5: HTML_ELEMENT_LIST@21..36 + 0: HTML_ELEMENT@21..36 + 0: HTML_OPENING_ELEMENT@21..27 + 0: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@25..26 + 0: HTML_LITERAL@25..26 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@26..26 + 3: R_ANGLE@26..27 ">" [] [] + 1: HTML_ELEMENT_LIST@27..32 + 0: HTML_CONTENT@27..32 + 0: HTML_LITERAL@27..32 "Done!" [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..36 + 2: SVELTE_AWAIT_CLOSING_BLOCK@36..45 + 0: SV_CURLY_SLASH@36..39 "{/" [Newline("\n")] [] + 1: AWAIT_KW@39..44 "await" [] [] + 2: R_CURLY@44..45 "}" [] [] + 4: EOF@45..46 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_shorthand_missing_binding.svelte:1:21 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an expression, instead none was found. + + > 1 │ {#await promise then} + │ + 2 │

Done!

+ 3 │ {/await} + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte new file mode 100644 index 000000000000..5fc37e1eb8b8 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte @@ -0,0 +1,4 @@ +{#await promise} +

Loading...

+{:then value} +

The value is {value}

diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte.snap new file mode 100644 index 000000000000..b4b6161ebcea --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte.snap @@ -0,0 +1,196 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+ +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + then_token: THEN_KW@39..43 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@43..49 " value" [] [], + }, + r_curly_token: R_CURLY@49..50 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@54..55 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@55..56 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@56..69 "The value is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@69..70 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@70..75 "value" [] [], + }, + r_curly_token: R_CURLY@75..76 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@76..77 "<" [] [], + slash_token: SLASH@77..78 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@78..79 "p" [] [], + }, + r_angle_token: R_ANGLE@79..80 ">" [] [], + }, + }, + ], + }, + ], + closing_block: missing (required), + }, + ], + eof_token: EOF@80..81 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..81 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..80 + 0: SVELTE_AWAIT_BLOCK@0..80 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..80 + 0: SVELTE_AWAIT_THEN_BLOCK@36..80 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: THEN_KW@39..43 "then" [] [] + 2: HTML_TEXT_EXPRESSION@43..49 + 0: HTML_LITERAL@43..49 " value" [] [] + 3: R_CURLY@49..50 "}" [] [] + 4: HTML_ELEMENT_LIST@50..80 + 0: HTML_ELEMENT@50..80 + 0: HTML_OPENING_ELEMENT@50..56 + 0: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@54..55 + 0: HTML_LITERAL@54..55 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@55..55 + 3: R_ANGLE@55..56 ">" [] [] + 1: HTML_ELEMENT_LIST@56..76 + 0: HTML_CONTENT@56..69 + 0: HTML_LITERAL@56..69 "The value is" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@69..76 + 0: L_CURLY@69..70 "{" [] [] + 1: HTML_TEXT_EXPRESSION@70..75 + 0: HTML_LITERAL@70..75 "value" [] [] + 2: R_CURLY@75..76 "}" [] [] + 2: HTML_CLOSING_ELEMENT@76..80 + 0: L_ANGLE@76..77 "<" [] [] + 1: SLASH@77..78 "/" [] [] + 2: HTML_TAG_NAME@78..79 + 0: HTML_LITERAL@78..79 "p" [] [] + 3: R_ANGLE@79..80 ">" [] [] + 2: (empty) + 4: EOF@80..81 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +await_unclosed.svelte:5:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a closing block, instead found none. + + 3 │ {:then value} + 4 │

The value is {value}

+ > 5 │ + │ + + i This is where the block started. + + 3 │ {:then value} + 4 │

The value is {value}

+ > 5 │ + │ + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/each_missing_as.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/each_missing_as.svelte.snap index 8ade3aa0a5fd..ca93fb0a4ac0 100644 --- a/crates/biome_html_parser/tests/html_specs/error/svelte/each_missing_as.svelte.snap +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/each_missing_as.svelte.snap @@ -20,51 +20,52 @@ HtmlRoot { frontmatter: missing (optional), directive: missing (optional), html: HtmlElementList [ - SvelteEachBlock { - opening_block: SvelteEachOpeningBlock { - sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], - each_token: EACH_KW@2..6 "each" [] [], - list: HtmlTextExpression { - html_literal_token: HTML_LITERAL@6..17 " items item" [] [], - }, - item: missing (optional), - r_curly_token: R_CURLY@17..18 "}" [] [], - }, - children: HtmlElementList [ - HtmlElement { - opening_element: HtmlOpeningElement { - l_angle_token: L_ANGLE@18..22 "<" [Newline("\n"), Whitespace(" ")] [], - name: HtmlTagName { - value_token: HTML_LITERAL@22..25 "div" [] [], - }, - attributes: HtmlAttributeList [], - r_angle_token: R_ANGLE@25..26 ">" [] [], + SvelteBogusBlock { + items: [ + SvelteEachOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + each_token: EACH_KW@2..6 "each" [] [], + list: HtmlTextExpression { + html_literal_token: HTML_LITERAL@6..17 " items item" [] [], }, - children: HtmlElementList [ - HtmlSingleTextExpression { - l_curly_token: L_CURLY@26..27 "{" [] [], - expression: HtmlTextExpression { - html_literal_token: HTML_LITERAL@27..31 "item" [] [], + item: missing (optional), + r_curly_token: R_CURLY@17..18 "}" [] [], + }, + HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@18..22 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@22..25 "div" [] [], }, - r_curly_token: R_CURLY@31..32 "}" [] [], + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@25..26 ">" [] [], }, - ], - closing_element: HtmlClosingElement { - l_angle_token: L_ANGLE@32..33 "<" [] [], - slash_token: SLASH@33..34 "/" [] [], - name: HtmlTagName { - value_token: HTML_LITERAL@34..37 "div" [] [], + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@26..27 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@27..31 "item" [] [], + }, + r_curly_token: R_CURLY@31..32 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..37 "div" [] [], + }, + r_angle_token: R_ANGLE@37..38 ">" [] [], }, - r_angle_token: R_ANGLE@37..38 ">" [] [], }, + ], + SvelteEachClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@38..41 "{/" [Newline("\n")] [], + each_token: EACH_KW@41..45 "each" [] [], + r_curly_token: R_CURLY@45..46 "}" [] [], }, ], - else_clause: missing (optional), - closing_block: SvelteEachClosingBlock { - sv_curly_slash_token: SV_CURLY_SLASH@38..41 "{/" [Newline("\n")] [], - each_token: EACH_KW@41..45 "each" [] [], - r_curly_token: R_CURLY@45..46 "}" [] [], - }, }, ], eof_token: EOF@46..47 "" [Newline("\n")] [], @@ -79,7 +80,7 @@ HtmlRoot { 1: (empty) 2: (empty) 3: HTML_ELEMENT_LIST@0..46 - 0: SVELTE_EACH_BLOCK@0..46 + 0: SVELTE_BOGUS_BLOCK@0..46 0: SVELTE_EACH_OPENING_BLOCK@0..18 0: SV_CURLY_HASH@0..2 "{#" [] [] 1: EACH_KW@2..6 "each" [] [] @@ -107,8 +108,7 @@ HtmlRoot { 2: HTML_TAG_NAME@34..37 0: HTML_LITERAL@34..37 "div" [] [] 3: R_ANGLE@37..38 ">" [] [] - 2: (empty) - 3: SVELTE_EACH_CLOSING_BLOCK@38..46 + 2: SVELTE_EACH_CLOSING_BLOCK@38..46 0: SV_CURLY_SLASH@38..41 "{/" [Newline("\n")] [] 1: EACH_KW@41..45 "each" [] [] 2: R_CURLY@45..46 "}" [] [] diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte new file mode 100644 index 000000000000..b13a557d5b68 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte @@ -0,0 +1,2 @@ +{#snippet greeting()} +

Hello!

diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte.snap new file mode 100644 index 000000000000..dac7ff7f3191 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte.snap @@ -0,0 +1,119 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet greeting()} +

Hello!

+ +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..20 " greeting()" [] [], + }, + r_curly_token: R_CURLY@20..21 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@25..26 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@26..27 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@27..33 "Hello!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@33..34 "<" [] [], + slash_token: SLASH@34..35 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@35..36 "p" [] [], + }, + r_angle_token: R_ANGLE@36..37 ">" [] [], + }, + }, + ], + }, + closing_block: missing (required), + }, + ], + eof_token: EOF@37..38 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..38 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..37 + 0: SVELTE_SNIPPET_BLOCK@0..37 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..37 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..20 + 0: HTML_LITERAL@9..20 " greeting()" [] [] + 3: R_CURLY@20..21 "}" [] [] + 4: HTML_ELEMENT_LIST@21..37 + 0: HTML_ELEMENT@21..37 + 0: HTML_OPENING_ELEMENT@21..27 + 0: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@25..26 + 0: HTML_LITERAL@25..26 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@26..26 + 3: R_ANGLE@26..27 ">" [] [] + 1: HTML_ELEMENT_LIST@27..33 + 0: HTML_CONTENT@27..33 + 0: HTML_LITERAL@27..33 "Hello!" [] [] + 2: HTML_CLOSING_ELEMENT@33..37 + 0: L_ANGLE@33..34 "<" [] [] + 1: SLASH@34..35 "/" [] [] + 2: HTML_TAG_NAME@35..36 + 0: HTML_LITERAL@35..36 "p" [] [] + 3: R_ANGLE@36..37 ">" [] [] + 1: (empty) + 4: EOF@37..38 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +snippet_missing_close.svelte:3:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a closing block, instead found none. + + 1 │ {#snippet greeting()} + 2 │

Hello!

+ > 3 │ + │ + + i This is where the block started. + + 1 │ {#snippet greeting()} + 2 │

Hello!

+ > 3 │ + │ + +``` diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte new file mode 100644 index 000000000000..0006daeef592 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte @@ -0,0 +1,5 @@ +{#snippet greeting()} +

Hello!

+{/snippet + +{@render greeting()} diff --git a/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte.snap b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte.snap new file mode 100644 index 000000000000..26ae868da492 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte.snap @@ -0,0 +1,139 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet greeting()} +

Hello!

+{/snippet + +{@render greeting()} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..20 " greeting()" [] [], + }, + r_curly_token: R_CURLY@20..21 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@25..26 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@26..27 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@27..33 "Hello!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@33..34 "<" [] [], + slash_token: SLASH@34..35 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@35..36 "p" [] [], + }, + r_angle_token: R_ANGLE@36..37 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@37..40 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@40..47 "snippet" [] [], + r_curly_token: missing (required), + }, + }, + SvelteRenderBlock { + sv_curly_at_token: SV_CURLY_AT@47..51 "{@" [Newline("\n"), Newline("\n")] [], + render_token: RENDER_KW@51..57 "render" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@57..68 " greeting()" [] [], + }, + r_curly_token: R_CURLY@68..69 "}" [] [], + }, + ], + eof_token: EOF@69..70 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..70 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..69 + 0: SVELTE_SNIPPET_BLOCK@0..47 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..37 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..20 + 0: HTML_LITERAL@9..20 " greeting()" [] [] + 3: R_CURLY@20..21 "}" [] [] + 4: HTML_ELEMENT_LIST@21..37 + 0: HTML_ELEMENT@21..37 + 0: HTML_OPENING_ELEMENT@21..27 + 0: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@25..26 + 0: HTML_LITERAL@25..26 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@26..26 + 3: R_ANGLE@26..27 ">" [] [] + 1: HTML_ELEMENT_LIST@27..33 + 0: HTML_CONTENT@27..33 + 0: HTML_LITERAL@27..33 "Hello!" [] [] + 2: HTML_CLOSING_ELEMENT@33..37 + 0: L_ANGLE@33..34 "<" [] [] + 1: SLASH@34..35 "/" [] [] + 2: HTML_TAG_NAME@35..36 + 0: HTML_LITERAL@35..36 "p" [] [] + 3: R_ANGLE@36..37 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@37..47 + 0: SV_CURLY_SLASH@37..40 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@40..47 "snippet" [] [] + 2: (empty) + 1: SVELTE_RENDER_BLOCK@47..69 + 0: SV_CURLY_AT@47..51 "{@" [Newline("\n"), Newline("\n")] [] + 1: RENDER_KW@51..57 "render" [] [] + 2: HTML_TEXT_EXPRESSION@57..68 + 0: HTML_LITERAL@57..68 " greeting()" [] [] + 3: R_CURLY@68..69 "}" [] [] + 4: EOF@69..70 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +snippet_unclosed.svelte:5:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `}` but instead found `{@` + + 3 │ {/snippet + 4 │ + > 5 │ {@render greeting()} + │ ^^ + 6 │ + + i Remove {@ + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte new file mode 100644 index 000000000000..812e0b61aa2f --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte @@ -0,0 +1,4 @@ +{#await promise then [first, second, ...rest]} +

First: {first}, Second: {second}

+

Rest: {rest.join(', ')}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte.snap new file mode 100644 index 000000000000..0f2663223c9d --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte.snap @@ -0,0 +1,201 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise then [first, second, ...rest]} +

First: {first}, Second: {second}

+

Rest: {rest.join(', ')}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@16..20 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@20..45 " [first, second, ...rest]" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@45..46 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@46..50 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@50..51 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@51..52 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@52..59 "First:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@59..60 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@60..65 "first" [] [], + }, + r_curly_token: R_CURLY@65..66 "}" [] [], + }, + HtmlContent { + value_token: HTML_LITERAL@66..76 ", Second:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@76..77 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@77..83 "second" [] [], + }, + r_curly_token: R_CURLY@83..84 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@84..85 "<" [] [], + slash_token: SLASH@85..86 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@86..87 "p" [] [], + }, + r_angle_token: R_ANGLE@87..88 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@88..92 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@92..93 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@93..94 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@94..100 "Rest:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@100..101 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@101..116 "rest.join(', ')" [] [], + }, + r_curly_token: R_CURLY@116..117 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@117..118 "<" [] [], + slash_token: SLASH@118..119 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@119..120 "p" [] [], + }, + r_angle_token: R_ANGLE@120..121 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@121..124 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@124..129 "await" [] [], + r_curly_token: R_CURLY@129..130 "}" [] [], + }, + }, + ], + eof_token: EOF@130..131 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..131 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..130 + 0: SVELTE_AWAIT_BLOCK@0..130 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..121 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@16..45 + 0: THEN_KW@16..20 "then" [] [] + 1: HTML_TEXT_EXPRESSION@20..45 + 0: HTML_LITERAL@20..45 " [first, second, ...rest]" [] [] + 4: (empty) + 5: R_CURLY@45..46 "}" [] [] + 6: HTML_ELEMENT_LIST@46..121 + 0: HTML_ELEMENT@46..88 + 0: HTML_OPENING_ELEMENT@46..52 + 0: L_ANGLE@46..50 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@50..51 + 0: HTML_LITERAL@50..51 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@51..51 + 3: R_ANGLE@51..52 ">" [] [] + 1: HTML_ELEMENT_LIST@52..84 + 0: HTML_CONTENT@52..59 + 0: HTML_LITERAL@52..59 "First:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@59..66 + 0: L_CURLY@59..60 "{" [] [] + 1: HTML_TEXT_EXPRESSION@60..65 + 0: HTML_LITERAL@60..65 "first" [] [] + 2: R_CURLY@65..66 "}" [] [] + 2: HTML_CONTENT@66..76 + 0: HTML_LITERAL@66..76 ", Second:" [] [Whitespace(" ")] + 3: HTML_SINGLE_TEXT_EXPRESSION@76..84 + 0: L_CURLY@76..77 "{" [] [] + 1: HTML_TEXT_EXPRESSION@77..83 + 0: HTML_LITERAL@77..83 "second" [] [] + 2: R_CURLY@83..84 "}" [] [] + 2: HTML_CLOSING_ELEMENT@84..88 + 0: L_ANGLE@84..85 "<" [] [] + 1: SLASH@85..86 "/" [] [] + 2: HTML_TAG_NAME@86..87 + 0: HTML_LITERAL@86..87 "p" [] [] + 3: R_ANGLE@87..88 ">" [] [] + 1: HTML_ELEMENT@88..121 + 0: HTML_OPENING_ELEMENT@88..94 + 0: L_ANGLE@88..92 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@92..93 + 0: HTML_LITERAL@92..93 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@93..93 + 3: R_ANGLE@93..94 ">" [] [] + 1: HTML_ELEMENT_LIST@94..117 + 0: HTML_CONTENT@94..100 + 0: HTML_LITERAL@94..100 "Rest:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@100..117 + 0: L_CURLY@100..101 "{" [] [] + 1: HTML_TEXT_EXPRESSION@101..116 + 0: HTML_LITERAL@101..116 "rest.join(', ')" [] [] + 2: R_CURLY@116..117 "}" [] [] + 2: HTML_CLOSING_ELEMENT@117..121 + 0: L_ANGLE@117..118 "<" [] [] + 1: SLASH@118..119 "/" [] [] + 2: HTML_TAG_NAME@119..120 + 0: HTML_LITERAL@119..120 "p" [] [] + 3: R_ANGLE@120..121 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@121..121 + 2: SVELTE_AWAIT_CLOSING_BLOCK@121..130 + 0: SV_CURLY_SLASH@121..124 "{/" [Newline("\n")] [] + 1: AWAIT_KW@124..129 "await" [] [] + 2: R_CURLY@129..130 "}" [] [] + 4: EOF@130..131 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_basic.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_basic.svelte new file mode 100644 index 000000000000..77d3a697c198 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_basic.svelte @@ -0,0 +1,3 @@ +{#await promise} +

Loading...

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_basic.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_basic.svelte.snap new file mode 100644 index 000000000000..2acd6ab4f7c6 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_basic.svelte.snap @@ -0,0 +1,112 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@36..39 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@39..44 "await" [] [], + r_curly_token: R_CURLY@44..45 "}" [] [], + }, + }, + ], + eof_token: EOF@45..46 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..46 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..45 + 0: SVELTE_AWAIT_BLOCK@0..45 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..36 + 2: SVELTE_AWAIT_CLOSING_BLOCK@36..45 + 0: SV_CURLY_SLASH@36..39 "{/" [Newline("\n")] [] + 1: AWAIT_KW@39..44 "await" [] [] + 2: R_CURLY@44..45 "}" [] [] + 4: EOF@45..46 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte new file mode 100644 index 000000000000..2fb1d49d8852 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte @@ -0,0 +1,3 @@ +{#await promise catch error} +

Error: {error.message}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte.snap new file mode 100644 index 000000000000..0a5337dc4a7b --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte.snap @@ -0,0 +1,132 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise catch error} +

Error: {error.message}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: missing (optional), + catch_clause: SvelteAwaitCatchClause { + catch_token: CATCH_KW@16..21 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@21..27 " error" [] [], + }, + }, + r_curly_token: R_CURLY@27..28 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@28..32 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@32..33 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@33..34 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@34..41 "Error:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@41..42 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@42..55 "error.message" [] [], + }, + r_curly_token: R_CURLY@55..56 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@56..57 "<" [] [], + slash_token: SLASH@57..58 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@58..59 "p" [] [], + }, + r_angle_token: R_ANGLE@59..60 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@60..63 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@63..68 "await" [] [], + r_curly_token: R_CURLY@68..69 "}" [] [], + }, + }, + ], + eof_token: EOF@69..70 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..70 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..69 + 0: SVELTE_AWAIT_BLOCK@0..69 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..60 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: (empty) + 4: SVELTE_AWAIT_CATCH_CLAUSE@16..27 + 0: CATCH_KW@16..21 "catch" [] [] + 1: HTML_TEXT_EXPRESSION@21..27 + 0: HTML_LITERAL@21..27 " error" [] [] + 5: R_CURLY@27..28 "}" [] [] + 6: HTML_ELEMENT_LIST@28..60 + 0: HTML_ELEMENT@28..60 + 0: HTML_OPENING_ELEMENT@28..34 + 0: L_ANGLE@28..32 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@32..33 + 0: HTML_LITERAL@32..33 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@33..33 + 3: R_ANGLE@33..34 ">" [] [] + 1: HTML_ELEMENT_LIST@34..56 + 0: HTML_CONTENT@34..41 + 0: HTML_LITERAL@34..41 "Error:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@41..56 + 0: L_CURLY@41..42 "{" [] [] + 1: HTML_TEXT_EXPRESSION@42..55 + 0: HTML_LITERAL@42..55 "error.message" [] [] + 2: R_CURLY@55..56 "}" [] [] + 2: HTML_CLOSING_ELEMENT@56..60 + 0: L_ANGLE@56..57 "<" [] [] + 1: SLASH@57..58 "/" [] [] + 2: HTML_TAG_NAME@58..59 + 0: HTML_LITERAL@58..59 "p" [] [] + 3: R_ANGLE@59..60 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@60..60 + 2: SVELTE_AWAIT_CLOSING_BLOCK@60..69 + 0: SV_CURLY_SLASH@60..63 "{/" [Newline("\n")] [] + 1: AWAIT_KW@63..68 "await" [] [] + 2: R_CURLY@68..69 "}" [] [] + 4: EOF@69..70 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte new file mode 100644 index 000000000000..df384522d348 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte @@ -0,0 +1,10 @@ +{#await fetchUser(userId).then(u => u.profile)} +

Loading user profile...

+{:then profile} +
+

{profile.name}

+

{profile.bio}

+
+{:catch error} +

Failed to load profile: {error.message}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte.snap new file mode 100644 index 000000000000..657b489dc43d --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte.snap @@ -0,0 +1,331 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await fetchUser(userId).then(u => u.profile)} +

Loading user profile...

+{:then profile} +
+

{profile.name}

+

{profile.bio}

+
+{:catch error} +

Failed to load profile: {error.message}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..46 " fetchUser(userId).then(u => u.profile)" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@46..47 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@47..51 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@51..52 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@52..53 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@53..76 "Loading user profile..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@76..77 "<" [] [], + slash_token: SLASH@77..78 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@78..79 "p" [] [], + }, + r_angle_token: R_ANGLE@79..80 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@80..83 "{:" [Newline("\n")] [], + then_token: THEN_KW@83..87 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@87..95 " profile" [] [], + }, + r_curly_token: R_CURLY@95..96 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@96..100 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@100..103 "div" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@103..104 ">" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@104..110 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@110..112 "h1" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@112..113 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@113..114 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@114..126 "profile.name" [] [], + }, + r_curly_token: R_CURLY@126..127 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@127..128 "<" [] [], + slash_token: SLASH@128..129 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@129..131 "h1" [] [], + }, + r_angle_token: R_ANGLE@131..132 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@132..138 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@138..139 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@139..140 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@140..141 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@141..152 "profile.bio" [] [], + }, + r_curly_token: R_CURLY@152..153 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@153..154 "<" [] [], + slash_token: SLASH@154..155 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@155..156 "p" [] [], + }, + r_angle_token: R_ANGLE@156..157 ">" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@157..161 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@161..162 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@162..165 "div" [] [], + }, + r_angle_token: R_ANGLE@165..166 ">" [] [], + }, + }, + ], + }, + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@166..169 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@169..174 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@174..180 " error" [] [], + }, + r_curly_token: R_CURLY@180..181 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@181..185 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@185..186 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@186..187 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@187..211 "Failed to load profile:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@211..212 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@212..225 "error.message" [] [], + }, + r_curly_token: R_CURLY@225..226 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@226..227 "<" [] [], + slash_token: SLASH@227..228 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@228..229 "p" [] [], + }, + r_angle_token: R_ANGLE@229..230 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@230..233 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@233..238 "await" [] [], + r_curly_token: R_CURLY@238..239 "}" [] [], + }, + }, + ], + eof_token: EOF@239..240 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..240 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..239 + 0: SVELTE_AWAIT_BLOCK@0..239 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..80 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..46 + 0: HTML_LITERAL@7..46 " fetchUser(userId).then(u => u.profile)" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@46..47 "}" [] [] + 6: HTML_ELEMENT_LIST@47..80 + 0: HTML_ELEMENT@47..80 + 0: HTML_OPENING_ELEMENT@47..53 + 0: L_ANGLE@47..51 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@51..52 + 0: HTML_LITERAL@51..52 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@52..52 + 3: R_ANGLE@52..53 ">" [] [] + 1: HTML_ELEMENT_LIST@53..76 + 0: HTML_CONTENT@53..76 + 0: HTML_LITERAL@53..76 "Loading user profile..." [] [] + 2: HTML_CLOSING_ELEMENT@76..80 + 0: L_ANGLE@76..77 "<" [] [] + 1: SLASH@77..78 "/" [] [] + 2: HTML_TAG_NAME@78..79 + 0: HTML_LITERAL@78..79 "p" [] [] + 3: R_ANGLE@79..80 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@80..230 + 0: SVELTE_AWAIT_THEN_BLOCK@80..166 + 0: SV_CURLY_COLON@80..83 "{:" [Newline("\n")] [] + 1: THEN_KW@83..87 "then" [] [] + 2: HTML_TEXT_EXPRESSION@87..95 + 0: HTML_LITERAL@87..95 " profile" [] [] + 3: R_CURLY@95..96 "}" [] [] + 4: HTML_ELEMENT_LIST@96..166 + 0: HTML_ELEMENT@96..166 + 0: HTML_OPENING_ELEMENT@96..104 + 0: L_ANGLE@96..100 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@100..103 + 0: HTML_LITERAL@100..103 "div" [] [] + 2: HTML_ATTRIBUTE_LIST@103..103 + 3: R_ANGLE@103..104 ">" [] [] + 1: HTML_ELEMENT_LIST@104..157 + 0: HTML_ELEMENT@104..132 + 0: HTML_OPENING_ELEMENT@104..113 + 0: L_ANGLE@104..110 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@110..112 + 0: HTML_LITERAL@110..112 "h1" [] [] + 2: HTML_ATTRIBUTE_LIST@112..112 + 3: R_ANGLE@112..113 ">" [] [] + 1: HTML_ELEMENT_LIST@113..127 + 0: HTML_SINGLE_TEXT_EXPRESSION@113..127 + 0: L_CURLY@113..114 "{" [] [] + 1: HTML_TEXT_EXPRESSION@114..126 + 0: HTML_LITERAL@114..126 "profile.name" [] [] + 2: R_CURLY@126..127 "}" [] [] + 2: HTML_CLOSING_ELEMENT@127..132 + 0: L_ANGLE@127..128 "<" [] [] + 1: SLASH@128..129 "/" [] [] + 2: HTML_TAG_NAME@129..131 + 0: HTML_LITERAL@129..131 "h1" [] [] + 3: R_ANGLE@131..132 ">" [] [] + 1: HTML_ELEMENT@132..157 + 0: HTML_OPENING_ELEMENT@132..140 + 0: L_ANGLE@132..138 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@138..139 + 0: HTML_LITERAL@138..139 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@139..139 + 3: R_ANGLE@139..140 ">" [] [] + 1: HTML_ELEMENT_LIST@140..153 + 0: HTML_SINGLE_TEXT_EXPRESSION@140..153 + 0: L_CURLY@140..141 "{" [] [] + 1: HTML_TEXT_EXPRESSION@141..152 + 0: HTML_LITERAL@141..152 "profile.bio" [] [] + 2: R_CURLY@152..153 "}" [] [] + 2: HTML_CLOSING_ELEMENT@153..157 + 0: L_ANGLE@153..154 "<" [] [] + 1: SLASH@154..155 "/" [] [] + 2: HTML_TAG_NAME@155..156 + 0: HTML_LITERAL@155..156 "p" [] [] + 3: R_ANGLE@156..157 ">" [] [] + 2: HTML_CLOSING_ELEMENT@157..166 + 0: L_ANGLE@157..161 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@161..162 "/" [] [] + 2: HTML_TAG_NAME@162..165 + 0: HTML_LITERAL@162..165 "div" [] [] + 3: R_ANGLE@165..166 ">" [] [] + 1: SVELTE_AWAIT_CATCH_BLOCK@166..230 + 0: SV_CURLY_COLON@166..169 "{:" [Newline("\n")] [] + 1: CATCH_KW@169..174 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@174..180 + 0: HTML_LITERAL@174..180 " error" [] [] + 3: R_CURLY@180..181 "}" [] [] + 4: HTML_ELEMENT_LIST@181..230 + 0: HTML_ELEMENT@181..230 + 0: HTML_OPENING_ELEMENT@181..187 + 0: L_ANGLE@181..185 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@185..186 + 0: HTML_LITERAL@185..186 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@186..186 + 3: R_ANGLE@186..187 ">" [] [] + 1: HTML_ELEMENT_LIST@187..226 + 0: HTML_CONTENT@187..211 + 0: HTML_LITERAL@187..211 "Failed to load profile:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@211..226 + 0: L_CURLY@211..212 "{" [] [] + 1: HTML_TEXT_EXPRESSION@212..225 + 0: HTML_LITERAL@212..225 "error.message" [] [] + 2: R_CURLY@225..226 "}" [] [] + 2: HTML_CLOSING_ELEMENT@226..230 + 0: L_ANGLE@226..227 "<" [] [] + 1: SLASH@227..228 "/" [] [] + 2: HTML_TAG_NAME@228..229 + 0: HTML_LITERAL@228..229 "p" [] [] + 3: R_ANGLE@229..230 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@230..239 + 0: SV_CURLY_SLASH@230..233 "{/" [Newline("\n")] [] + 1: AWAIT_KW@233..238 "await" [] [] + 2: R_CURLY@238..239 "}" [] [] + 4: EOF@239..240 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte new file mode 100644 index 000000000000..aee6d97408af --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte @@ -0,0 +1,7 @@ +{#await promise then { name, age, address }} +
+

Name: {name}

+

Age: {age}

+

Address: {address}

+
+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte.snap new file mode 100644 index 000000000000..d5204fe2c8d5 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte.snap @@ -0,0 +1,272 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise then { name, age, address }} +
+

Name: {name}

+

Age: {age}

+

Address: {address}

+
+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@16..20 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@20..43 " { name, age, address }" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@43..44 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@44..48 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@48..51 "div" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@51..52 ">" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@52..58 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@58..59 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@59..60 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@60..66 "Name:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@66..67 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@67..71 "name" [] [], + }, + r_curly_token: R_CURLY@71..72 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@72..73 "<" [] [], + slash_token: SLASH@73..74 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@74..75 "p" [] [], + }, + r_angle_token: R_ANGLE@75..76 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@76..82 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@82..83 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@83..84 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@84..89 "Age:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@89..90 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@90..93 "age" [] [], + }, + r_curly_token: R_CURLY@93..94 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@94..95 "<" [] [], + slash_token: SLASH@95..96 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@96..97 "p" [] [], + }, + r_angle_token: R_ANGLE@97..98 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@98..104 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@104..105 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@105..106 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@106..115 "Address:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@115..116 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@116..123 "address" [] [], + }, + r_curly_token: R_CURLY@123..124 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@124..125 "<" [] [], + slash_token: SLASH@125..126 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@126..127 "p" [] [], + }, + r_angle_token: R_ANGLE@127..128 ">" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@128..132 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@132..133 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@133..136 "div" [] [], + }, + r_angle_token: R_ANGLE@136..137 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@137..140 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@140..145 "await" [] [], + r_curly_token: R_CURLY@145..146 "}" [] [], + }, + }, + ], + eof_token: EOF@146..147 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..147 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..146 + 0: SVELTE_AWAIT_BLOCK@0..146 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..137 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@16..43 + 0: THEN_KW@16..20 "then" [] [] + 1: HTML_TEXT_EXPRESSION@20..43 + 0: HTML_LITERAL@20..43 " { name, age, address }" [] [] + 4: (empty) + 5: R_CURLY@43..44 "}" [] [] + 6: HTML_ELEMENT_LIST@44..137 + 0: HTML_ELEMENT@44..137 + 0: HTML_OPENING_ELEMENT@44..52 + 0: L_ANGLE@44..48 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@48..51 + 0: HTML_LITERAL@48..51 "div" [] [] + 2: HTML_ATTRIBUTE_LIST@51..51 + 3: R_ANGLE@51..52 ">" [] [] + 1: HTML_ELEMENT_LIST@52..128 + 0: HTML_ELEMENT@52..76 + 0: HTML_OPENING_ELEMENT@52..60 + 0: L_ANGLE@52..58 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@58..59 + 0: HTML_LITERAL@58..59 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@59..59 + 3: R_ANGLE@59..60 ">" [] [] + 1: HTML_ELEMENT_LIST@60..72 + 0: HTML_CONTENT@60..66 + 0: HTML_LITERAL@60..66 "Name:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@66..72 + 0: L_CURLY@66..67 "{" [] [] + 1: HTML_TEXT_EXPRESSION@67..71 + 0: HTML_LITERAL@67..71 "name" [] [] + 2: R_CURLY@71..72 "}" [] [] + 2: HTML_CLOSING_ELEMENT@72..76 + 0: L_ANGLE@72..73 "<" [] [] + 1: SLASH@73..74 "/" [] [] + 2: HTML_TAG_NAME@74..75 + 0: HTML_LITERAL@74..75 "p" [] [] + 3: R_ANGLE@75..76 ">" [] [] + 1: HTML_ELEMENT@76..98 + 0: HTML_OPENING_ELEMENT@76..84 + 0: L_ANGLE@76..82 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@82..83 + 0: HTML_LITERAL@82..83 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@83..83 + 3: R_ANGLE@83..84 ">" [] [] + 1: HTML_ELEMENT_LIST@84..94 + 0: HTML_CONTENT@84..89 + 0: HTML_LITERAL@84..89 "Age:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@89..94 + 0: L_CURLY@89..90 "{" [] [] + 1: HTML_TEXT_EXPRESSION@90..93 + 0: HTML_LITERAL@90..93 "age" [] [] + 2: R_CURLY@93..94 "}" [] [] + 2: HTML_CLOSING_ELEMENT@94..98 + 0: L_ANGLE@94..95 "<" [] [] + 1: SLASH@95..96 "/" [] [] + 2: HTML_TAG_NAME@96..97 + 0: HTML_LITERAL@96..97 "p" [] [] + 3: R_ANGLE@97..98 ">" [] [] + 2: HTML_ELEMENT@98..128 + 0: HTML_OPENING_ELEMENT@98..106 + 0: L_ANGLE@98..104 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@104..105 + 0: HTML_LITERAL@104..105 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@105..105 + 3: R_ANGLE@105..106 ">" [] [] + 1: HTML_ELEMENT_LIST@106..124 + 0: HTML_CONTENT@106..115 + 0: HTML_LITERAL@106..115 "Address:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@115..124 + 0: L_CURLY@115..116 "{" [] [] + 1: HTML_TEXT_EXPRESSION@116..123 + 0: HTML_LITERAL@116..123 "address" [] [] + 2: R_CURLY@123..124 "}" [] [] + 2: HTML_CLOSING_ELEMENT@124..128 + 0: L_ANGLE@124..125 "<" [] [] + 1: SLASH@125..126 "/" [] [] + 2: HTML_TAG_NAME@126..127 + 0: HTML_LITERAL@126..127 "p" [] [] + 3: R_ANGLE@127..128 ">" [] [] + 2: HTML_CLOSING_ELEMENT@128..137 + 0: L_ANGLE@128..132 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@132..133 "/" [] [] + 2: HTML_TAG_NAME@133..136 + 0: HTML_LITERAL@133..136 "div" [] [] + 3: R_ANGLE@136..137 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@137..137 + 2: SVELTE_AWAIT_CLOSING_BLOCK@137..146 + 0: SV_CURLY_SLASH@137..140 "{/" [Newline("\n")] [] + 1: AWAIT_KW@140..145 "await" [] [] + 2: R_CURLY@145..146 "}" [] [] + 4: EOF@146..147 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte new file mode 100644 index 000000000000..1ed0f41c7765 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte @@ -0,0 +1,3 @@ +{#await import('./Component.svelte') then { default: Component }} + +{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte.snap new file mode 100644 index 000000000000..8345f2076904 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte.snap @@ -0,0 +1,97 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await import('./Component.svelte') then { default: Component }} + +{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..37 " import('./Component.svelte') " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@37..41 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@41..64 " { default: Component }" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@64..65 "}" [] [], + children: HtmlElementList [ + HtmlSelfClosingElement { + l_angle_token: L_ANGLE@65..69 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@69..79 "Component" [] [Whitespace(" ")], + }, + attributes: HtmlAttributeList [], + slash_token: SLASH@79..80 "/" [] [], + r_angle_token: R_ANGLE@80..81 ">" [] [], + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@81..84 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@84..89 "await" [] [], + r_curly_token: R_CURLY@89..90 "}" [] [], + }, + }, + ], + eof_token: EOF@90..91 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..91 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..90 + 0: SVELTE_AWAIT_BLOCK@0..90 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..81 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..37 + 0: HTML_LITERAL@7..37 " import('./Component.svelte') " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@37..64 + 0: THEN_KW@37..41 "then" [] [] + 1: HTML_TEXT_EXPRESSION@41..64 + 0: HTML_LITERAL@41..64 " { default: Component }" [] [] + 4: (empty) + 5: R_CURLY@64..65 "}" [] [] + 6: HTML_ELEMENT_LIST@65..81 + 0: HTML_SELF_CLOSING_ELEMENT@65..81 + 0: L_ANGLE@65..69 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@69..79 + 0: HTML_LITERAL@69..79 "Component" [] [Whitespace(" ")] + 2: HTML_ATTRIBUTE_LIST@79..79 + 3: SLASH@79..80 "/" [] [] + 4: R_ANGLE@80..81 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@81..81 + 2: SVELTE_AWAIT_CLOSING_BLOCK@81..90 + 0: SV_CURLY_SLASH@81..84 "{/" [Newline("\n")] [] + 1: AWAIT_KW@84..89 "await" [] [] + 2: R_CURLY@89..90 "}" [] [] + 4: EOF@90..91 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte new file mode 100644 index 000000000000..d63056249b88 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte @@ -0,0 +1,17 @@ +{#await promise} +
+ +

Please wait while we load your data...

+
+{:then data} +
+

Success!

+
{JSON.stringify(data, null, 2)}
+
+{:catch error} +
+

Error

+

{error.message}

+ +
+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte.snap new file mode 100644 index 000000000000..deac9df2beba --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte.snap @@ -0,0 +1,600 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +
+ +

Please wait while we load your data...

+
+{:then data} +
+

Success!

+
{JSON.stringify(data, null, 2)}
+
+{:catch error} +
+

Error

+

{error.message}

+ +
+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..24 "div" [] [Whitespace(" ")], + }, + attributes: HtmlAttributeList [ + HtmlAttribute { + name: HtmlAttributeName { + value_token: HTML_LITERAL@24..29 "class" [] [], + }, + initializer: HtmlAttributeInitializerClause { + eq_token: EQ@29..30 "=" [] [], + value: HtmlString { + value_token: HTML_STRING_LITERAL@30..39 "\"loading\"" [] [], + }, + }, + }, + ], + r_angle_token: R_ANGLE@39..40 ">" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@40..46 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@46..51 "span" [] [Whitespace(" ")], + }, + attributes: HtmlAttributeList [ + HtmlAttribute { + name: HtmlAttributeName { + value_token: HTML_LITERAL@51..56 "class" [] [], + }, + initializer: HtmlAttributeInitializerClause { + eq_token: EQ@56..57 "=" [] [], + value: HtmlString { + value_token: HTML_STRING_LITERAL@57..66 "\"spinner\"" [] [], + }, + }, + }, + ], + r_angle_token: R_ANGLE@66..67 ">" [] [], + }, + children: HtmlElementList [], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@67..68 "<" [] [], + slash_token: SLASH@68..69 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@69..73 "span" [] [], + }, + r_angle_token: R_ANGLE@73..74 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@74..80 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@80..81 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@81..82 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@82..120 "Please wait while we load your data..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@120..121 "<" [] [], + slash_token: SLASH@121..122 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@122..123 "p" [] [], + }, + r_angle_token: R_ANGLE@123..124 ">" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@124..128 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@128..129 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@129..132 "div" [] [], + }, + r_angle_token: R_ANGLE@132..133 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@133..136 "{:" [Newline("\n")] [], + then_token: THEN_KW@136..140 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@140..145 " data" [] [], + }, + r_curly_token: R_CURLY@145..146 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@146..150 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@150..154 "div" [] [Whitespace(" ")], + }, + attributes: HtmlAttributeList [ + HtmlAttribute { + name: HtmlAttributeName { + value_token: HTML_LITERAL@154..159 "class" [] [], + }, + initializer: HtmlAttributeInitializerClause { + eq_token: EQ@159..160 "=" [] [], + value: HtmlString { + value_token: HTML_STRING_LITERAL@160..169 "\"success\"" [] [], + }, + }, + }, + ], + r_angle_token: R_ANGLE@169..170 ">" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@170..176 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@176..178 "h2" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@178..179 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@179..187 "Success!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@187..188 "<" [] [], + slash_token: SLASH@188..189 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@189..191 "h2" [] [], + }, + r_angle_token: R_ANGLE@191..192 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@192..198 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@198..201 "pre" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@201..202 ">" [] [], + }, + children: HtmlElementList [ + HtmlEmbeddedContent { + value_token: HTML_LITERAL@202..233 "{JSON.stringify(data, null, 2)}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@233..234 "<" [] [], + slash_token: SLASH@234..235 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@235..238 "pre" [] [], + }, + r_angle_token: R_ANGLE@238..239 ">" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@239..243 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@243..244 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@244..247 "div" [] [], + }, + r_angle_token: R_ANGLE@247..248 ">" [] [], + }, + }, + ], + }, + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@248..251 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@251..256 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@256..262 " error" [] [], + }, + r_curly_token: R_CURLY@262..263 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@263..267 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@267..271 "div" [] [Whitespace(" ")], + }, + attributes: HtmlAttributeList [ + HtmlAttribute { + name: HtmlAttributeName { + value_token: HTML_LITERAL@271..276 "class" [] [], + }, + initializer: HtmlAttributeInitializerClause { + eq_token: EQ@276..277 "=" [] [], + value: HtmlString { + value_token: HTML_STRING_LITERAL@277..284 "\"error\"" [] [], + }, + }, + }, + ], + r_angle_token: R_ANGLE@284..285 ">" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@285..291 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@291..293 "h2" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@293..294 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@294..299 "Error" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@299..300 "<" [] [], + slash_token: SLASH@300..301 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@301..303 "h2" [] [], + }, + r_angle_token: R_ANGLE@303..304 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@304..310 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@310..311 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@311..312 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@312..313 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@313..326 "error.message" [] [], + }, + r_curly_token: R_CURLY@326..327 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@327..328 "<" [] [], + slash_token: SLASH@328..329 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@329..330 "p" [] [], + }, + r_angle_token: R_ANGLE@330..331 ">" [] [], + }, + }, + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@331..337 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@337..344 "button" [] [Whitespace(" ")], + }, + attributes: HtmlAttributeList [ + HtmlAttribute { + name: HtmlAttributeName { + value_token: HTML_LITERAL@344..352 "on:click" [] [], + }, + initializer: HtmlAttributeInitializerClause { + eq_token: EQ@352..353 "=" [] [], + value: HtmlSingleTextExpression { + l_curly_token: L_CURLY@353..354 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@354..359 "retry" [] [], + }, + r_curly_token: R_CURLY@359..360 "}" [] [], + }, + }, + }, + ], + r_angle_token: R_ANGLE@360..361 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@361..366 "Retry" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@366..367 "<" [] [], + slash_token: SLASH@367..368 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@368..374 "button" [] [], + }, + r_angle_token: R_ANGLE@374..375 ">" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@375..379 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@379..380 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@380..383 "div" [] [], + }, + r_angle_token: R_ANGLE@383..384 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@384..387 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@387..392 "await" [] [], + r_curly_token: R_CURLY@392..393 "}" [] [], + }, + }, + ], + eof_token: EOF@393..394 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..394 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..393 + 0: SVELTE_AWAIT_BLOCK@0..393 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..133 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..133 + 0: HTML_ELEMENT@16..133 + 0: HTML_OPENING_ELEMENT@16..40 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..24 + 0: HTML_LITERAL@20..24 "div" [] [Whitespace(" ")] + 2: HTML_ATTRIBUTE_LIST@24..39 + 0: HTML_ATTRIBUTE@24..39 + 0: HTML_ATTRIBUTE_NAME@24..29 + 0: HTML_LITERAL@24..29 "class" [] [] + 1: HTML_ATTRIBUTE_INITIALIZER_CLAUSE@29..39 + 0: EQ@29..30 "=" [] [] + 1: HTML_STRING@30..39 + 0: HTML_STRING_LITERAL@30..39 "\"loading\"" [] [] + 3: R_ANGLE@39..40 ">" [] [] + 1: HTML_ELEMENT_LIST@40..124 + 0: HTML_ELEMENT@40..74 + 0: HTML_OPENING_ELEMENT@40..67 + 0: L_ANGLE@40..46 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@46..51 + 0: HTML_LITERAL@46..51 "span" [] [Whitespace(" ")] + 2: HTML_ATTRIBUTE_LIST@51..66 + 0: HTML_ATTRIBUTE@51..66 + 0: HTML_ATTRIBUTE_NAME@51..56 + 0: HTML_LITERAL@51..56 "class" [] [] + 1: HTML_ATTRIBUTE_INITIALIZER_CLAUSE@56..66 + 0: EQ@56..57 "=" [] [] + 1: HTML_STRING@57..66 + 0: HTML_STRING_LITERAL@57..66 "\"spinner\"" [] [] + 3: R_ANGLE@66..67 ">" [] [] + 1: HTML_ELEMENT_LIST@67..67 + 2: HTML_CLOSING_ELEMENT@67..74 + 0: L_ANGLE@67..68 "<" [] [] + 1: SLASH@68..69 "/" [] [] + 2: HTML_TAG_NAME@69..73 + 0: HTML_LITERAL@69..73 "span" [] [] + 3: R_ANGLE@73..74 ">" [] [] + 1: HTML_ELEMENT@74..124 + 0: HTML_OPENING_ELEMENT@74..82 + 0: L_ANGLE@74..80 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@80..81 + 0: HTML_LITERAL@80..81 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@81..81 + 3: R_ANGLE@81..82 ">" [] [] + 1: HTML_ELEMENT_LIST@82..120 + 0: HTML_CONTENT@82..120 + 0: HTML_LITERAL@82..120 "Please wait while we load your data..." [] [] + 2: HTML_CLOSING_ELEMENT@120..124 + 0: L_ANGLE@120..121 "<" [] [] + 1: SLASH@121..122 "/" [] [] + 2: HTML_TAG_NAME@122..123 + 0: HTML_LITERAL@122..123 "p" [] [] + 3: R_ANGLE@123..124 ">" [] [] + 2: HTML_CLOSING_ELEMENT@124..133 + 0: L_ANGLE@124..128 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@128..129 "/" [] [] + 2: HTML_TAG_NAME@129..132 + 0: HTML_LITERAL@129..132 "div" [] [] + 3: R_ANGLE@132..133 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@133..384 + 0: SVELTE_AWAIT_THEN_BLOCK@133..248 + 0: SV_CURLY_COLON@133..136 "{:" [Newline("\n")] [] + 1: THEN_KW@136..140 "then" [] [] + 2: HTML_TEXT_EXPRESSION@140..145 + 0: HTML_LITERAL@140..145 " data" [] [] + 3: R_CURLY@145..146 "}" [] [] + 4: HTML_ELEMENT_LIST@146..248 + 0: HTML_ELEMENT@146..248 + 0: HTML_OPENING_ELEMENT@146..170 + 0: L_ANGLE@146..150 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@150..154 + 0: HTML_LITERAL@150..154 "div" [] [Whitespace(" ")] + 2: HTML_ATTRIBUTE_LIST@154..169 + 0: HTML_ATTRIBUTE@154..169 + 0: HTML_ATTRIBUTE_NAME@154..159 + 0: HTML_LITERAL@154..159 "class" [] [] + 1: HTML_ATTRIBUTE_INITIALIZER_CLAUSE@159..169 + 0: EQ@159..160 "=" [] [] + 1: HTML_STRING@160..169 + 0: HTML_STRING_LITERAL@160..169 "\"success\"" [] [] + 3: R_ANGLE@169..170 ">" [] [] + 1: HTML_ELEMENT_LIST@170..239 + 0: HTML_ELEMENT@170..192 + 0: HTML_OPENING_ELEMENT@170..179 + 0: L_ANGLE@170..176 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@176..178 + 0: HTML_LITERAL@176..178 "h2" [] [] + 2: HTML_ATTRIBUTE_LIST@178..178 + 3: R_ANGLE@178..179 ">" [] [] + 1: HTML_ELEMENT_LIST@179..187 + 0: HTML_CONTENT@179..187 + 0: HTML_LITERAL@179..187 "Success!" [] [] + 2: HTML_CLOSING_ELEMENT@187..192 + 0: L_ANGLE@187..188 "<" [] [] + 1: SLASH@188..189 "/" [] [] + 2: HTML_TAG_NAME@189..191 + 0: HTML_LITERAL@189..191 "h2" [] [] + 3: R_ANGLE@191..192 ">" [] [] + 1: HTML_ELEMENT@192..239 + 0: HTML_OPENING_ELEMENT@192..202 + 0: L_ANGLE@192..198 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@198..201 + 0: HTML_LITERAL@198..201 "pre" [] [] + 2: HTML_ATTRIBUTE_LIST@201..201 + 3: R_ANGLE@201..202 ">" [] [] + 1: HTML_ELEMENT_LIST@202..233 + 0: HTML_EMBEDDED_CONTENT@202..233 + 0: HTML_LITERAL@202..233 "{JSON.stringify(data, null, 2)}" [] [] + 2: HTML_CLOSING_ELEMENT@233..239 + 0: L_ANGLE@233..234 "<" [] [] + 1: SLASH@234..235 "/" [] [] + 2: HTML_TAG_NAME@235..238 + 0: HTML_LITERAL@235..238 "pre" [] [] + 3: R_ANGLE@238..239 ">" [] [] + 2: HTML_CLOSING_ELEMENT@239..248 + 0: L_ANGLE@239..243 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@243..244 "/" [] [] + 2: HTML_TAG_NAME@244..247 + 0: HTML_LITERAL@244..247 "div" [] [] + 3: R_ANGLE@247..248 ">" [] [] + 1: SVELTE_AWAIT_CATCH_BLOCK@248..384 + 0: SV_CURLY_COLON@248..251 "{:" [Newline("\n")] [] + 1: CATCH_KW@251..256 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@256..262 + 0: HTML_LITERAL@256..262 " error" [] [] + 3: R_CURLY@262..263 "}" [] [] + 4: HTML_ELEMENT_LIST@263..384 + 0: HTML_ELEMENT@263..384 + 0: HTML_OPENING_ELEMENT@263..285 + 0: L_ANGLE@263..267 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@267..271 + 0: HTML_LITERAL@267..271 "div" [] [Whitespace(" ")] + 2: HTML_ATTRIBUTE_LIST@271..284 + 0: HTML_ATTRIBUTE@271..284 + 0: HTML_ATTRIBUTE_NAME@271..276 + 0: HTML_LITERAL@271..276 "class" [] [] + 1: HTML_ATTRIBUTE_INITIALIZER_CLAUSE@276..284 + 0: EQ@276..277 "=" [] [] + 1: HTML_STRING@277..284 + 0: HTML_STRING_LITERAL@277..284 "\"error\"" [] [] + 3: R_ANGLE@284..285 ">" [] [] + 1: HTML_ELEMENT_LIST@285..375 + 0: HTML_ELEMENT@285..304 + 0: HTML_OPENING_ELEMENT@285..294 + 0: L_ANGLE@285..291 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@291..293 + 0: HTML_LITERAL@291..293 "h2" [] [] + 2: HTML_ATTRIBUTE_LIST@293..293 + 3: R_ANGLE@293..294 ">" [] [] + 1: HTML_ELEMENT_LIST@294..299 + 0: HTML_CONTENT@294..299 + 0: HTML_LITERAL@294..299 "Error" [] [] + 2: HTML_CLOSING_ELEMENT@299..304 + 0: L_ANGLE@299..300 "<" [] [] + 1: SLASH@300..301 "/" [] [] + 2: HTML_TAG_NAME@301..303 + 0: HTML_LITERAL@301..303 "h2" [] [] + 3: R_ANGLE@303..304 ">" [] [] + 1: HTML_ELEMENT@304..331 + 0: HTML_OPENING_ELEMENT@304..312 + 0: L_ANGLE@304..310 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@310..311 + 0: HTML_LITERAL@310..311 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@311..311 + 3: R_ANGLE@311..312 ">" [] [] + 1: HTML_ELEMENT_LIST@312..327 + 0: HTML_SINGLE_TEXT_EXPRESSION@312..327 + 0: L_CURLY@312..313 "{" [] [] + 1: HTML_TEXT_EXPRESSION@313..326 + 0: HTML_LITERAL@313..326 "error.message" [] [] + 2: R_CURLY@326..327 "}" [] [] + 2: HTML_CLOSING_ELEMENT@327..331 + 0: L_ANGLE@327..328 "<" [] [] + 1: SLASH@328..329 "/" [] [] + 2: HTML_TAG_NAME@329..330 + 0: HTML_LITERAL@329..330 "p" [] [] + 3: R_ANGLE@330..331 ">" [] [] + 2: HTML_ELEMENT@331..375 + 0: HTML_OPENING_ELEMENT@331..361 + 0: L_ANGLE@331..337 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@337..344 + 0: HTML_LITERAL@337..344 "button" [] [Whitespace(" ")] + 2: HTML_ATTRIBUTE_LIST@344..360 + 0: HTML_ATTRIBUTE@344..360 + 0: HTML_ATTRIBUTE_NAME@344..352 + 0: HTML_LITERAL@344..352 "on:click" [] [] + 1: HTML_ATTRIBUTE_INITIALIZER_CLAUSE@352..360 + 0: EQ@352..353 "=" [] [] + 1: HTML_SINGLE_TEXT_EXPRESSION@353..360 + 0: L_CURLY@353..354 "{" [] [] + 1: HTML_TEXT_EXPRESSION@354..359 + 0: HTML_LITERAL@354..359 "retry" [] [] + 2: R_CURLY@359..360 "}" [] [] + 3: R_ANGLE@360..361 ">" [] [] + 1: HTML_ELEMENT_LIST@361..366 + 0: HTML_CONTENT@361..366 + 0: HTML_LITERAL@361..366 "Retry" [] [] + 2: HTML_CLOSING_ELEMENT@366..375 + 0: L_ANGLE@366..367 "<" [] [] + 1: SLASH@367..368 "/" [] [] + 2: HTML_TAG_NAME@368..374 + 0: HTML_LITERAL@368..374 "button" [] [] + 3: R_ANGLE@374..375 ">" [] [] + 2: HTML_CLOSING_ELEMENT@375..384 + 0: L_ANGLE@375..379 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@379..380 "/" [] [] + 2: HTML_TAG_NAME@380..383 + 0: HTML_LITERAL@380..383 "div" [] [] + 3: R_ANGLE@383..384 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@384..393 + 0: SV_CURLY_SLASH@384..387 "{/" [Newline("\n")] [] + 1: AWAIT_KW@387..392 "await" [] [] + 2: R_CURLY@392..393 "}" [] [] + 4: EOF@393..394 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte new file mode 100644 index 000000000000..56bfe71bb0da --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte @@ -0,0 +1,16 @@ +{#await userPromise} +

Loading user...

+{:then user} +
+

{user.name}

+ {#await user.postsPromise then posts} +
    + {#each posts as post} +
  • {post.title}
  • + {/each} +
+ {/await} +
+{:catch error} +

Error: {error.message}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte.snap new file mode 100644 index 000000000000..1d5713f551a0 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte.snap @@ -0,0 +1,459 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await userPromise} +

Loading user...

+{:then user} +
+

{user.name}

+ {#await user.postsPromise then posts} +
    + {#each posts as post} +
  • {post.title}
  • + {/each} +
+ {/await} +
+{:catch error} +

Error: {error.message}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..19 " userPromise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@19..20 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@20..24 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@24..25 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@25..26 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@26..41 "Loading user..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@41..42 "<" [] [], + slash_token: SLASH@42..43 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@43..44 "p" [] [], + }, + r_angle_token: R_ANGLE@44..45 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@45..48 "{:" [Newline("\n")] [], + then_token: THEN_KW@48..52 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@52..57 " user" [] [], + }, + r_curly_token: R_CURLY@57..58 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@58..62 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@62..65 "div" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@65..66 ">" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@66..72 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@72..74 "h1" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@74..75 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@75..76 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@76..85 "user.name" [] [], + }, + r_curly_token: R_CURLY@85..86 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@86..87 "<" [] [], + slash_token: SLASH@87..88 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@88..90 "h1" [] [], + }, + r_angle_token: R_ANGLE@90..91 ">" [] [], + }, + }, + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@91..98 "{#" [Newline("\n"), Whitespace(" ")] [], + await_token: AWAIT_KW@98..103 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@103..122 " user.postsPromise " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@122..126 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@126..132 " posts" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@132..133 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@133..141 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@141..143 "ul" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@143..144 ">" [] [], + }, + children: HtmlElementList [ + SvelteEachBlock { + opening_block: SvelteEachOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@144..155 "{#" [Newline("\n"), Whitespace(" ")] [], + each_token: EACH_KW@155..159 "each" [] [], + list: HtmlTextExpression { + html_literal_token: HTML_LITERAL@159..166 " posts " [] [], + }, + item: SvelteEachAsKeyedItem { + as_token: AS_KW@166..168 "as" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@168..173 " post" [] [], + }, + index: missing (optional), + key: missing (optional), + }, + r_curly_token: R_CURLY@173..174 "}" [] [], + }, + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@174..186 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@186..188 "li" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@188..189 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@189..190 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@190..200 "post.title" [] [], + }, + r_curly_token: R_CURLY@200..201 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@201..202 "<" [] [], + slash_token: SLASH@202..203 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@203..205 "li" [] [], + }, + r_angle_token: R_ANGLE@205..206 ">" [] [], + }, + }, + ], + else_clause: missing (optional), + closing_block: SvelteEachClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@206..217 "{/" [Newline("\n"), Whitespace(" ")] [], + each_token: EACH_KW@217..221 "each" [] [], + r_curly_token: R_CURLY@221..222 "}" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@222..230 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@230..231 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@231..233 "ul" [] [], + }, + r_angle_token: R_ANGLE@233..234 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@234..241 "{/" [Newline("\n"), Whitespace(" ")] [], + await_token: AWAIT_KW@241..246 "await" [] [], + r_curly_token: R_CURLY@246..247 "}" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@247..251 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@251..252 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@252..255 "div" [] [], + }, + r_angle_token: R_ANGLE@255..256 ">" [] [], + }, + }, + ], + }, + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@256..259 "{:" [Newline("\n")] [], + catch_token: CATCH_KW@259..264 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@264..270 " error" [] [], + }, + r_curly_token: R_CURLY@270..271 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@271..275 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@275..276 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@276..277 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@277..284 "Error:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@284..285 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@285..298 "error.message" [] [], + }, + r_curly_token: R_CURLY@298..299 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@299..300 "<" [] [], + slash_token: SLASH@300..301 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@301..302 "p" [] [], + }, + r_angle_token: R_ANGLE@302..303 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@303..306 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@306..311 "await" [] [], + r_curly_token: R_CURLY@311..312 "}" [] [], + }, + }, + ], + eof_token: EOF@312..313 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..313 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..312 + 0: SVELTE_AWAIT_BLOCK@0..312 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..45 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..19 + 0: HTML_LITERAL@7..19 " userPromise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@19..20 "}" [] [] + 6: HTML_ELEMENT_LIST@20..45 + 0: HTML_ELEMENT@20..45 + 0: HTML_OPENING_ELEMENT@20..26 + 0: L_ANGLE@20..24 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@24..25 + 0: HTML_LITERAL@24..25 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@25..25 + 3: R_ANGLE@25..26 ">" [] [] + 1: HTML_ELEMENT_LIST@26..41 + 0: HTML_CONTENT@26..41 + 0: HTML_LITERAL@26..41 "Loading user..." [] [] + 2: HTML_CLOSING_ELEMENT@41..45 + 0: L_ANGLE@41..42 "<" [] [] + 1: SLASH@42..43 "/" [] [] + 2: HTML_TAG_NAME@43..44 + 0: HTML_LITERAL@43..44 "p" [] [] + 3: R_ANGLE@44..45 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@45..303 + 0: SVELTE_AWAIT_THEN_BLOCK@45..256 + 0: SV_CURLY_COLON@45..48 "{:" [Newline("\n")] [] + 1: THEN_KW@48..52 "then" [] [] + 2: HTML_TEXT_EXPRESSION@52..57 + 0: HTML_LITERAL@52..57 " user" [] [] + 3: R_CURLY@57..58 "}" [] [] + 4: HTML_ELEMENT_LIST@58..256 + 0: HTML_ELEMENT@58..256 + 0: HTML_OPENING_ELEMENT@58..66 + 0: L_ANGLE@58..62 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@62..65 + 0: HTML_LITERAL@62..65 "div" [] [] + 2: HTML_ATTRIBUTE_LIST@65..65 + 3: R_ANGLE@65..66 ">" [] [] + 1: HTML_ELEMENT_LIST@66..247 + 0: HTML_ELEMENT@66..91 + 0: HTML_OPENING_ELEMENT@66..75 + 0: L_ANGLE@66..72 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@72..74 + 0: HTML_LITERAL@72..74 "h1" [] [] + 2: HTML_ATTRIBUTE_LIST@74..74 + 3: R_ANGLE@74..75 ">" [] [] + 1: HTML_ELEMENT_LIST@75..86 + 0: HTML_SINGLE_TEXT_EXPRESSION@75..86 + 0: L_CURLY@75..76 "{" [] [] + 1: HTML_TEXT_EXPRESSION@76..85 + 0: HTML_LITERAL@76..85 "user.name" [] [] + 2: R_CURLY@85..86 "}" [] [] + 2: HTML_CLOSING_ELEMENT@86..91 + 0: L_ANGLE@86..87 "<" [] [] + 1: SLASH@87..88 "/" [] [] + 2: HTML_TAG_NAME@88..90 + 0: HTML_LITERAL@88..90 "h1" [] [] + 3: R_ANGLE@90..91 ">" [] [] + 1: SVELTE_AWAIT_BLOCK@91..247 + 0: SVELTE_AWAIT_OPENING_BLOCK@91..234 + 0: SV_CURLY_HASH@91..98 "{#" [Newline("\n"), Whitespace(" ")] [] + 1: AWAIT_KW@98..103 "await" [] [] + 2: HTML_TEXT_EXPRESSION@103..122 + 0: HTML_LITERAL@103..122 " user.postsPromise " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@122..132 + 0: THEN_KW@122..126 "then" [] [] + 1: HTML_TEXT_EXPRESSION@126..132 + 0: HTML_LITERAL@126..132 " posts" [] [] + 4: (empty) + 5: R_CURLY@132..133 "}" [] [] + 6: HTML_ELEMENT_LIST@133..234 + 0: HTML_ELEMENT@133..234 + 0: HTML_OPENING_ELEMENT@133..144 + 0: L_ANGLE@133..141 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@141..143 + 0: HTML_LITERAL@141..143 "ul" [] [] + 2: HTML_ATTRIBUTE_LIST@143..143 + 3: R_ANGLE@143..144 ">" [] [] + 1: HTML_ELEMENT_LIST@144..222 + 0: SVELTE_EACH_BLOCK@144..222 + 0: SVELTE_EACH_OPENING_BLOCK@144..174 + 0: SV_CURLY_HASH@144..155 "{#" [Newline("\n"), Whitespace(" ")] [] + 1: EACH_KW@155..159 "each" [] [] + 2: HTML_TEXT_EXPRESSION@159..166 + 0: HTML_LITERAL@159..166 " posts " [] [] + 3: SVELTE_EACH_AS_KEYED_ITEM@166..173 + 0: AS_KW@166..168 "as" [] [] + 1: HTML_TEXT_EXPRESSION@168..173 + 0: HTML_LITERAL@168..173 " post" [] [] + 2: (empty) + 3: (empty) + 4: R_CURLY@173..174 "}" [] [] + 1: HTML_ELEMENT_LIST@174..206 + 0: HTML_ELEMENT@174..206 + 0: HTML_OPENING_ELEMENT@174..189 + 0: L_ANGLE@174..186 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@186..188 + 0: HTML_LITERAL@186..188 "li" [] [] + 2: HTML_ATTRIBUTE_LIST@188..188 + 3: R_ANGLE@188..189 ">" [] [] + 1: HTML_ELEMENT_LIST@189..201 + 0: HTML_SINGLE_TEXT_EXPRESSION@189..201 + 0: L_CURLY@189..190 "{" [] [] + 1: HTML_TEXT_EXPRESSION@190..200 + 0: HTML_LITERAL@190..200 "post.title" [] [] + 2: R_CURLY@200..201 "}" [] [] + 2: HTML_CLOSING_ELEMENT@201..206 + 0: L_ANGLE@201..202 "<" [] [] + 1: SLASH@202..203 "/" [] [] + 2: HTML_TAG_NAME@203..205 + 0: HTML_LITERAL@203..205 "li" [] [] + 3: R_ANGLE@205..206 ">" [] [] + 2: (empty) + 3: SVELTE_EACH_CLOSING_BLOCK@206..222 + 0: SV_CURLY_SLASH@206..217 "{/" [Newline("\n"), Whitespace(" ")] [] + 1: EACH_KW@217..221 "each" [] [] + 2: R_CURLY@221..222 "}" [] [] + 2: HTML_CLOSING_ELEMENT@222..234 + 0: L_ANGLE@222..230 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@230..231 "/" [] [] + 2: HTML_TAG_NAME@231..233 + 0: HTML_LITERAL@231..233 "ul" [] [] + 3: R_ANGLE@233..234 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@234..234 + 2: SVELTE_AWAIT_CLOSING_BLOCK@234..247 + 0: SV_CURLY_SLASH@234..241 "{/" [Newline("\n"), Whitespace(" ")] [] + 1: AWAIT_KW@241..246 "await" [] [] + 2: R_CURLY@246..247 "}" [] [] + 2: HTML_CLOSING_ELEMENT@247..256 + 0: L_ANGLE@247..251 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@251..252 "/" [] [] + 2: HTML_TAG_NAME@252..255 + 0: HTML_LITERAL@252..255 "div" [] [] + 3: R_ANGLE@255..256 ">" [] [] + 1: SVELTE_AWAIT_CATCH_BLOCK@256..303 + 0: SV_CURLY_COLON@256..259 "{:" [Newline("\n")] [] + 1: CATCH_KW@259..264 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@264..270 + 0: HTML_LITERAL@264..270 " error" [] [] + 3: R_CURLY@270..271 "}" [] [] + 4: HTML_ELEMENT_LIST@271..303 + 0: HTML_ELEMENT@271..303 + 0: HTML_OPENING_ELEMENT@271..277 + 0: L_ANGLE@271..275 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@275..276 + 0: HTML_LITERAL@275..276 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@276..276 + 3: R_ANGLE@276..277 ">" [] [] + 1: HTML_ELEMENT_LIST@277..299 + 0: HTML_CONTENT@277..284 + 0: HTML_LITERAL@277..284 "Error:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@284..299 + 0: L_CURLY@284..285 "{" [] [] + 1: HTML_TEXT_EXPRESSION@285..298 + 0: HTML_LITERAL@285..298 "error.message" [] [] + 2: R_CURLY@298..299 "}" [] [] + 2: HTML_CLOSING_ELEMENT@299..303 + 0: L_ANGLE@299..300 "<" [] [] + 1: SLASH@300..301 "/" [] [] + 2: HTML_TAG_NAME@301..302 + 0: HTML_LITERAL@301..302 "p" [] [] + 3: R_ANGLE@302..303 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@303..312 + 0: SV_CURLY_SLASH@303..306 "{/" [Newline("\n")] [] + 1: AWAIT_KW@306..311 "await" [] [] + 2: R_CURLY@311..312 "}" [] [] + 4: EOF@312..313 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte new file mode 100644 index 000000000000..651c19df9421 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte @@ -0,0 +1,5 @@ +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte.snap new file mode 100644 index 000000000000..8cab1ad882d7 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte.snap @@ -0,0 +1,183 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise} +

Loading...

+{:then value} +

The value is {value}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..15 " promise" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@15..16 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@20..21 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@21..22 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@22..32 "Loading..." [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [], + then_token: THEN_KW@39..43 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@43..49 " value" [] [], + }, + r_curly_token: R_CURLY@49..50 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@54..55 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@55..56 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@56..69 "The value is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@69..70 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@70..75 "value" [] [], + }, + r_curly_token: R_CURLY@75..76 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@76..77 "<" [] [], + slash_token: SLASH@77..78 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@78..79 "p" [] [], + }, + r_angle_token: R_ANGLE@79..80 ">" [] [], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@80..83 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@83..88 "await" [] [], + r_curly_token: R_CURLY@88..89 "}" [] [], + }, + }, + ], + eof_token: EOF@89..90 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..90 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..89 + 0: SVELTE_AWAIT_BLOCK@0..89 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..36 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..15 + 0: HTML_LITERAL@7..15 " promise" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@15..16 "}" [] [] + 6: HTML_ELEMENT_LIST@16..36 + 0: HTML_ELEMENT@16..36 + 0: HTML_OPENING_ELEMENT@16..22 + 0: L_ANGLE@16..20 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@20..21 + 0: HTML_LITERAL@20..21 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@21..21 + 3: R_ANGLE@21..22 ">" [] [] + 1: HTML_ELEMENT_LIST@22..32 + 0: HTML_CONTENT@22..32 + 0: HTML_LITERAL@22..32 "Loading..." [] [] + 2: HTML_CLOSING_ELEMENT@32..36 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 3: R_ANGLE@35..36 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@36..80 + 0: SVELTE_AWAIT_THEN_BLOCK@36..80 + 0: SV_CURLY_COLON@36..39 "{:" [Newline("\n")] [] + 1: THEN_KW@39..43 "then" [] [] + 2: HTML_TEXT_EXPRESSION@43..49 + 0: HTML_LITERAL@43..49 " value" [] [] + 3: R_CURLY@49..50 "}" [] [] + 4: HTML_ELEMENT_LIST@50..80 + 0: HTML_ELEMENT@50..80 + 0: HTML_OPENING_ELEMENT@50..56 + 0: L_ANGLE@50..54 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@54..55 + 0: HTML_LITERAL@54..55 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@55..55 + 3: R_ANGLE@55..56 ">" [] [] + 1: HTML_ELEMENT_LIST@56..76 + 0: HTML_CONTENT@56..69 + 0: HTML_LITERAL@56..69 "The value is" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@69..76 + 0: L_CURLY@69..70 "{" [] [] + 1: HTML_TEXT_EXPRESSION@70..75 + 0: HTML_LITERAL@70..75 "value" [] [] + 2: R_CURLY@75..76 "}" [] [] + 2: HTML_CLOSING_ELEMENT@76..80 + 0: L_ANGLE@76..77 "<" [] [] + 1: SLASH@77..78 "/" [] [] + 2: HTML_TAG_NAME@78..79 + 0: HTML_LITERAL@78..79 "p" [] [] + 3: R_ANGLE@79..80 ">" [] [] + 2: SVELTE_AWAIT_CLOSING_BLOCK@80..89 + 0: SV_CURLY_SLASH@80..83 "{/" [Newline("\n")] [] + 1: AWAIT_KW@83..88 "await" [] [] + 2: R_CURLY@88..89 "}" [] [] + 4: EOF@89..90 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte new file mode 100644 index 000000000000..1a9cbb552a9a --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte @@ -0,0 +1 @@ +{#await expression}

{:then name}

{:catch name}

{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte.snap new file mode 100644 index 000000000000..d3672a32a9ad --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte.snap @@ -0,0 +1,205 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await expression}

{:then name}

{:catch name}

{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..18 " expression" [] [], + }, + then_clause: missing (optional), + catch_clause: missing (optional), + r_curly_token: R_CURLY@18..20 "}" [] [Whitespace(" ")], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@20..21 "<" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@21..22 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@22..23 ">" [] [], + }, + children: HtmlElementList [], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@23..24 "<" [] [], + slash_token: SLASH@24..25 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@25..26 "p" [] [], + }, + r_angle_token: R_ANGLE@26..28 ">" [] [Whitespace(" ")], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [ + SvelteAwaitThenBlock { + sv_curly_colon_token: SV_CURLY_COLON@28..30 "{:" [] [], + then_token: THEN_KW@30..34 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@34..39 " name" [] [], + }, + r_curly_token: R_CURLY@39..41 "}" [] [Whitespace(" ")], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@41..42 "<" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@42..43 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@43..44 ">" [] [], + }, + children: HtmlElementList [], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@44..45 "<" [] [], + slash_token: SLASH@45..46 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@46..47 "p" [] [], + }, + r_angle_token: R_ANGLE@47..49 ">" [] [Whitespace(" ")], + }, + }, + ], + }, + SvelteAwaitCatchBlock { + sv_curly_colon_token: SV_CURLY_COLON@49..51 "{:" [] [], + catch_token: CATCH_KW@51..56 "catch" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@56..61 " name" [] [], + }, + r_curly_token: R_CURLY@61..63 "}" [] [Whitespace(" ")], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@63..64 "<" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@64..65 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@65..66 ">" [] [], + }, + children: HtmlElementList [], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@66..67 "<" [] [], + slash_token: SLASH@67..68 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@68..69 "p" [] [], + }, + r_angle_token: R_ANGLE@69..71 ">" [] [Whitespace(" ")], + }, + }, + ], + }, + ], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@71..73 "{/" [] [], + await_token: AWAIT_KW@73..78 "await" [] [], + r_curly_token: R_CURLY@78..79 "}" [] [], + }, + }, + ], + eof_token: EOF@79..80 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..80 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..79 + 0: SVELTE_AWAIT_BLOCK@0..79 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..28 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..18 + 0: HTML_LITERAL@7..18 " expression" [] [] + 3: (empty) + 4: (empty) + 5: R_CURLY@18..20 "}" [] [Whitespace(" ")] + 6: HTML_ELEMENT_LIST@20..28 + 0: HTML_ELEMENT@20..28 + 0: HTML_OPENING_ELEMENT@20..23 + 0: L_ANGLE@20..21 "<" [] [] + 1: HTML_TAG_NAME@21..22 + 0: HTML_LITERAL@21..22 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@22..22 + 3: R_ANGLE@22..23 ">" [] [] + 1: HTML_ELEMENT_LIST@23..23 + 2: HTML_CLOSING_ELEMENT@23..28 + 0: L_ANGLE@23..24 "<" [] [] + 1: SLASH@24..25 "/" [] [] + 2: HTML_TAG_NAME@25..26 + 0: HTML_LITERAL@25..26 "p" [] [] + 3: R_ANGLE@26..28 ">" [] [Whitespace(" ")] + 1: SVELTE_AWAIT_CLAUSES_LIST@28..71 + 0: SVELTE_AWAIT_THEN_BLOCK@28..49 + 0: SV_CURLY_COLON@28..30 "{:" [] [] + 1: THEN_KW@30..34 "then" [] [] + 2: HTML_TEXT_EXPRESSION@34..39 + 0: HTML_LITERAL@34..39 " name" [] [] + 3: R_CURLY@39..41 "}" [] [Whitespace(" ")] + 4: HTML_ELEMENT_LIST@41..49 + 0: HTML_ELEMENT@41..49 + 0: HTML_OPENING_ELEMENT@41..44 + 0: L_ANGLE@41..42 "<" [] [] + 1: HTML_TAG_NAME@42..43 + 0: HTML_LITERAL@42..43 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@43..43 + 3: R_ANGLE@43..44 ">" [] [] + 1: HTML_ELEMENT_LIST@44..44 + 2: HTML_CLOSING_ELEMENT@44..49 + 0: L_ANGLE@44..45 "<" [] [] + 1: SLASH@45..46 "/" [] [] + 2: HTML_TAG_NAME@46..47 + 0: HTML_LITERAL@46..47 "p" [] [] + 3: R_ANGLE@47..49 ">" [] [Whitespace(" ")] + 1: SVELTE_AWAIT_CATCH_BLOCK@49..71 + 0: SV_CURLY_COLON@49..51 "{:" [] [] + 1: CATCH_KW@51..56 "catch" [] [] + 2: HTML_TEXT_EXPRESSION@56..61 + 0: HTML_LITERAL@56..61 " name" [] [] + 3: R_CURLY@61..63 "}" [] [Whitespace(" ")] + 4: HTML_ELEMENT_LIST@63..71 + 0: HTML_ELEMENT@63..71 + 0: HTML_OPENING_ELEMENT@63..66 + 0: L_ANGLE@63..64 "<" [] [] + 1: HTML_TAG_NAME@64..65 + 0: HTML_LITERAL@64..65 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@65..65 + 3: R_ANGLE@65..66 ">" [] [] + 1: HTML_ELEMENT_LIST@66..66 + 2: HTML_CLOSING_ELEMENT@66..71 + 0: L_ANGLE@66..67 "<" [] [] + 1: SLASH@67..68 "/" [] [] + 2: HTML_TAG_NAME@68..69 + 0: HTML_LITERAL@68..69 "p" [] [] + 3: R_ANGLE@69..71 ">" [] [Whitespace(" ")] + 2: SVELTE_AWAIT_CLOSING_BLOCK@71..79 + 0: SV_CURLY_SLASH@71..73 "{/" [] [] + 1: AWAIT_KW@73..78 "await" [] [] + 2: R_CURLY@78..79 "}" [] [] + 4: EOF@79..80 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte new file mode 100644 index 000000000000..60311cd304fd --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte @@ -0,0 +1,3 @@ +{#await promise then value} +

The value is {value}

+{/await} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte.snap new file mode 100644 index 000000000000..941d3a3da8c0 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte.snap @@ -0,0 +1,132 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#await promise then value} +

The value is {value}

+{/await} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteAwaitBlock { + opening_block: SvelteAwaitOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + await_token: AWAIT_KW@2..7 "await" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@7..16 " promise " [] [], + }, + then_clause: SvelteAwaitThenClause { + then_token: THEN_KW@16..20 "then" [] [], + name: HtmlTextExpression { + html_literal_token: HTML_LITERAL@20..26 " value" [] [], + }, + }, + catch_clause: missing (optional), + r_curly_token: R_CURLY@26..27 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@27..31 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@31..32 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@32..33 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@33..46 "The value is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@46..47 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@47..52 "value" [] [], + }, + r_curly_token: R_CURLY@52..53 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@53..54 "<" [] [], + slash_token: SLASH@54..55 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@55..56 "p" [] [], + }, + r_angle_token: R_ANGLE@56..57 ">" [] [], + }, + }, + ], + }, + clauses: SvelteAwaitClausesList [], + closing_block: SvelteAwaitClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@57..60 "{/" [Newline("\n")] [], + await_token: AWAIT_KW@60..65 "await" [] [], + r_curly_token: R_CURLY@65..66 "}" [] [], + }, + }, + ], + eof_token: EOF@66..67 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..67 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..66 + 0: SVELTE_AWAIT_BLOCK@0..66 + 0: SVELTE_AWAIT_OPENING_BLOCK@0..57 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: AWAIT_KW@2..7 "await" [] [] + 2: HTML_TEXT_EXPRESSION@7..16 + 0: HTML_LITERAL@7..16 " promise " [] [] + 3: SVELTE_AWAIT_THEN_CLAUSE@16..26 + 0: THEN_KW@16..20 "then" [] [] + 1: HTML_TEXT_EXPRESSION@20..26 + 0: HTML_LITERAL@20..26 " value" [] [] + 4: (empty) + 5: R_CURLY@26..27 "}" [] [] + 6: HTML_ELEMENT_LIST@27..57 + 0: HTML_ELEMENT@27..57 + 0: HTML_OPENING_ELEMENT@27..33 + 0: L_ANGLE@27..31 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@31..32 + 0: HTML_LITERAL@31..32 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@32..32 + 3: R_ANGLE@32..33 ">" [] [] + 1: HTML_ELEMENT_LIST@33..53 + 0: HTML_CONTENT@33..46 + 0: HTML_LITERAL@33..46 "The value is" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@46..53 + 0: L_CURLY@46..47 "{" [] [] + 1: HTML_TEXT_EXPRESSION@47..52 + 0: HTML_LITERAL@47..52 "value" [] [] + 2: R_CURLY@52..53 "}" [] [] + 2: HTML_CLOSING_ELEMENT@53..57 + 0: L_ANGLE@53..54 "<" [] [] + 1: SLASH@54..55 "/" [] [] + 2: HTML_TAG_NAME@55..56 + 0: HTML_LITERAL@55..56 "p" [] [] + 3: R_ANGLE@56..57 ">" [] [] + 1: SVELTE_AWAIT_CLAUSES_LIST@57..57 + 2: SVELTE_AWAIT_CLOSING_BLOCK@57..66 + 0: SV_CURLY_SLASH@57..60 "{/" [Newline("\n")] [] + 1: AWAIT_KW@60..65 "await" [] [] + 2: R_CURLY@65..66 "}" [] [] + 4: EOF@66..67 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte new file mode 100644 index 000000000000..ea612545c55f --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte @@ -0,0 +1,3 @@ +{#snippet coords([x, y])} +

Position: {x}, {y}

+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte.snap new file mode 100644 index 000000000000..1e6af83b5a59 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte.snap @@ -0,0 +1,135 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet coords([x, y])} +

Position: {x}, {y}

+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..24 " coords([x, y])" [] [], + }, + r_curly_token: R_CURLY@24..25 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@25..29 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@29..30 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@30..31 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@31..41 "Position:" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@41..42 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@42..43 "x" [] [], + }, + r_curly_token: R_CURLY@43..44 "}" [] [], + }, + HtmlContent { + value_token: HTML_LITERAL@44..46 "," [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@46..47 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@47..48 "y" [] [], + }, + r_curly_token: R_CURLY@48..49 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@49..50 "<" [] [], + slash_token: SLASH@50..51 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@51..52 "p" [] [], + }, + r_angle_token: R_ANGLE@52..53 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@53..56 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@56..63 "snippet" [] [], + r_curly_token: R_CURLY@63..64 "}" [] [], + }, + }, + ], + eof_token: EOF@64..65 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..65 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..64 + 0: SVELTE_SNIPPET_BLOCK@0..64 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..53 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..24 + 0: HTML_LITERAL@9..24 " coords([x, y])" [] [] + 3: R_CURLY@24..25 "}" [] [] + 4: HTML_ELEMENT_LIST@25..53 + 0: HTML_ELEMENT@25..53 + 0: HTML_OPENING_ELEMENT@25..31 + 0: L_ANGLE@25..29 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@29..30 + 0: HTML_LITERAL@29..30 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@30..30 + 3: R_ANGLE@30..31 ">" [] [] + 1: HTML_ELEMENT_LIST@31..49 + 0: HTML_CONTENT@31..41 + 0: HTML_LITERAL@31..41 "Position:" [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@41..44 + 0: L_CURLY@41..42 "{" [] [] + 1: HTML_TEXT_EXPRESSION@42..43 + 0: HTML_LITERAL@42..43 "x" [] [] + 2: R_CURLY@43..44 "}" [] [] + 2: HTML_CONTENT@44..46 + 0: HTML_LITERAL@44..46 "," [] [Whitespace(" ")] + 3: HTML_SINGLE_TEXT_EXPRESSION@46..49 + 0: L_CURLY@46..47 "{" [] [] + 1: HTML_TEXT_EXPRESSION@47..48 + 0: HTML_LITERAL@47..48 "y" [] [] + 2: R_CURLY@48..49 "}" [] [] + 2: HTML_CLOSING_ELEMENT@49..53 + 0: L_ANGLE@49..50 "<" [] [] + 1: SLASH@50..51 "/" [] [] + 2: HTML_TAG_NAME@51..52 + 0: HTML_LITERAL@51..52 "p" [] [] + 3: R_ANGLE@52..53 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@53..64 + 0: SV_CURLY_SLASH@53..56 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@56..63 "snippet" [] [] + 2: R_CURLY@63..64 "}" [] [] + 4: EOF@64..65 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte new file mode 100644 index 000000000000..a7db91898bba --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte @@ -0,0 +1,3 @@ +{#snippet greeting()} +

Hello!

+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte.snap new file mode 100644 index 000000000000..2946f443b054 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte.snap @@ -0,0 +1,106 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet greeting()} +

Hello!

+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..20 " greeting()" [] [], + }, + r_curly_token: R_CURLY@20..21 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@25..26 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@26..27 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@27..33 "Hello!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@33..34 "<" [] [], + slash_token: SLASH@34..35 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@35..36 "p" [] [], + }, + r_angle_token: R_ANGLE@36..37 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@37..40 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@40..47 "snippet" [] [], + r_curly_token: R_CURLY@47..48 "}" [] [], + }, + }, + ], + eof_token: EOF@48..49 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..49 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..48 + 0: SVELTE_SNIPPET_BLOCK@0..48 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..37 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..20 + 0: HTML_LITERAL@9..20 " greeting()" [] [] + 3: R_CURLY@20..21 "}" [] [] + 4: HTML_ELEMENT_LIST@21..37 + 0: HTML_ELEMENT@21..37 + 0: HTML_OPENING_ELEMENT@21..27 + 0: L_ANGLE@21..25 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@25..26 + 0: HTML_LITERAL@25..26 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@26..26 + 3: R_ANGLE@26..27 ">" [] [] + 1: HTML_ELEMENT_LIST@27..33 + 0: HTML_CONTENT@27..33 + 0: HTML_LITERAL@27..33 "Hello!" [] [] + 2: HTML_CLOSING_ELEMENT@33..37 + 0: L_ANGLE@33..34 "<" [] [] + 1: SLASH@34..35 "/" [] [] + 2: HTML_TAG_NAME@35..36 + 0: HTML_LITERAL@35..36 "p" [] [] + 3: R_ANGLE@36..37 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@37..48 + 0: SV_CURLY_SLASH@37..40 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@40..47 "snippet" [] [] + 2: R_CURLY@47..48 "}" [] [] + 4: EOF@48..49 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte new file mode 100644 index 000000000000..9a6ce470d732 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte @@ -0,0 +1,3 @@ +{#snippet greeting(name = 'World')} +

Hello, {name}!

+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte.snap new file mode 100644 index 000000000000..a48b247676fa --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte.snap @@ -0,0 +1,123 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet greeting(name = 'World')} +

Hello, {name}!

+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..34 " greeting(name = 'World')" [] [], + }, + r_curly_token: R_CURLY@34..35 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@35..39 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@39..40 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@40..41 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@41..48 "Hello," [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@48..49 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@49..53 "name" [] [], + }, + r_curly_token: R_CURLY@53..54 "}" [] [], + }, + HtmlContent { + value_token: HTML_LITERAL@54..55 "!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@55..56 "<" [] [], + slash_token: SLASH@56..57 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@57..58 "p" [] [], + }, + r_angle_token: R_ANGLE@58..59 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@59..62 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@62..69 "snippet" [] [], + r_curly_token: R_CURLY@69..70 "}" [] [], + }, + }, + ], + eof_token: EOF@70..71 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..71 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..70 + 0: SVELTE_SNIPPET_BLOCK@0..70 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..59 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..34 + 0: HTML_LITERAL@9..34 " greeting(name = 'World')" [] [] + 3: R_CURLY@34..35 "}" [] [] + 4: HTML_ELEMENT_LIST@35..59 + 0: HTML_ELEMENT@35..59 + 0: HTML_OPENING_ELEMENT@35..41 + 0: L_ANGLE@35..39 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@39..40 + 0: HTML_LITERAL@39..40 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@40..40 + 3: R_ANGLE@40..41 ">" [] [] + 1: HTML_ELEMENT_LIST@41..55 + 0: HTML_CONTENT@41..48 + 0: HTML_LITERAL@41..48 "Hello," [] [Whitespace(" ")] + 1: HTML_SINGLE_TEXT_EXPRESSION@48..54 + 0: L_CURLY@48..49 "{" [] [] + 1: HTML_TEXT_EXPRESSION@49..53 + 0: HTML_LITERAL@49..53 "name" [] [] + 2: R_CURLY@53..54 "}" [] [] + 2: HTML_CONTENT@54..55 + 0: HTML_LITERAL@54..55 "!" [] [] + 2: HTML_CLOSING_ELEMENT@55..59 + 0: L_ANGLE@55..56 "<" [] [] + 1: SLASH@56..57 "/" [] [] + 2: HTML_TAG_NAME@57..58 + 0: HTML_LITERAL@57..58 "p" [] [] + 3: R_ANGLE@58..59 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@59..70 + 0: SV_CURLY_SLASH@59..62 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@62..69 "snippet" [] [] + 2: R_CURLY@69..70 "}" [] [] + 4: EOF@70..71 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte new file mode 100644 index 000000000000..9f8821b0ca1f --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte @@ -0,0 +1,3 @@ +{#snippet user({ name, age })} +

{name} is {age} years old

+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte.snap new file mode 100644 index 000000000000..fb45ba96e1f1 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte.snap @@ -0,0 +1,135 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet user({ name, age })} +

{name} is {age} years old

+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..29 " user({ name, age })" [] [], + }, + r_curly_token: R_CURLY@29..30 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@30..34 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..35 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@35..36 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@36..37 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@37..41 "name" [] [], + }, + r_curly_token: R_CURLY@41..43 "}" [] [Whitespace(" ")], + }, + HtmlContent { + value_token: HTML_LITERAL@43..46 "is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@46..47 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@47..50 "age" [] [], + }, + r_curly_token: R_CURLY@50..52 "}" [] [Whitespace(" ")], + }, + HtmlContent { + value_token: HTML_LITERAL@52..61 "years old" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@61..62 "<" [] [], + slash_token: SLASH@62..63 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@63..64 "p" [] [], + }, + r_angle_token: R_ANGLE@64..65 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@65..68 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@68..75 "snippet" [] [], + r_curly_token: R_CURLY@75..76 "}" [] [], + }, + }, + ], + eof_token: EOF@76..77 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..77 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..76 + 0: SVELTE_SNIPPET_BLOCK@0..76 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..65 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..29 + 0: HTML_LITERAL@9..29 " user({ name, age })" [] [] + 3: R_CURLY@29..30 "}" [] [] + 4: HTML_ELEMENT_LIST@30..65 + 0: HTML_ELEMENT@30..65 + 0: HTML_OPENING_ELEMENT@30..36 + 0: L_ANGLE@30..34 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@34..35 + 0: HTML_LITERAL@34..35 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@35..35 + 3: R_ANGLE@35..36 ">" [] [] + 1: HTML_ELEMENT_LIST@36..61 + 0: HTML_SINGLE_TEXT_EXPRESSION@36..43 + 0: L_CURLY@36..37 "{" [] [] + 1: HTML_TEXT_EXPRESSION@37..41 + 0: HTML_LITERAL@37..41 "name" [] [] + 2: R_CURLY@41..43 "}" [] [Whitespace(" ")] + 1: HTML_CONTENT@43..46 + 0: HTML_LITERAL@43..46 "is" [] [Whitespace(" ")] + 2: HTML_SINGLE_TEXT_EXPRESSION@46..52 + 0: L_CURLY@46..47 "{" [] [] + 1: HTML_TEXT_EXPRESSION@47..50 + 0: HTML_LITERAL@47..50 "age" [] [] + 2: R_CURLY@50..52 "}" [] [Whitespace(" ")] + 3: HTML_CONTENT@52..61 + 0: HTML_LITERAL@52..61 "years old" [] [] + 2: HTML_CLOSING_ELEMENT@61..65 + 0: L_ANGLE@61..62 "<" [] [] + 1: SLASH@62..63 "/" [] [] + 2: HTML_TAG_NAME@63..64 + 0: HTML_LITERAL@63..64 "p" [] [] + 3: R_ANGLE@64..65 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@65..76 + 0: SV_CURLY_SLASH@65..68 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@68..75 "snippet" [] [] + 2: R_CURLY@75..76 "}" [] [] + 4: EOF@76..77 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte new file mode 100644 index 000000000000..7299e11d5a7f --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte @@ -0,0 +1,7 @@ +{#snippet header()} +

Header

+{/snippet} + +{#snippet footer()} +

Footer

+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte.snap new file mode 100644 index 000000000000..063f18407f1c --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte.snap @@ -0,0 +1,178 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet header()} +

Header

+{/snippet} + +{#snippet footer()} +

Footer

+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..18 " header()" [] [], + }, + r_curly_token: R_CURLY@18..19 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@19..23 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@23..25 "h1" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@25..26 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@26..32 "Header" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@32..33 "<" [] [], + slash_token: SLASH@33..34 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@34..36 "h1" [] [], + }, + r_angle_token: R_ANGLE@36..37 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@37..40 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@40..47 "snippet" [] [], + r_curly_token: R_CURLY@47..48 "}" [] [], + }, + }, + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@48..52 "{#" [Newline("\n"), Newline("\n")] [], + snippet_token: SNIPPET_KW@52..59 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@59..68 " footer()" [] [], + }, + r_curly_token: R_CURLY@68..69 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@69..73 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@73..74 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@74..75 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@75..81 "Footer" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@81..82 "<" [] [], + slash_token: SLASH@82..83 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@83..84 "p" [] [], + }, + r_angle_token: R_ANGLE@84..85 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@85..88 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@88..95 "snippet" [] [], + r_curly_token: R_CURLY@95..96 "}" [] [], + }, + }, + ], + eof_token: EOF@96..97 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..97 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..96 + 0: SVELTE_SNIPPET_BLOCK@0..48 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..37 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..18 + 0: HTML_LITERAL@9..18 " header()" [] [] + 3: R_CURLY@18..19 "}" [] [] + 4: HTML_ELEMENT_LIST@19..37 + 0: HTML_ELEMENT@19..37 + 0: HTML_OPENING_ELEMENT@19..26 + 0: L_ANGLE@19..23 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@23..25 + 0: HTML_LITERAL@23..25 "h1" [] [] + 2: HTML_ATTRIBUTE_LIST@25..25 + 3: R_ANGLE@25..26 ">" [] [] + 1: HTML_ELEMENT_LIST@26..32 + 0: HTML_CONTENT@26..32 + 0: HTML_LITERAL@26..32 "Header" [] [] + 2: HTML_CLOSING_ELEMENT@32..37 + 0: L_ANGLE@32..33 "<" [] [] + 1: SLASH@33..34 "/" [] [] + 2: HTML_TAG_NAME@34..36 + 0: HTML_LITERAL@34..36 "h1" [] [] + 3: R_ANGLE@36..37 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@37..48 + 0: SV_CURLY_SLASH@37..40 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@40..47 "snippet" [] [] + 2: R_CURLY@47..48 "}" [] [] + 1: SVELTE_SNIPPET_BLOCK@48..96 + 0: SVELTE_SNIPPET_OPENING_BLOCK@48..85 + 0: SV_CURLY_HASH@48..52 "{#" [Newline("\n"), Newline("\n")] [] + 1: SNIPPET_KW@52..59 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@59..68 + 0: HTML_LITERAL@59..68 " footer()" [] [] + 3: R_CURLY@68..69 "}" [] [] + 4: HTML_ELEMENT_LIST@69..85 + 0: HTML_ELEMENT@69..85 + 0: HTML_OPENING_ELEMENT@69..75 + 0: L_ANGLE@69..73 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@73..74 + 0: HTML_LITERAL@73..74 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@74..74 + 3: R_ANGLE@74..75 ">" [] [] + 1: HTML_ELEMENT_LIST@75..81 + 0: HTML_CONTENT@75..81 + 0: HTML_LITERAL@75..81 "Footer" [] [] + 2: HTML_CLOSING_ELEMENT@81..85 + 0: L_ANGLE@81..82 "<" [] [] + 1: SLASH@82..83 "/" [] [] + 2: HTML_TAG_NAME@83..84 + 0: HTML_LITERAL@83..84 "p" [] [] + 3: R_ANGLE@84..85 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@85..96 + 0: SV_CURLY_SLASH@85..88 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@88..95 "snippet" [] [] + 2: R_CURLY@95..96 "}" [] [] + 4: EOF@96..97 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte new file mode 100644 index 000000000000..1afea2d2855f --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte @@ -0,0 +1,7 @@ +{#snippet outer()} +
+ {#snippet inner()} +

Inner content

+ {/snippet} +
+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte.snap new file mode 100644 index 000000000000..b1d202494d7b --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte.snap @@ -0,0 +1,173 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet outer()} +
+ {#snippet inner()} +

Inner content

+ {/snippet} +
+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..17 " outer()" [] [], + }, + r_curly_token: R_CURLY@17..18 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@18..22 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@22..25 "div" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@25..26 ">" [] [], + }, + children: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@26..33 "{#" [Newline("\n"), Whitespace(" ")] [], + snippet_token: SNIPPET_KW@33..40 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@40..48 " inner()" [] [], + }, + r_curly_token: R_CURLY@48..49 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@49..57 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@57..58 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@58..59 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@59..72 "Inner content" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@72..73 "<" [] [], + slash_token: SLASH@73..74 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@74..75 "p" [] [], + }, + r_angle_token: R_ANGLE@75..76 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@76..83 "{/" [Newline("\n"), Whitespace(" ")] [], + snippet_token: SNIPPET_KW@83..90 "snippet" [] [], + r_curly_token: R_CURLY@90..91 "}" [] [], + }, + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@91..95 "<" [Newline("\n"), Whitespace(" ")] [], + slash_token: SLASH@95..96 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@96..99 "div" [] [], + }, + r_angle_token: R_ANGLE@99..100 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@100..103 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@103..110 "snippet" [] [], + r_curly_token: R_CURLY@110..111 "}" [] [], + }, + }, + ], + eof_token: EOF@111..112 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..112 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..111 + 0: SVELTE_SNIPPET_BLOCK@0..111 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..100 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..17 + 0: HTML_LITERAL@9..17 " outer()" [] [] + 3: R_CURLY@17..18 "}" [] [] + 4: HTML_ELEMENT_LIST@18..100 + 0: HTML_ELEMENT@18..100 + 0: HTML_OPENING_ELEMENT@18..26 + 0: L_ANGLE@18..22 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@22..25 + 0: HTML_LITERAL@22..25 "div" [] [] + 2: HTML_ATTRIBUTE_LIST@25..25 + 3: R_ANGLE@25..26 ">" [] [] + 1: HTML_ELEMENT_LIST@26..91 + 0: SVELTE_SNIPPET_BLOCK@26..91 + 0: SVELTE_SNIPPET_OPENING_BLOCK@26..76 + 0: SV_CURLY_HASH@26..33 "{#" [Newline("\n"), Whitespace(" ")] [] + 1: SNIPPET_KW@33..40 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@40..48 + 0: HTML_LITERAL@40..48 " inner()" [] [] + 3: R_CURLY@48..49 "}" [] [] + 4: HTML_ELEMENT_LIST@49..76 + 0: HTML_ELEMENT@49..76 + 0: HTML_OPENING_ELEMENT@49..59 + 0: L_ANGLE@49..57 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@57..58 + 0: HTML_LITERAL@57..58 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@58..58 + 3: R_ANGLE@58..59 ">" [] [] + 1: HTML_ELEMENT_LIST@59..72 + 0: HTML_CONTENT@59..72 + 0: HTML_LITERAL@59..72 "Inner content" [] [] + 2: HTML_CLOSING_ELEMENT@72..76 + 0: L_ANGLE@72..73 "<" [] [] + 1: SLASH@73..74 "/" [] [] + 2: HTML_TAG_NAME@74..75 + 0: HTML_LITERAL@74..75 "p" [] [] + 3: R_ANGLE@75..76 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@76..91 + 0: SV_CURLY_SLASH@76..83 "{/" [Newline("\n"), Whitespace(" ")] [] + 1: SNIPPET_KW@83..90 "snippet" [] [] + 2: R_CURLY@90..91 "}" [] [] + 2: HTML_CLOSING_ELEMENT@91..100 + 0: L_ANGLE@91..95 "<" [Newline("\n"), Whitespace(" ")] [] + 1: SLASH@95..96 "/" [] [] + 2: HTML_TAG_NAME@96..99 + 0: HTML_LITERAL@96..99 "div" [] [] + 3: R_ANGLE@99..100 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@100..111 + 0: SV_CURLY_SLASH@100..103 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@103..110 "snippet" [] [] + 2: R_CURLY@110..111 "}" [] [] + 4: EOF@111..112 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte new file mode 100644 index 000000000000..c32d22e34b6a --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte @@ -0,0 +1,7 @@ +{#snippet countdown(n)} + {#if n > 0} +

{n}

+ {:else} +

Liftoff!

+ {/if} +{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte.snap new file mode 100644 index 000000000000..815e0ecbd769 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte.snap @@ -0,0 +1,199 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet countdown(n)} + {#if n > 0} +

{n}

+ {:else} +

Liftoff!

+ {/if} +{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..22 " countdown(n)" [] [], + }, + r_curly_token: R_CURLY@22..23 "}" [] [], + children: HtmlElementList [ + SvelteIfBlock { + opening_block: SvelteIfOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@23..28 "{#" [Newline("\n"), Whitespace(" ")] [], + if_token: IF_KW@28..30 "if" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@30..36 " n > 0" [] [], + }, + r_curly_token: R_CURLY@36..37 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@37..43 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@43..44 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@44..45 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@45..46 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@46..47 "n" [] [], + }, + r_curly_token: R_CURLY@47..48 "}" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@48..49 "<" [] [], + slash_token: SLASH@49..50 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@50..51 "p" [] [], + }, + r_angle_token: R_ANGLE@51..52 ">" [] [], + }, + }, + ], + }, + else_if_clauses: SvelteElseIfClauseList [], + else_clause: SvelteElseClause { + sv_curly_colon_token: SV_CURLY_COLON@52..57 "{:" [Newline("\n"), Whitespace(" ")] [], + else_token: ELSE_KW@57..61 "else" [] [], + r_curly_token: R_CURLY@61..62 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@62..68 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@68..69 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@69..70 ">" [] [], + }, + children: HtmlElementList [ + HtmlContent { + value_token: HTML_LITERAL@70..78 "Liftoff!" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@78..79 "<" [] [], + slash_token: SLASH@79..80 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@80..81 "p" [] [], + }, + r_angle_token: R_ANGLE@81..82 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteIfClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@82..87 "{/" [Newline("\n"), Whitespace(" ")] [], + if_token: IF_KW@87..89 "if" [] [], + r_curly_token: R_CURLY@89..90 "}" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@90..93 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@93..100 "snippet" [] [], + r_curly_token: R_CURLY@100..101 "}" [] [], + }, + }, + ], + eof_token: EOF@101..102 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..102 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..101 + 0: SVELTE_SNIPPET_BLOCK@0..101 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..90 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..22 + 0: HTML_LITERAL@9..22 " countdown(n)" [] [] + 3: R_CURLY@22..23 "}" [] [] + 4: HTML_ELEMENT_LIST@23..90 + 0: SVELTE_IF_BLOCK@23..90 + 0: SVELTE_IF_OPENING_BLOCK@23..52 + 0: SV_CURLY_HASH@23..28 "{#" [Newline("\n"), Whitespace(" ")] [] + 1: IF_KW@28..30 "if" [] [] + 2: HTML_TEXT_EXPRESSION@30..36 + 0: HTML_LITERAL@30..36 " n > 0" [] [] + 3: R_CURLY@36..37 "}" [] [] + 4: HTML_ELEMENT_LIST@37..52 + 0: HTML_ELEMENT@37..52 + 0: HTML_OPENING_ELEMENT@37..45 + 0: L_ANGLE@37..43 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@43..44 + 0: HTML_LITERAL@43..44 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@44..44 + 3: R_ANGLE@44..45 ">" [] [] + 1: HTML_ELEMENT_LIST@45..48 + 0: HTML_SINGLE_TEXT_EXPRESSION@45..48 + 0: L_CURLY@45..46 "{" [] [] + 1: HTML_TEXT_EXPRESSION@46..47 + 0: HTML_LITERAL@46..47 "n" [] [] + 2: R_CURLY@47..48 "}" [] [] + 2: HTML_CLOSING_ELEMENT@48..52 + 0: L_ANGLE@48..49 "<" [] [] + 1: SLASH@49..50 "/" [] [] + 2: HTML_TAG_NAME@50..51 + 0: HTML_LITERAL@50..51 "p" [] [] + 3: R_ANGLE@51..52 ">" [] [] + 1: SVELTE_ELSE_IF_CLAUSE_LIST@52..52 + 2: SVELTE_ELSE_CLAUSE@52..82 + 0: SV_CURLY_COLON@52..57 "{:" [Newline("\n"), Whitespace(" ")] [] + 1: ELSE_KW@57..61 "else" [] [] + 2: R_CURLY@61..62 "}" [] [] + 3: HTML_ELEMENT_LIST@62..82 + 0: HTML_ELEMENT@62..82 + 0: HTML_OPENING_ELEMENT@62..70 + 0: L_ANGLE@62..68 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@68..69 + 0: HTML_LITERAL@68..69 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@69..69 + 3: R_ANGLE@69..70 ">" [] [] + 1: HTML_ELEMENT_LIST@70..78 + 0: HTML_CONTENT@70..78 + 0: HTML_LITERAL@70..78 "Liftoff!" [] [] + 2: HTML_CLOSING_ELEMENT@78..82 + 0: L_ANGLE@78..79 "<" [] [] + 1: SLASH@79..80 "/" [] [] + 2: HTML_TAG_NAME@80..81 + 0: HTML_LITERAL@80..81 "p" [] [] + 3: R_ANGLE@81..82 ">" [] [] + 3: SVELTE_IF_CLOSING_BLOCK@82..90 + 0: SV_CURLY_SLASH@82..87 "{/" [Newline("\n"), Whitespace(" ")] [] + 1: IF_KW@87..89 "if" [] [] + 2: R_CURLY@89..90 "}" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@90..101 + 0: SV_CURLY_SLASH@90..93 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@93..100 "snippet" [] [] + 2: R_CURLY@100..101 "}" [] [] + 4: EOF@101..102 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte new file mode 100644 index 000000000000..dc9dcfc2ff0f --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte @@ -0,0 +1,3 @@ +{#snippet user(name, age)} +

{name} is {age} years old

+{/snippet} diff --git a/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte.snap b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte.snap new file mode 100644 index 000000000000..78582941aa52 --- /dev/null +++ b/crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte.snap @@ -0,0 +1,135 @@ +--- +source: crates/biome_html_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```svelte +{#snippet user(name, age)} +

{name} is {age} years old

+{/snippet} + +``` + + +## AST + +``` +HtmlRoot { + bom_token: missing (optional), + frontmatter: missing (optional), + directive: missing (optional), + html: HtmlElementList [ + SvelteSnippetBlock { + opening_block: SvelteSnippetOpeningBlock { + sv_curly_hash_token: SV_CURLY_HASH@0..2 "{#" [] [], + snippet_token: SNIPPET_KW@2..9 "snippet" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@9..25 " user(name, age)" [] [], + }, + r_curly_token: R_CURLY@25..26 "}" [] [], + children: HtmlElementList [ + HtmlElement { + opening_element: HtmlOpeningElement { + l_angle_token: L_ANGLE@26..30 "<" [Newline("\n"), Whitespace(" ")] [], + name: HtmlTagName { + value_token: HTML_LITERAL@30..31 "p" [] [], + }, + attributes: HtmlAttributeList [], + r_angle_token: R_ANGLE@31..32 ">" [] [], + }, + children: HtmlElementList [ + HtmlSingleTextExpression { + l_curly_token: L_CURLY@32..33 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@33..37 "name" [] [], + }, + r_curly_token: R_CURLY@37..39 "}" [] [Whitespace(" ")], + }, + HtmlContent { + value_token: HTML_LITERAL@39..42 "is" [] [Whitespace(" ")], + }, + HtmlSingleTextExpression { + l_curly_token: L_CURLY@42..43 "{" [] [], + expression: HtmlTextExpression { + html_literal_token: HTML_LITERAL@43..46 "age" [] [], + }, + r_curly_token: R_CURLY@46..48 "}" [] [Whitespace(" ")], + }, + HtmlContent { + value_token: HTML_LITERAL@48..57 "years old" [] [], + }, + ], + closing_element: HtmlClosingElement { + l_angle_token: L_ANGLE@57..58 "<" [] [], + slash_token: SLASH@58..59 "/" [] [], + name: HtmlTagName { + value_token: HTML_LITERAL@59..60 "p" [] [], + }, + r_angle_token: R_ANGLE@60..61 ">" [] [], + }, + }, + ], + }, + closing_block: SvelteSnippetClosingBlock { + sv_curly_slash_token: SV_CURLY_SLASH@61..64 "{/" [Newline("\n")] [], + snippet_token: SNIPPET_KW@64..71 "snippet" [] [], + r_curly_token: R_CURLY@71..72 "}" [] [], + }, + }, + ], + eof_token: EOF@72..73 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: HTML_ROOT@0..73 + 0: (empty) + 1: (empty) + 2: (empty) + 3: HTML_ELEMENT_LIST@0..72 + 0: SVELTE_SNIPPET_BLOCK@0..72 + 0: SVELTE_SNIPPET_OPENING_BLOCK@0..61 + 0: SV_CURLY_HASH@0..2 "{#" [] [] + 1: SNIPPET_KW@2..9 "snippet" [] [] + 2: HTML_TEXT_EXPRESSION@9..25 + 0: HTML_LITERAL@9..25 " user(name, age)" [] [] + 3: R_CURLY@25..26 "}" [] [] + 4: HTML_ELEMENT_LIST@26..61 + 0: HTML_ELEMENT@26..61 + 0: HTML_OPENING_ELEMENT@26..32 + 0: L_ANGLE@26..30 "<" [Newline("\n"), Whitespace(" ")] [] + 1: HTML_TAG_NAME@30..31 + 0: HTML_LITERAL@30..31 "p" [] [] + 2: HTML_ATTRIBUTE_LIST@31..31 + 3: R_ANGLE@31..32 ">" [] [] + 1: HTML_ELEMENT_LIST@32..57 + 0: HTML_SINGLE_TEXT_EXPRESSION@32..39 + 0: L_CURLY@32..33 "{" [] [] + 1: HTML_TEXT_EXPRESSION@33..37 + 0: HTML_LITERAL@33..37 "name" [] [] + 2: R_CURLY@37..39 "}" [] [Whitespace(" ")] + 1: HTML_CONTENT@39..42 + 0: HTML_LITERAL@39..42 "is" [] [Whitespace(" ")] + 2: HTML_SINGLE_TEXT_EXPRESSION@42..48 + 0: L_CURLY@42..43 "{" [] [] + 1: HTML_TEXT_EXPRESSION@43..46 + 0: HTML_LITERAL@43..46 "age" [] [] + 2: R_CURLY@46..48 "}" [] [Whitespace(" ")] + 3: HTML_CONTENT@48..57 + 0: HTML_LITERAL@48..57 "years old" [] [] + 2: HTML_CLOSING_ELEMENT@57..61 + 0: L_ANGLE@57..58 "<" [] [] + 1: SLASH@58..59 "/" [] [] + 2: HTML_TAG_NAME@59..60 + 0: HTML_LITERAL@59..60 "p" [] [] + 3: R_ANGLE@60..61 ">" [] [] + 1: SVELTE_SNIPPET_CLOSING_BLOCK@61..72 + 0: SV_CURLY_SLASH@61..64 "{/" [Newline("\n")] [] + 1: SNIPPET_KW@64..71 "snippet" [] [] + 2: R_CURLY@71..72 "}" [] [] + 4: EOF@72..73 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_html_parser/tests/quick_test.rs b/crates/biome_html_parser/tests/quick_test.rs index d5682336b5af..51ca743f1a69 100644 --- a/crates/biome_html_parser/tests/quick_test.rs +++ b/crates/biome_html_parser/tests/quick_test.rs @@ -4,13 +4,11 @@ use biome_test_utils::has_bogus_nodes_or_empty_slots; #[ignore] #[test] pub fn quick_test() { - let code = r#"{#each items as item, i (item.id)} -
{i}: {item.name}
-{/each} + let code = r#"{#snippet f()} +

+{/snippet}"#; - "#; - - let options = HtmlParseOptions::default().with_vue(); + let options = HtmlParseOptions::default().with_single_text_expression(); let root = parse_html(code, options); let syntax = root.syntax(); dbg!(&syntax, root.diagnostics(), root.has_errors()); diff --git a/crates/biome_html_syntax/src/generated/kind.rs b/crates/biome_html_syntax/src/generated/kind.rs index 23ca5d4bf8b3..0629deeee8c7 100644 --- a/crates/biome_html_syntax/src/generated/kind.rs +++ b/crates/biome_html_syntax/src/generated/kind.rs @@ -52,6 +52,10 @@ pub enum HtmlSyntaxKind { IF_KW, AS_KW, EACH_KW, + THEN_KW, + AWAIT_KW, + CATCH_KW, + SNIPPET_KW, HTML_STRING_LITERAL, HTML_LITERAL, ERROR_TOKEN, @@ -104,6 +108,17 @@ pub enum HtmlSyntaxKind { SVELTE_EACH_INDEX, SVELTE_EACH_KEY, SVELTE_EACH_CLOSING_BLOCK, + SVELTE_AWAIT_BLOCK, + SVELTE_AWAIT_OPENING_BLOCK, + SVELTE_AWAIT_THEN_BLOCK, + SVELTE_AWAIT_CLAUSES_LIST, + SVELTE_AWAIT_CATCH_BLOCK, + SVELTE_AWAIT_CLOSING_BLOCK, + SVELTE_AWAIT_THEN_CLAUSE, + SVELTE_AWAIT_CATCH_CLAUSE, + SVELTE_SNIPPET_BLOCK, + SVELTE_SNIPPET_OPENING_BLOCK, + SVELTE_SNIPPET_CLOSING_BLOCK, VUE_DIRECTIVE, VUE_DIRECTIVE_ARGUMENT, VUE_V_BIND_SHORTHAND_DIRECTIVE, @@ -167,6 +182,7 @@ impl HtmlSyntaxKind { | HTML_ATTRIBUTE_LIST | SVELTE_BINDING_LIST | SVELTE_ELSE_IF_CLAUSE_LIST + | SVELTE_AWAIT_CLAUSES_LIST | VUE_MODIFIER_LIST ) } @@ -186,6 +202,10 @@ impl HtmlSyntaxKind { "if" => IF_KW, "as" => AS_KW, "each" => EACH_KW, + "then" => THEN_KW, + "await" => AWAIT_KW, + "catch" => CATCH_KW, + "snippet" => SNIPPET_KW, _ => return None, }; Some(kw) @@ -232,6 +252,10 @@ impl HtmlSyntaxKind { IF_KW => "if", AS_KW => "as", EACH_KW => "each", + THEN_KW => "then", + AWAIT_KW => "await", + CATCH_KW => "catch", + SNIPPET_KW => "snippet", EOF => "EOF", HTML_STRING_LITERAL => "string literal", _ => return None, @@ -241,4 +265,4 @@ impl HtmlSyntaxKind { } #[doc = r" Utility macro for creating a SyntaxKind through simple macro syntax"] #[macro_export] -macro_rules ! T { [<] => { $ crate :: HtmlSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: HtmlSyntaxKind :: R_ANGLE } ; [/] => { $ crate :: HtmlSyntaxKind :: SLASH } ; [=] => { $ crate :: HtmlSyntaxKind :: EQ } ; [!] => { $ crate :: HtmlSyntaxKind :: BANG } ; [-] => { $ crate :: HtmlSyntaxKind :: MINUS } ; [" { $ crate :: HtmlSyntaxKind :: CDATA_START } ; ["]]>"] => { $ crate :: HtmlSyntaxKind :: CDATA_END } ; [---] => { $ crate :: HtmlSyntaxKind :: FENCE } ; ['{'] => { $ crate :: HtmlSyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: HtmlSyntaxKind :: R_CURLY } ; ["{{"] => { $ crate :: HtmlSyntaxKind :: L_DOUBLE_CURLY } ; ["}}"] => { $ crate :: HtmlSyntaxKind :: R_DOUBLE_CURLY } ; ["{@"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_AT } ; ["{#"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_HASH } ; ["{/"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_SLASH } ; ["{:"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_COLON } ; [,] => { $ crate :: HtmlSyntaxKind :: COMMA } ; [:] => { $ crate :: HtmlSyntaxKind :: COLON } ; [@] => { $ crate :: HtmlSyntaxKind :: AT } ; [.] => { $ crate :: HtmlSyntaxKind :: DOT } ; ['['] => { $ crate :: HtmlSyntaxKind :: L_BRACKET } ; [']'] => { $ crate :: HtmlSyntaxKind :: R_BRACKET } ; [#] => { $ crate :: HtmlSyntaxKind :: HASH } ; ['('] => { $ crate :: HtmlSyntaxKind :: L_PAREN } ; [')'] => { $ crate :: HtmlSyntaxKind :: R_PAREN } ; [null] => { $ crate :: HtmlSyntaxKind :: NULL_KW } ; [true] => { $ crate :: HtmlSyntaxKind :: TRUE_KW } ; [false] => { $ crate :: HtmlSyntaxKind :: FALSE_KW } ; [doctype] => { $ crate :: HtmlSyntaxKind :: DOCTYPE_KW } ; [html] => { $ crate :: HtmlSyntaxKind :: HTML_KW } ; [debug] => { $ crate :: HtmlSyntaxKind :: DEBUG_KW } ; [key] => { $ crate :: HtmlSyntaxKind :: KEY_KW } ; [render] => { $ crate :: HtmlSyntaxKind :: RENDER_KW } ; [const] => { $ crate :: HtmlSyntaxKind :: CONST_KW } ; [attach] => { $ crate :: HtmlSyntaxKind :: ATTACH_KW } ; [else] => { $ crate :: HtmlSyntaxKind :: ELSE_KW } ; [if] => { $ crate :: HtmlSyntaxKind :: IF_KW } ; [as] => { $ crate :: HtmlSyntaxKind :: AS_KW } ; [each] => { $ crate :: HtmlSyntaxKind :: EACH_KW } ; [ident] => { $ crate :: HtmlSyntaxKind :: IDENT } ; [EOF] => { $ crate :: HtmlSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: HtmlSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: HtmlSyntaxKind :: HASH } ; } +macro_rules ! T { [<] => { $ crate :: HtmlSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: HtmlSyntaxKind :: R_ANGLE } ; [/] => { $ crate :: HtmlSyntaxKind :: SLASH } ; [=] => { $ crate :: HtmlSyntaxKind :: EQ } ; [!] => { $ crate :: HtmlSyntaxKind :: BANG } ; [-] => { $ crate :: HtmlSyntaxKind :: MINUS } ; [" { $ crate :: HtmlSyntaxKind :: CDATA_START } ; ["]]>"] => { $ crate :: HtmlSyntaxKind :: CDATA_END } ; [---] => { $ crate :: HtmlSyntaxKind :: FENCE } ; ['{'] => { $ crate :: HtmlSyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: HtmlSyntaxKind :: R_CURLY } ; ["{{"] => { $ crate :: HtmlSyntaxKind :: L_DOUBLE_CURLY } ; ["}}"] => { $ crate :: HtmlSyntaxKind :: R_DOUBLE_CURLY } ; ["{@"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_AT } ; ["{#"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_HASH } ; ["{/"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_SLASH } ; ["{:"] => { $ crate :: HtmlSyntaxKind :: SV_CURLY_COLON } ; [,] => { $ crate :: HtmlSyntaxKind :: COMMA } ; [:] => { $ crate :: HtmlSyntaxKind :: COLON } ; [@] => { $ crate :: HtmlSyntaxKind :: AT } ; [.] => { $ crate :: HtmlSyntaxKind :: DOT } ; ['['] => { $ crate :: HtmlSyntaxKind :: L_BRACKET } ; [']'] => { $ crate :: HtmlSyntaxKind :: R_BRACKET } ; [#] => { $ crate :: HtmlSyntaxKind :: HASH } ; ['('] => { $ crate :: HtmlSyntaxKind :: L_PAREN } ; [')'] => { $ crate :: HtmlSyntaxKind :: R_PAREN } ; [null] => { $ crate :: HtmlSyntaxKind :: NULL_KW } ; [true] => { $ crate :: HtmlSyntaxKind :: TRUE_KW } ; [false] => { $ crate :: HtmlSyntaxKind :: FALSE_KW } ; [doctype] => { $ crate :: HtmlSyntaxKind :: DOCTYPE_KW } ; [html] => { $ crate :: HtmlSyntaxKind :: HTML_KW } ; [debug] => { $ crate :: HtmlSyntaxKind :: DEBUG_KW } ; [key] => { $ crate :: HtmlSyntaxKind :: KEY_KW } ; [render] => { $ crate :: HtmlSyntaxKind :: RENDER_KW } ; [const] => { $ crate :: HtmlSyntaxKind :: CONST_KW } ; [attach] => { $ crate :: HtmlSyntaxKind :: ATTACH_KW } ; [else] => { $ crate :: HtmlSyntaxKind :: ELSE_KW } ; [if] => { $ crate :: HtmlSyntaxKind :: IF_KW } ; [as] => { $ crate :: HtmlSyntaxKind :: AS_KW } ; [each] => { $ crate :: HtmlSyntaxKind :: EACH_KW } ; [then] => { $ crate :: HtmlSyntaxKind :: THEN_KW } ; [await] => { $ crate :: HtmlSyntaxKind :: AWAIT_KW } ; [catch] => { $ crate :: HtmlSyntaxKind :: CATCH_KW } ; [snippet] => { $ crate :: HtmlSyntaxKind :: SNIPPET_KW } ; [ident] => { $ crate :: HtmlSyntaxKind :: IDENT } ; [EOF] => { $ crate :: HtmlSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: HtmlSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: HtmlSyntaxKind :: HASH } ; } diff --git a/crates/biome_html_syntax/src/generated/macros.rs b/crates/biome_html_syntax/src/generated/macros.rs index 040048a04820..7d47614e4ca0 100644 --- a/crates/biome_html_syntax/src/generated/macros.rs +++ b/crates/biome_html_syntax/src/generated/macros.rs @@ -97,6 +97,34 @@ macro_rules! map_syntax_node { let $pattern = unsafe { $crate::SvelteAttachAttribute::new_unchecked(node) }; $body } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_BLOCK => { + let $pattern = unsafe { $crate::SvelteAwaitBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_CATCH_BLOCK => { + let $pattern = unsafe { $crate::SvelteAwaitCatchBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_CATCH_CLAUSE => { + let $pattern = unsafe { $crate::SvelteAwaitCatchClause::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_CLOSING_BLOCK => { + let $pattern = unsafe { $crate::SvelteAwaitClosingBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_OPENING_BLOCK => { + let $pattern = unsafe { $crate::SvelteAwaitOpeningBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_THEN_BLOCK => { + let $pattern = unsafe { $crate::SvelteAwaitThenBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_THEN_CLAUSE => { + let $pattern = unsafe { $crate::SvelteAwaitThenClause::new_unchecked(node) }; + $body + } $crate::HtmlSyntaxKind::SVELTE_CONST_BLOCK => { let $pattern = unsafe { $crate::SvelteConstBlock::new_unchecked(node) }; $body @@ -177,6 +205,20 @@ macro_rules! map_syntax_node { let $pattern = unsafe { $crate::SvelteRenderBlock::new_unchecked(node) }; $body } + $crate::HtmlSyntaxKind::SVELTE_SNIPPET_BLOCK => { + let $pattern = unsafe { $crate::SvelteSnippetBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_SNIPPET_CLOSING_BLOCK => { + let $pattern = + unsafe { $crate::SvelteSnippetClosingBlock::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::SVELTE_SNIPPET_OPENING_BLOCK => { + let $pattern = + unsafe { $crate::SvelteSnippetOpeningBlock::new_unchecked(node) }; + $body + } $crate::HtmlSyntaxKind::VUE_DIRECTIVE => { let $pattern = unsafe { $crate::VueDirective::new_unchecked(node) }; $body @@ -252,6 +294,10 @@ macro_rules! map_syntax_node { let $pattern = unsafe { $crate::HtmlElementList::new_unchecked(node) }; $body } + $crate::HtmlSyntaxKind::SVELTE_AWAIT_CLAUSES_LIST => { + let $pattern = unsafe { $crate::SvelteAwaitClausesList::new_unchecked(node) }; + $body + } $crate::HtmlSyntaxKind::SVELTE_BINDING_LIST => { let $pattern = unsafe { $crate::SvelteBindingList::new_unchecked(node) }; $body diff --git a/crates/biome_html_syntax/src/generated/nodes.rs b/crates/biome_html_syntax/src/generated/nodes.rs index 5ea275ebb2f1..238b5f7e7294 100644 --- a/crates/biome_html_syntax/src/generated/nodes.rs +++ b/crates/biome_html_syntax/src/generated/nodes.rs @@ -900,10 +900,10 @@ pub struct SvelteAttachAttributeFields { pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteConstBlock { +pub struct SvelteAwaitBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteConstBlock { +impl SvelteAwaitBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -913,28 +913,24 @@ impl SvelteConstBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteConstBlockFields { - SvelteConstBlockFields { - sv_curly_at_token: self.sv_curly_at_token(), - const_token: self.const_token(), - expression: self.expression(), - r_curly_token: self.r_curly_token(), + pub fn as_fields(&self) -> SvelteAwaitBlockFields { + SvelteAwaitBlockFields { + opening_block: self.opening_block(), + clauses: self.clauses(), + closing_block: self.closing_block(), } } - pub fn sv_curly_at_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 0usize) + pub fn opening_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) } - pub fn const_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 1usize) + pub fn clauses(&self) -> SvelteAwaitClausesList { + support::list(&self.syntax, 1usize) } - pub fn expression(&self) -> SyntaxResult { + pub fn closing_block(&self) -> SyntaxResult { support::required_node(&self.syntax, 2usize) } - pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 3usize) - } } -impl Serialize for SvelteConstBlock { +impl Serialize for SvelteAwaitBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -943,17 +939,16 @@ impl Serialize for SvelteConstBlock { } } #[derive(Serialize)] -pub struct SvelteConstBlockFields { - pub sv_curly_at_token: SyntaxResult, - pub const_token: SyntaxResult, - pub expression: SyntaxResult, - pub r_curly_token: SyntaxResult, +pub struct SvelteAwaitBlockFields { + pub opening_block: SyntaxResult, + pub clauses: SvelteAwaitClausesList, + pub closing_block: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteDebugBlock { +pub struct SvelteAwaitCatchBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteDebugBlock { +impl SvelteAwaitCatchBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -963,28 +958,32 @@ impl SvelteDebugBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteDebugBlockFields { - SvelteDebugBlockFields { - sv_curly_at_token: self.sv_curly_at_token(), - debug_token: self.debug_token(), - bindings: self.bindings(), + pub fn as_fields(&self) -> SvelteAwaitCatchBlockFields { + SvelteAwaitCatchBlockFields { + sv_curly_colon_token: self.sv_curly_colon_token(), + catch_token: self.catch_token(), + name: self.name(), r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn sv_curly_at_token(&self) -> SyntaxResult { + pub fn sv_curly_colon_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn debug_token(&self) -> SyntaxResult { + pub fn catch_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } - pub fn bindings(&self) -> SvelteBindingList { - support::list(&self.syntax, 2usize) + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) } pub fn r_curly_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 3usize) } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 4usize) + } } -impl Serialize for SvelteDebugBlock { +impl Serialize for SvelteAwaitCatchBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -993,17 +992,18 @@ impl Serialize for SvelteDebugBlock { } } #[derive(Serialize)] -pub struct SvelteDebugBlockFields { - pub sv_curly_at_token: SyntaxResult, - pub debug_token: SyntaxResult, - pub bindings: SvelteBindingList, +pub struct SvelteAwaitCatchBlockFields { + pub sv_curly_colon_token: SyntaxResult, + pub catch_token: SyntaxResult, + pub name: SyntaxResult, pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachAsKeyedItem { +pub struct SvelteAwaitCatchClause { pub(crate) syntax: SyntaxNode, } -impl SvelteEachAsKeyedItem { +impl SvelteAwaitCatchClause { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1013,28 +1013,20 @@ impl SvelteEachAsKeyedItem { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachAsKeyedItemFields { - SvelteEachAsKeyedItemFields { - as_token: self.as_token(), + pub fn as_fields(&self) -> SvelteAwaitCatchClauseFields { + SvelteAwaitCatchClauseFields { + catch_token: self.catch_token(), name: self.name(), - index: self.index(), - key: self.key(), } } - pub fn as_token(&self) -> SyntaxResult { + pub fn catch_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } pub fn name(&self) -> SyntaxResult { support::required_node(&self.syntax, 1usize) } - pub fn index(&self) -> Option { - support::node(&self.syntax, 2usize) - } - pub fn key(&self) -> Option { - support::node(&self.syntax, 3usize) - } } -impl Serialize for SvelteEachAsKeyedItem { +impl Serialize for SvelteAwaitCatchClause { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1043,17 +1035,15 @@ impl Serialize for SvelteEachAsKeyedItem { } } #[derive(Serialize)] -pub struct SvelteEachAsKeyedItemFields { - pub as_token: SyntaxResult, +pub struct SvelteAwaitCatchClauseFields { + pub catch_token: SyntaxResult, pub name: SyntaxResult, - pub index: Option, - pub key: Option, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachBlock { +pub struct SvelteAwaitClosingBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteEachBlock { +impl SvelteAwaitClosingBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1063,28 +1053,24 @@ impl SvelteEachBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachBlockFields { - SvelteEachBlockFields { - opening_block: self.opening_block(), - children: self.children(), - else_clause: self.else_clause(), - closing_block: self.closing_block(), + pub fn as_fields(&self) -> SvelteAwaitClosingBlockFields { + SvelteAwaitClosingBlockFields { + sv_curly_slash_token: self.sv_curly_slash_token(), + await_token: self.await_token(), + r_curly_token: self.r_curly_token(), } } - pub fn opening_block(&self) -> SyntaxResult { - support::required_node(&self.syntax, 0usize) - } - pub fn children(&self) -> HtmlElementList { - support::list(&self.syntax, 1usize) + pub fn sv_curly_slash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn else_clause(&self) -> Option { - support::node(&self.syntax, 2usize) + pub fn await_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) } - pub fn closing_block(&self) -> SyntaxResult { - support::required_node(&self.syntax, 3usize) + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 2usize) } } -impl Serialize for SvelteEachBlock { +impl Serialize for SvelteAwaitClosingBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1093,17 +1079,16 @@ impl Serialize for SvelteEachBlock { } } #[derive(Serialize)] -pub struct SvelteEachBlockFields { - pub opening_block: SyntaxResult, - pub children: HtmlElementList, - pub else_clause: Option, - pub closing_block: SyntaxResult, +pub struct SvelteAwaitClosingBlockFields { + pub sv_curly_slash_token: SyntaxResult, + pub await_token: SyntaxResult, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachClosingBlock { +pub struct SvelteAwaitOpeningBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteEachClosingBlock { +impl SvelteAwaitOpeningBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1113,24 +1098,40 @@ impl SvelteEachClosingBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachClosingBlockFields { - SvelteEachClosingBlockFields { - sv_curly_slash_token: self.sv_curly_slash_token(), - each_token: self.each_token(), + pub fn as_fields(&self) -> SvelteAwaitOpeningBlockFields { + SvelteAwaitOpeningBlockFields { + sv_curly_hash_token: self.sv_curly_hash_token(), + await_token: self.await_token(), + expression: self.expression(), + then_clause: self.then_clause(), + catch_clause: self.catch_clause(), r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn sv_curly_slash_token(&self) -> SyntaxResult { + pub fn sv_curly_hash_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn each_token(&self) -> SyntaxResult { + pub fn await_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn then_clause(&self) -> Option { + support::node(&self.syntax, 3usize) + } + pub fn catch_clause(&self) -> Option { + support::node(&self.syntax, 4usize) + } pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 2usize) + support::required_token(&self.syntax, 5usize) + } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 6usize) } } -impl Serialize for SvelteEachClosingBlock { +impl Serialize for SvelteAwaitOpeningBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1139,16 +1140,20 @@ impl Serialize for SvelteEachClosingBlock { } } #[derive(Serialize)] -pub struct SvelteEachClosingBlockFields { - pub sv_curly_slash_token: SyntaxResult, - pub each_token: SyntaxResult, +pub struct SvelteAwaitOpeningBlockFields { + pub sv_curly_hash_token: SyntaxResult, + pub await_token: SyntaxResult, + pub expression: SyntaxResult, + pub then_clause: Option, + pub catch_clause: Option, pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachIndex { +pub struct SvelteAwaitThenBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteEachIndex { +impl SvelteAwaitThenBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1158,20 +1163,32 @@ impl SvelteEachIndex { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachIndexFields { - SvelteEachIndexFields { - comma_token: self.comma_token(), - value: self.value(), + pub fn as_fields(&self) -> SvelteAwaitThenBlockFields { + SvelteAwaitThenBlockFields { + sv_curly_colon_token: self.sv_curly_colon_token(), + then_token: self.then_token(), + name: self.name(), + r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn comma_token(&self) -> SyntaxResult { + pub fn sv_curly_colon_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn value(&self) -> SyntaxResult { - support::required_node(&self.syntax, 1usize) + pub fn then_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 4usize) } } -impl Serialize for SvelteEachIndex { +impl Serialize for SvelteAwaitThenBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1180,15 +1197,18 @@ impl Serialize for SvelteEachIndex { } } #[derive(Serialize)] -pub struct SvelteEachIndexFields { - pub comma_token: SyntaxResult, - pub value: SyntaxResult, +pub struct SvelteAwaitThenBlockFields { + pub sv_curly_colon_token: SyntaxResult, + pub then_token: SyntaxResult, + pub name: SyntaxResult, + pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachKey { +pub struct SvelteAwaitThenClause { pub(crate) syntax: SyntaxNode, } -impl SvelteEachKey { +impl SvelteAwaitThenClause { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1198,24 +1218,20 @@ impl SvelteEachKey { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachKeyFields { - SvelteEachKeyFields { - l_paren_token: self.l_paren_token(), - expression: self.expression(), - r_paren_token: self.r_paren_token(), + pub fn as_fields(&self) -> SvelteAwaitThenClauseFields { + SvelteAwaitThenClauseFields { + then_token: self.then_token(), + name: self.name(), } } - pub fn l_paren_token(&self) -> SyntaxResult { + pub fn then_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn expression(&self) -> SyntaxResult { + pub fn name(&self) -> SyntaxResult { support::required_node(&self.syntax, 1usize) } - pub fn r_paren_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 2usize) - } } -impl Serialize for SvelteEachKey { +impl Serialize for SvelteAwaitThenClause { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1224,16 +1240,15 @@ impl Serialize for SvelteEachKey { } } #[derive(Serialize)] -pub struct SvelteEachKeyFields { - pub l_paren_token: SyntaxResult, - pub expression: SyntaxResult, - pub r_paren_token: SyntaxResult, +pub struct SvelteAwaitThenClauseFields { + pub then_token: SyntaxResult, + pub name: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachKeyedItem { +pub struct SvelteConstBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteEachKeyedItem { +impl SvelteConstBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1243,16 +1258,28 @@ impl SvelteEachKeyedItem { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachKeyedItemFields { - SvelteEachKeyedItemFields { - index: self.index(), + pub fn as_fields(&self) -> SvelteConstBlockFields { + SvelteConstBlockFields { + sv_curly_at_token: self.sv_curly_at_token(), + const_token: self.const_token(), + expression: self.expression(), + r_curly_token: self.r_curly_token(), } } - pub fn index(&self) -> Option { - support::node(&self.syntax, 0usize) + pub fn sv_curly_at_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn const_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) } } -impl Serialize for SvelteEachKeyedItem { +impl Serialize for SvelteConstBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1261,14 +1288,17 @@ impl Serialize for SvelteEachKeyedItem { } } #[derive(Serialize)] -pub struct SvelteEachKeyedItemFields { - pub index: Option, +pub struct SvelteConstBlockFields { + pub sv_curly_at_token: SyntaxResult, + pub const_token: SyntaxResult, + pub expression: SyntaxResult, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteEachOpeningBlock { +pub struct SvelteDebugBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteEachOpeningBlock { +impl SvelteDebugBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1278,32 +1308,28 @@ impl SvelteEachOpeningBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteEachOpeningBlockFields { - SvelteEachOpeningBlockFields { - sv_curly_hash_token: self.sv_curly_hash_token(), - each_token: self.each_token(), - list: self.list(), - item: self.item(), + pub fn as_fields(&self) -> SvelteDebugBlockFields { + SvelteDebugBlockFields { + sv_curly_at_token: self.sv_curly_at_token(), + debug_token: self.debug_token(), + bindings: self.bindings(), r_curly_token: self.r_curly_token(), } } - pub fn sv_curly_hash_token(&self) -> SyntaxResult { + pub fn sv_curly_at_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn each_token(&self) -> SyntaxResult { + pub fn debug_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } - pub fn list(&self) -> SyntaxResult { - support::required_node(&self.syntax, 2usize) - } - pub fn item(&self) -> Option { - support::node(&self.syntax, 3usize) + pub fn bindings(&self) -> SvelteBindingList { + support::list(&self.syntax, 2usize) } pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 4usize) + support::required_token(&self.syntax, 3usize) } } -impl Serialize for SvelteEachOpeningBlock { +impl Serialize for SvelteDebugBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1312,18 +1338,17 @@ impl Serialize for SvelteEachOpeningBlock { } } #[derive(Serialize)] -pub struct SvelteEachOpeningBlockFields { - pub sv_curly_hash_token: SyntaxResult, - pub each_token: SyntaxResult, - pub list: SyntaxResult, - pub item: Option, - pub r_curly_token: SyntaxResult, +pub struct SvelteDebugBlockFields { + pub sv_curly_at_token: SyntaxResult, + pub debug_token: SyntaxResult, + pub bindings: SvelteBindingList, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteElseClause { +pub struct SvelteEachAsKeyedItem { pub(crate) syntax: SyntaxNode, } -impl SvelteElseClause { +impl SvelteEachAsKeyedItem { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1333,28 +1358,28 @@ impl SvelteElseClause { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteElseClauseFields { - SvelteElseClauseFields { - sv_curly_colon_token: self.sv_curly_colon_token(), - else_token: self.else_token(), - r_curly_token: self.r_curly_token(), - children: self.children(), + pub fn as_fields(&self) -> SvelteEachAsKeyedItemFields { + SvelteEachAsKeyedItemFields { + as_token: self.as_token(), + name: self.name(), + index: self.index(), + key: self.key(), } } - pub fn sv_curly_colon_token(&self) -> SyntaxResult { + pub fn as_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn else_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 1usize) + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) } - pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 2usize) + pub fn index(&self) -> Option { + support::node(&self.syntax, 2usize) } - pub fn children(&self) -> HtmlElementList { - support::list(&self.syntax, 3usize) + pub fn key(&self) -> Option { + support::node(&self.syntax, 3usize) } } -impl Serialize for SvelteElseClause { +impl Serialize for SvelteEachAsKeyedItem { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1363,17 +1388,17 @@ impl Serialize for SvelteElseClause { } } #[derive(Serialize)] -pub struct SvelteElseClauseFields { - pub sv_curly_colon_token: SyntaxResult, - pub else_token: SyntaxResult, - pub r_curly_token: SyntaxResult, - pub children: HtmlElementList, +pub struct SvelteEachAsKeyedItemFields { + pub as_token: SyntaxResult, + pub name: SyntaxResult, + pub index: Option, + pub key: Option, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteElseIfClause { +pub struct SvelteEachBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteElseIfClause { +impl SvelteEachBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1383,36 +1408,28 @@ impl SvelteElseIfClause { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteElseIfClauseFields { - SvelteElseIfClauseFields { - sv_curly_colon_token: self.sv_curly_colon_token(), - else_token: self.else_token(), - if_token: self.if_token(), - expression: self.expression(), - r_curly_token: self.r_curly_token(), + pub fn as_fields(&self) -> SvelteEachBlockFields { + SvelteEachBlockFields { + opening_block: self.opening_block(), children: self.children(), + else_clause: self.else_clause(), + closing_block: self.closing_block(), } } - pub fn sv_curly_colon_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 0usize) + pub fn opening_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) } - pub fn else_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 1usize) + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 1usize) } - pub fn if_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 2usize) + pub fn else_clause(&self) -> Option { + support::node(&self.syntax, 2usize) } - pub fn expression(&self) -> SyntaxResult { + pub fn closing_block(&self) -> SyntaxResult { support::required_node(&self.syntax, 3usize) } - pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 4usize) - } - pub fn children(&self) -> HtmlElementList { - support::list(&self.syntax, 5usize) - } } -impl Serialize for SvelteElseIfClause { +impl Serialize for SvelteEachBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1421,19 +1438,17 @@ impl Serialize for SvelteElseIfClause { } } #[derive(Serialize)] -pub struct SvelteElseIfClauseFields { - pub sv_curly_colon_token: SyntaxResult, - pub else_token: SyntaxResult, - pub if_token: SyntaxResult, - pub expression: SyntaxResult, - pub r_curly_token: SyntaxResult, +pub struct SvelteEachBlockFields { + pub opening_block: SyntaxResult, pub children: HtmlElementList, + pub else_clause: Option, + pub closing_block: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteHtmlBlock { +pub struct SvelteEachClosingBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteHtmlBlock { +impl SvelteEachClosingBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1443,28 +1458,24 @@ impl SvelteHtmlBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteHtmlBlockFields { - SvelteHtmlBlockFields { - sv_curly_at_token: self.sv_curly_at_token(), - html_token: self.html_token(), - expression: self.expression(), + pub fn as_fields(&self) -> SvelteEachClosingBlockFields { + SvelteEachClosingBlockFields { + sv_curly_slash_token: self.sv_curly_slash_token(), + each_token: self.each_token(), r_curly_token: self.r_curly_token(), } } - pub fn sv_curly_at_token(&self) -> SyntaxResult { + pub fn sv_curly_slash_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn html_token(&self) -> SyntaxResult { + pub fn each_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } - pub fn expression(&self) -> SyntaxResult { - support::required_node(&self.syntax, 2usize) - } pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 3usize) + support::required_token(&self.syntax, 2usize) } } -impl Serialize for SvelteHtmlBlock { +impl Serialize for SvelteEachClosingBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1473,17 +1484,16 @@ impl Serialize for SvelteHtmlBlock { } } #[derive(Serialize)] -pub struct SvelteHtmlBlockFields { - pub sv_curly_at_token: SyntaxResult, - pub html_token: SyntaxResult, - pub expression: SyntaxResult, +pub struct SvelteEachClosingBlockFields { + pub sv_curly_slash_token: SyntaxResult, + pub each_token: SyntaxResult, pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteIfBlock { +pub struct SvelteEachIndex { pub(crate) syntax: SyntaxNode, } -impl SvelteIfBlock { +impl SvelteEachIndex { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1493,28 +1503,20 @@ impl SvelteIfBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteIfBlockFields { - SvelteIfBlockFields { - opening_block: self.opening_block(), - else_if_clauses: self.else_if_clauses(), - else_clause: self.else_clause(), - closing_block: self.closing_block(), + pub fn as_fields(&self) -> SvelteEachIndexFields { + SvelteEachIndexFields { + comma_token: self.comma_token(), + value: self.value(), } } - pub fn opening_block(&self) -> SyntaxResult { - support::required_node(&self.syntax, 0usize) - } - pub fn else_if_clauses(&self) -> SvelteElseIfClauseList { - support::list(&self.syntax, 1usize) - } - pub fn else_clause(&self) -> Option { - support::node(&self.syntax, 2usize) + pub fn comma_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn closing_block(&self) -> SyntaxResult { - support::required_node(&self.syntax, 3usize) + pub fn value(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) } } -impl Serialize for SvelteIfBlock { +impl Serialize for SvelteEachIndex { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1523,17 +1525,15 @@ impl Serialize for SvelteIfBlock { } } #[derive(Serialize)] -pub struct SvelteIfBlockFields { - pub opening_block: SyntaxResult, - pub else_if_clauses: SvelteElseIfClauseList, - pub else_clause: Option, - pub closing_block: SyntaxResult, +pub struct SvelteEachIndexFields { + pub comma_token: SyntaxResult, + pub value: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteIfClosingBlock { +pub struct SvelteEachKey { pub(crate) syntax: SyntaxNode, } -impl SvelteIfClosingBlock { +impl SvelteEachKey { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1543,24 +1543,24 @@ impl SvelteIfClosingBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteIfClosingBlockFields { - SvelteIfClosingBlockFields { - sv_curly_slash_token: self.sv_curly_slash_token(), - if_token: self.if_token(), - r_curly_token: self.r_curly_token(), + pub fn as_fields(&self) -> SvelteEachKeyFields { + SvelteEachKeyFields { + l_paren_token: self.l_paren_token(), + expression: self.expression(), + r_paren_token: self.r_paren_token(), } } - pub fn sv_curly_slash_token(&self) -> SyntaxResult { + pub fn l_paren_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn if_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 1usize) + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) } - pub fn r_curly_token(&self) -> SyntaxResult { + pub fn r_paren_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 2usize) } } -impl Serialize for SvelteIfClosingBlock { +impl Serialize for SvelteEachKey { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1569,16 +1569,16 @@ impl Serialize for SvelteIfClosingBlock { } } #[derive(Serialize)] -pub struct SvelteIfClosingBlockFields { - pub sv_curly_slash_token: SyntaxResult, - pub if_token: SyntaxResult, - pub r_curly_token: SyntaxResult, +pub struct SvelteEachKeyFields { + pub l_paren_token: SyntaxResult, + pub expression: SyntaxResult, + pub r_paren_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteIfOpeningBlock { +pub struct SvelteEachKeyedItem { pub(crate) syntax: SyntaxNode, } -impl SvelteIfOpeningBlock { +impl SvelteEachKeyedItem { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1588,32 +1588,16 @@ impl SvelteIfOpeningBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteIfOpeningBlockFields { - SvelteIfOpeningBlockFields { - sv_curly_hash_token: self.sv_curly_hash_token(), - if_token: self.if_token(), - expression: self.expression(), - r_curly_token: self.r_curly_token(), - children: self.children(), + pub fn as_fields(&self) -> SvelteEachKeyedItemFields { + SvelteEachKeyedItemFields { + index: self.index(), } } - pub fn sv_curly_hash_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 0usize) - } - pub fn if_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 1usize) - } - pub fn expression(&self) -> SyntaxResult { - support::required_node(&self.syntax, 2usize) - } - pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 3usize) - } - pub fn children(&self) -> HtmlElementList { - support::list(&self.syntax, 4usize) + pub fn index(&self) -> Option { + support::node(&self.syntax, 0usize) } } -impl Serialize for SvelteIfOpeningBlock { +impl Serialize for SvelteEachKeyedItem { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1622,18 +1606,14 @@ impl Serialize for SvelteIfOpeningBlock { } } #[derive(Serialize)] -pub struct SvelteIfOpeningBlockFields { - pub sv_curly_hash_token: SyntaxResult, - pub if_token: SyntaxResult, - pub expression: SyntaxResult, - pub r_curly_token: SyntaxResult, - pub children: HtmlElementList, +pub struct SvelteEachKeyedItemFields { + pub index: Option, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteKeyBlock { +pub struct SvelteEachOpeningBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteKeyBlock { +impl SvelteEachOpeningBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1643,24 +1623,32 @@ impl SvelteKeyBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteKeyBlockFields { - SvelteKeyBlockFields { - opening_block: self.opening_block(), - children: self.children(), - closing_block: self.closing_block(), + pub fn as_fields(&self) -> SvelteEachOpeningBlockFields { + SvelteEachOpeningBlockFields { + sv_curly_hash_token: self.sv_curly_hash_token(), + each_token: self.each_token(), + list: self.list(), + item: self.item(), + r_curly_token: self.r_curly_token(), } } - pub fn opening_block(&self) -> SyntaxResult { - support::required_node(&self.syntax, 0usize) + pub fn sv_curly_hash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn children(&self) -> HtmlElementList { - support::list(&self.syntax, 1usize) + pub fn each_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) } - pub fn closing_block(&self) -> SyntaxResult { + pub fn list(&self) -> SyntaxResult { support::required_node(&self.syntax, 2usize) } + pub fn item(&self) -> Option { + support::node(&self.syntax, 3usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 4usize) + } } -impl Serialize for SvelteKeyBlock { +impl Serialize for SvelteEachOpeningBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1669,16 +1657,18 @@ impl Serialize for SvelteKeyBlock { } } #[derive(Serialize)] -pub struct SvelteKeyBlockFields { - pub opening_block: SyntaxResult, - pub children: HtmlElementList, - pub closing_block: SyntaxResult, +pub struct SvelteEachOpeningBlockFields { + pub sv_curly_hash_token: SyntaxResult, + pub each_token: SyntaxResult, + pub list: SyntaxResult, + pub item: Option, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteKeyClosingBlock { +pub struct SvelteElseClause { pub(crate) syntax: SyntaxNode, } -impl SvelteKeyClosingBlock { +impl SvelteElseClause { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1688,24 +1678,28 @@ impl SvelteKeyClosingBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteKeyClosingBlockFields { - SvelteKeyClosingBlockFields { - sv_curly_slash_token: self.sv_curly_slash_token(), - key_token: self.key_token(), + pub fn as_fields(&self) -> SvelteElseClauseFields { + SvelteElseClauseFields { + sv_curly_colon_token: self.sv_curly_colon_token(), + else_token: self.else_token(), r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn sv_curly_slash_token(&self) -> SyntaxResult { + pub fn sv_curly_colon_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn key_token(&self) -> SyntaxResult { + pub fn else_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } pub fn r_curly_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 2usize) } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 3usize) + } } -impl Serialize for SvelteKeyClosingBlock { +impl Serialize for SvelteElseClause { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1714,16 +1708,17 @@ impl Serialize for SvelteKeyClosingBlock { } } #[derive(Serialize)] -pub struct SvelteKeyClosingBlockFields { - pub sv_curly_slash_token: SyntaxResult, - pub key_token: SyntaxResult, +pub struct SvelteElseClauseFields { + pub sv_curly_colon_token: SyntaxResult, + pub else_token: SyntaxResult, pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteKeyOpeningBlock { +pub struct SvelteElseIfClause { pub(crate) syntax: SyntaxNode, } -impl SvelteKeyOpeningBlock { +impl SvelteElseIfClause { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1733,28 +1728,36 @@ impl SvelteKeyOpeningBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteKeyOpeningBlockFields { - SvelteKeyOpeningBlockFields { - sv_curly_hash_token: self.sv_curly_hash_token(), - key_token: self.key_token(), + pub fn as_fields(&self) -> SvelteElseIfClauseFields { + SvelteElseIfClauseFields { + sv_curly_colon_token: self.sv_curly_colon_token(), + else_token: self.else_token(), + if_token: self.if_token(), expression: self.expression(), r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn sv_curly_hash_token(&self) -> SyntaxResult { + pub fn sv_curly_colon_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn key_token(&self) -> SyntaxResult { + pub fn else_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } + pub fn if_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 2usize) + } pub fn expression(&self) -> SyntaxResult { - support::required_node(&self.syntax, 2usize) + support::required_node(&self.syntax, 3usize) } pub fn r_curly_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 3usize) + support::required_token(&self.syntax, 4usize) + } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 5usize) } } -impl Serialize for SvelteKeyOpeningBlock { +impl Serialize for SvelteElseIfClause { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1763,52 +1766,19 @@ impl Serialize for SvelteKeyOpeningBlock { } } #[derive(Serialize)] -pub struct SvelteKeyOpeningBlockFields { - pub sv_curly_hash_token: SyntaxResult, - pub key_token: SyntaxResult, +pub struct SvelteElseIfClauseFields { + pub sv_curly_colon_token: SyntaxResult, + pub else_token: SyntaxResult, + pub if_token: SyntaxResult, pub expression: SyntaxResult, pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteName { - pub(crate) syntax: SyntaxNode, -} -impl SvelteName { - #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] - #[doc = r""] - #[doc = r" # Safety"] - #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] - #[doc = r" or a match on [SyntaxNode::kind]"] - #[inline] - pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { - Self { syntax } - } - pub fn as_fields(&self) -> SvelteNameFields { - SvelteNameFields { - ident_token: self.ident_token(), - } - } - pub fn ident_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 0usize) - } -} -impl Serialize for SvelteName { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.as_fields().serialize(serializer) - } -} -#[derive(Serialize)] -pub struct SvelteNameFields { - pub ident_token: SyntaxResult, -} -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct SvelteRenderBlock { +pub struct SvelteHtmlBlock { pub(crate) syntax: SyntaxNode, } -impl SvelteRenderBlock { +impl SvelteHtmlBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1818,10 +1788,10 @@ impl SvelteRenderBlock { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> SvelteRenderBlockFields { - SvelteRenderBlockFields { + pub fn as_fields(&self) -> SvelteHtmlBlockFields { + SvelteHtmlBlockFields { sv_curly_at_token: self.sv_curly_at_token(), - render_token: self.render_token(), + html_token: self.html_token(), expression: self.expression(), r_curly_token: self.r_curly_token(), } @@ -1829,7 +1799,7 @@ impl SvelteRenderBlock { pub fn sv_curly_at_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn render_token(&self) -> SyntaxResult { + pub fn html_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } pub fn expression(&self) -> SyntaxResult { @@ -1839,7 +1809,7 @@ impl SvelteRenderBlock { support::required_token(&self.syntax, 3usize) } } -impl Serialize for SvelteRenderBlock { +impl Serialize for SvelteHtmlBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1848,17 +1818,17 @@ impl Serialize for SvelteRenderBlock { } } #[derive(Serialize)] -pub struct SvelteRenderBlockFields { +pub struct SvelteHtmlBlockFields { pub sv_curly_at_token: SyntaxResult, - pub render_token: SyntaxResult, + pub html_token: SyntaxResult, pub expression: SyntaxResult, pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueDirective { +pub struct SvelteIfBlock { pub(crate) syntax: SyntaxNode, } -impl VueDirective { +impl SvelteIfBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1868,28 +1838,28 @@ impl VueDirective { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueDirectiveFields { - VueDirectiveFields { - name_token: self.name_token(), - arg: self.arg(), - modifiers: self.modifiers(), - initializer: self.initializer(), + pub fn as_fields(&self) -> SvelteIfBlockFields { + SvelteIfBlockFields { + opening_block: self.opening_block(), + else_if_clauses: self.else_if_clauses(), + else_clause: self.else_clause(), + closing_block: self.closing_block(), } } - pub fn name_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 0usize) + pub fn opening_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) } - pub fn arg(&self) -> Option { - support::node(&self.syntax, 1usize) + pub fn else_if_clauses(&self) -> SvelteElseIfClauseList { + support::list(&self.syntax, 1usize) } - pub fn modifiers(&self) -> VueModifierList { - support::list(&self.syntax, 2usize) + pub fn else_clause(&self) -> Option { + support::node(&self.syntax, 2usize) } - pub fn initializer(&self) -> Option { - support::node(&self.syntax, 3usize) + pub fn closing_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 3usize) } } -impl Serialize for VueDirective { +impl Serialize for SvelteIfBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1898,17 +1868,17 @@ impl Serialize for VueDirective { } } #[derive(Serialize)] -pub struct VueDirectiveFields { - pub name_token: SyntaxResult, - pub arg: Option, - pub modifiers: VueModifierList, - pub initializer: Option, +pub struct SvelteIfBlockFields { + pub opening_block: SyntaxResult, + pub else_if_clauses: SvelteElseIfClauseList, + pub else_clause: Option, + pub closing_block: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueDirectiveArgument { +pub struct SvelteIfClosingBlock { pub(crate) syntax: SyntaxNode, } -impl VueDirectiveArgument { +impl SvelteIfClosingBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1918,20 +1888,24 @@ impl VueDirectiveArgument { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueDirectiveArgumentFields { - VueDirectiveArgumentFields { - colon_token: self.colon_token(), - arg: self.arg(), + pub fn as_fields(&self) -> SvelteIfClosingBlockFields { + SvelteIfClosingBlockFields { + sv_curly_slash_token: self.sv_curly_slash_token(), + if_token: self.if_token(), + r_curly_token: self.r_curly_token(), } } - pub fn colon_token(&self) -> SyntaxResult { + pub fn sv_curly_slash_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn arg(&self) -> SyntaxResult { - support::required_node(&self.syntax, 1usize) + pub fn if_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 2usize) } } -impl Serialize for VueDirectiveArgument { +impl Serialize for SvelteIfClosingBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1940,15 +1914,16 @@ impl Serialize for VueDirectiveArgument { } } #[derive(Serialize)] -pub struct VueDirectiveArgumentFields { - pub colon_token: SyntaxResult, - pub arg: SyntaxResult, +pub struct SvelteIfClosingBlockFields { + pub sv_curly_slash_token: SyntaxResult, + pub if_token: SyntaxResult, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueDynamicArgument { +pub struct SvelteIfOpeningBlock { pub(crate) syntax: SyntaxNode, } -impl VueDynamicArgument { +impl SvelteIfOpeningBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -1958,24 +1933,32 @@ impl VueDynamicArgument { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueDynamicArgumentFields { - VueDynamicArgumentFields { - l_brack_token: self.l_brack_token(), - name_token: self.name_token(), - r_brack_token: self.r_brack_token(), + pub fn as_fields(&self) -> SvelteIfOpeningBlockFields { + SvelteIfOpeningBlockFields { + sv_curly_hash_token: self.sv_curly_hash_token(), + if_token: self.if_token(), + expression: self.expression(), + r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn l_brack_token(&self) -> SyntaxResult { + pub fn sv_curly_hash_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn name_token(&self) -> SyntaxResult { + pub fn if_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 1usize) } - pub fn r_brack_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 2usize) + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 4usize) } } -impl Serialize for VueDynamicArgument { +impl Serialize for SvelteIfOpeningBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -1984,16 +1967,18 @@ impl Serialize for VueDynamicArgument { } } #[derive(Serialize)] -pub struct VueDynamicArgumentFields { - pub l_brack_token: SyntaxResult, - pub name_token: SyntaxResult, - pub r_brack_token: SyntaxResult, -} +pub struct SvelteIfOpeningBlockFields { + pub sv_curly_hash_token: SyntaxResult, + pub if_token: SyntaxResult, + pub expression: SyntaxResult, + pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, +} #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueModifier { +pub struct SvelteKeyBlock { pub(crate) syntax: SyntaxNode, } -impl VueModifier { +impl SvelteKeyBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -2003,20 +1988,24 @@ impl VueModifier { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueModifierFields { - VueModifierFields { - dot_token: self.dot_token(), - modifier_token: self.modifier_token(), + pub fn as_fields(&self) -> SvelteKeyBlockFields { + SvelteKeyBlockFields { + opening_block: self.opening_block(), + children: self.children(), + closing_block: self.closing_block(), } } - pub fn dot_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 0usize) + pub fn opening_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) } - pub fn modifier_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 1usize) + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 1usize) + } + pub fn closing_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) } } -impl Serialize for VueModifier { +impl Serialize for SvelteKeyBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -2025,15 +2014,16 @@ impl Serialize for VueModifier { } } #[derive(Serialize)] -pub struct VueModifierFields { - pub dot_token: SyntaxResult, - pub modifier_token: SyntaxResult, +pub struct SvelteKeyBlockFields { + pub opening_block: SyntaxResult, + pub children: HtmlElementList, + pub closing_block: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueStaticArgument { +pub struct SvelteKeyClosingBlock { pub(crate) syntax: SyntaxNode, } -impl VueStaticArgument { +impl SvelteKeyClosingBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -2043,16 +2033,24 @@ impl VueStaticArgument { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueStaticArgumentFields { - VueStaticArgumentFields { - name_token: self.name_token(), + pub fn as_fields(&self) -> SvelteKeyClosingBlockFields { + SvelteKeyClosingBlockFields { + sv_curly_slash_token: self.sv_curly_slash_token(), + key_token: self.key_token(), + r_curly_token: self.r_curly_token(), } } - pub fn name_token(&self) -> SyntaxResult { + pub fn sv_curly_slash_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } + pub fn key_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 2usize) + } } -impl Serialize for VueStaticArgument { +impl Serialize for SvelteKeyClosingBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -2061,14 +2059,16 @@ impl Serialize for VueStaticArgument { } } #[derive(Serialize)] -pub struct VueStaticArgumentFields { - pub name_token: SyntaxResult, +pub struct SvelteKeyClosingBlockFields { + pub sv_curly_slash_token: SyntaxResult, + pub key_token: SyntaxResult, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueVBindShorthandDirective { +pub struct SvelteKeyOpeningBlock { pub(crate) syntax: SyntaxNode, } -impl VueVBindShorthandDirective { +impl SvelteKeyOpeningBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -2078,24 +2078,28 @@ impl VueVBindShorthandDirective { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueVBindShorthandDirectiveFields { - VueVBindShorthandDirectiveFields { - arg: self.arg(), - modifiers: self.modifiers(), - initializer: self.initializer(), + pub fn as_fields(&self) -> SvelteKeyOpeningBlockFields { + SvelteKeyOpeningBlockFields { + sv_curly_hash_token: self.sv_curly_hash_token(), + key_token: self.key_token(), + expression: self.expression(), + r_curly_token: self.r_curly_token(), } } - pub fn arg(&self) -> SyntaxResult { - support::required_node(&self.syntax, 0usize) + pub fn sv_curly_hash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn modifiers(&self) -> VueModifierList { - support::list(&self.syntax, 1usize) + pub fn key_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) } - pub fn initializer(&self) -> Option { - support::node(&self.syntax, 2usize) + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) } } -impl Serialize for VueVBindShorthandDirective { +impl Serialize for SvelteKeyOpeningBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -2104,16 +2108,17 @@ impl Serialize for VueVBindShorthandDirective { } } #[derive(Serialize)] -pub struct VueVBindShorthandDirectiveFields { - pub arg: SyntaxResult, - pub modifiers: VueModifierList, - pub initializer: Option, +pub struct SvelteKeyOpeningBlockFields { + pub sv_curly_hash_token: SyntaxResult, + pub key_token: SyntaxResult, + pub expression: SyntaxResult, + pub r_curly_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueVOnShorthandDirective { +pub struct SvelteName { pub(crate) syntax: SyntaxNode, } -impl VueVOnShorthandDirective { +impl SvelteName { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -2123,28 +2128,16 @@ impl VueVOnShorthandDirective { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueVOnShorthandDirectiveFields { - VueVOnShorthandDirectiveFields { - at_token: self.at_token(), - arg: self.arg(), - modifiers: self.modifiers(), - initializer: self.initializer(), + pub fn as_fields(&self) -> SvelteNameFields { + SvelteNameFields { + ident_token: self.ident_token(), } } - pub fn at_token(&self) -> SyntaxResult { + pub fn ident_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn arg(&self) -> SyntaxResult { - support::required_node(&self.syntax, 1usize) - } - pub fn modifiers(&self) -> VueModifierList { - support::list(&self.syntax, 2usize) - } - pub fn initializer(&self) -> Option { - support::node(&self.syntax, 3usize) - } } -impl Serialize for VueVOnShorthandDirective { +impl Serialize for SvelteName { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -2153,17 +2146,14 @@ impl Serialize for VueVOnShorthandDirective { } } #[derive(Serialize)] -pub struct VueVOnShorthandDirectiveFields { - pub at_token: SyntaxResult, - pub arg: SyntaxResult, - pub modifiers: VueModifierList, - pub initializer: Option, +pub struct SvelteNameFields { + pub ident_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct VueVSlotShorthandDirective { +pub struct SvelteRenderBlock { pub(crate) syntax: SyntaxNode, } -impl VueVSlotShorthandDirective { +impl SvelteRenderBlock { #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] #[doc = r""] #[doc = r" # Safety"] @@ -2173,28 +2163,28 @@ impl VueVSlotShorthandDirective { pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { Self { syntax } } - pub fn as_fields(&self) -> VueVSlotShorthandDirectiveFields { - VueVSlotShorthandDirectiveFields { - hash_token: self.hash_token(), - arg: self.arg(), - modifiers: self.modifiers(), - initializer: self.initializer(), + pub fn as_fields(&self) -> SvelteRenderBlockFields { + SvelteRenderBlockFields { + sv_curly_at_token: self.sv_curly_at_token(), + render_token: self.render_token(), + expression: self.expression(), + r_curly_token: self.r_curly_token(), } } - pub fn hash_token(&self) -> SyntaxResult { + pub fn sv_curly_at_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn arg(&self) -> SyntaxResult { - support::required_node(&self.syntax, 1usize) + pub fn render_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) } - pub fn modifiers(&self) -> VueModifierList { - support::list(&self.syntax, 2usize) + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) } - pub fn initializer(&self) -> Option { - support::node(&self.syntax, 3usize) + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) } } -impl Serialize for VueVSlotShorthandDirective { +impl Serialize for SvelteRenderBlock { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -2203,348 +2193,1254 @@ impl Serialize for VueVSlotShorthandDirective { } } #[derive(Serialize)] -pub struct VueVSlotShorthandDirectiveFields { - pub hash_token: SyntaxResult, - pub arg: SyntaxResult, - pub modifiers: VueModifierList, - pub initializer: Option, +pub struct SvelteRenderBlockFields { + pub sv_curly_at_token: SyntaxResult, + pub render_token: SyntaxResult, + pub expression: SyntaxResult, + pub r_curly_token: SyntaxResult, } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyAstroFrontmatterElement { - AstroBogusFrontmatter(AstroBogusFrontmatter), - AstroFrontmatterElement(AstroFrontmatterElement), +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct SvelteSnippetBlock { + pub(crate) syntax: SyntaxNode, } -impl AnyAstroFrontmatterElement { - pub fn as_astro_bogus_frontmatter(&self) -> Option<&AstroBogusFrontmatter> { - match &self { - Self::AstroBogusFrontmatter(item) => Some(item), - _ => None, - } +impl SvelteSnippetBlock { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_astro_frontmatter_element(&self) -> Option<&AstroFrontmatterElement> { - match &self { - Self::AstroFrontmatterElement(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> SvelteSnippetBlockFields { + SvelteSnippetBlockFields { + opening_block: self.opening_block(), + closing_block: self.closing_block(), } } + pub fn opening_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) + } + pub fn closing_block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyHtmlAttribute { - AnyVueDirective(AnyVueDirective), - HtmlAttribute(HtmlAttribute), - HtmlBogusAttribute(HtmlBogusAttribute), - HtmlDoubleTextExpression(HtmlDoubleTextExpression), - HtmlSingleTextExpression(HtmlSingleTextExpression), - SvelteAttachAttribute(SvelteAttachAttribute), +impl Serialize for SvelteSnippetBlock { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } } -impl AnyHtmlAttribute { - pub fn as_any_vue_directive(&self) -> Option<&AnyVueDirective> { - match &self { - Self::AnyVueDirective(item) => Some(item), - _ => None, - } +#[derive(Serialize)] +pub struct SvelteSnippetBlockFields { + pub opening_block: SyntaxResult, + pub closing_block: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct SvelteSnippetClosingBlock { + pub(crate) syntax: SyntaxNode, +} +impl SvelteSnippetClosingBlock { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_html_attribute(&self) -> Option<&HtmlAttribute> { - match &self { - Self::HtmlAttribute(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> SvelteSnippetClosingBlockFields { + SvelteSnippetClosingBlockFields { + sv_curly_slash_token: self.sv_curly_slash_token(), + snippet_token: self.snippet_token(), + r_curly_token: self.r_curly_token(), } } - pub fn as_html_bogus_attribute(&self) -> Option<&HtmlBogusAttribute> { - match &self { - Self::HtmlBogusAttribute(item) => Some(item), - _ => None, - } - } - pub fn as_html_double_text_expression(&self) -> Option<&HtmlDoubleTextExpression> { - match &self { - Self::HtmlDoubleTextExpression(item) => Some(item), - _ => None, - } + pub fn sv_curly_slash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn as_html_single_text_expression(&self) -> Option<&HtmlSingleTextExpression> { - match &self { - Self::HtmlSingleTextExpression(item) => Some(item), - _ => None, - } + pub fn snippet_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) } - pub fn as_svelte_attach_attribute(&self) -> Option<&SvelteAttachAttribute> { - match &self { - Self::SvelteAttachAttribute(item) => Some(item), - _ => None, - } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 2usize) } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyHtmlAttributeInitializer { - HtmlSingleTextExpression(HtmlSingleTextExpression), - HtmlString(HtmlString), -} -impl AnyHtmlAttributeInitializer { - pub fn as_html_single_text_expression(&self) -> Option<&HtmlSingleTextExpression> { - match &self { - Self::HtmlSingleTextExpression(item) => Some(item), - _ => None, - } - } - pub fn as_html_string(&self) -> Option<&HtmlString> { - match &self { - Self::HtmlString(item) => Some(item), - _ => None, - } +impl Serialize for SvelteSnippetClosingBlock { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyHtmlContent { - AnyHtmlTextExpression(AnyHtmlTextExpression), - HtmlContent(HtmlContent), - HtmlEmbeddedContent(HtmlEmbeddedContent), +#[derive(Serialize)] +pub struct SvelteSnippetClosingBlockFields { + pub sv_curly_slash_token: SyntaxResult, + pub snippet_token: SyntaxResult, + pub r_curly_token: SyntaxResult, } -impl AnyHtmlContent { - pub fn as_any_html_text_expression(&self) -> Option<&AnyHtmlTextExpression> { - match &self { - Self::AnyHtmlTextExpression(item) => Some(item), - _ => None, - } +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct SvelteSnippetOpeningBlock { + pub(crate) syntax: SyntaxNode, +} +impl SvelteSnippetOpeningBlock { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_html_content(&self) -> Option<&HtmlContent> { - match &self { - Self::HtmlContent(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> SvelteSnippetOpeningBlockFields { + SvelteSnippetOpeningBlockFields { + sv_curly_hash_token: self.sv_curly_hash_token(), + snippet_token: self.snippet_token(), + expression: self.expression(), + r_curly_token: self.r_curly_token(), + children: self.children(), } } - pub fn as_html_embedded_content(&self) -> Option<&HtmlEmbeddedContent> { - match &self { - Self::HtmlEmbeddedContent(item) => Some(item), - _ => None, - } + pub fn sv_curly_hash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } -} -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyHtmlElement { - AnyHtmlContent(AnyHtmlContent), - HtmlBogusElement(HtmlBogusElement), - HtmlCdataSection(HtmlCdataSection), - HtmlElement(HtmlElement), - HtmlSelfClosingElement(HtmlSelfClosingElement), -} -impl AnyHtmlElement { - pub fn as_any_html_content(&self) -> Option<&AnyHtmlContent> { - match &self { - Self::AnyHtmlContent(item) => Some(item), - _ => None, - } + pub fn snippet_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) } - pub fn as_html_bogus_element(&self) -> Option<&HtmlBogusElement> { - match &self { - Self::HtmlBogusElement(item) => Some(item), - _ => None, - } + pub fn expression(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) } - pub fn as_html_cdata_section(&self) -> Option<&HtmlCdataSection> { - match &self { - Self::HtmlCdataSection(item) => Some(item), - _ => None, - } + pub fn r_curly_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) } - pub fn as_html_element(&self) -> Option<&HtmlElement> { - match &self { - Self::HtmlElement(item) => Some(item), - _ => None, - } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 4usize) } - pub fn as_html_self_closing_element(&self) -> Option<&HtmlSelfClosingElement> { - match &self { - Self::HtmlSelfClosingElement(item) => Some(item), - _ => None, - } +} +impl Serialize for SvelteSnippetOpeningBlock { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyHtmlTextExpression { - AnySvelteBlock(AnySvelteBlock), - HtmlBogusTextExpression(HtmlBogusTextExpression), - HtmlDoubleTextExpression(HtmlDoubleTextExpression), - HtmlSingleTextExpression(HtmlSingleTextExpression), +#[derive(Serialize)] +pub struct SvelteSnippetOpeningBlockFields { + pub sv_curly_hash_token: SyntaxResult, + pub snippet_token: SyntaxResult, + pub expression: SyntaxResult, + pub r_curly_token: SyntaxResult, + pub children: HtmlElementList, } -impl AnyHtmlTextExpression { - pub fn as_any_svelte_block(&self) -> Option<&AnySvelteBlock> { - match &self { - Self::AnySvelteBlock(item) => Some(item), - _ => None, - } +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueDirective { + pub(crate) syntax: SyntaxNode, +} +impl VueDirective { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_html_bogus_text_expression(&self) -> Option<&HtmlBogusTextExpression> { - match &self { - Self::HtmlBogusTextExpression(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> VueDirectiveFields { + VueDirectiveFields { + name_token: self.name_token(), + arg: self.arg(), + modifiers: self.modifiers(), + initializer: self.initializer(), } } - pub fn as_html_double_text_expression(&self) -> Option<&HtmlDoubleTextExpression> { - match &self { - Self::HtmlDoubleTextExpression(item) => Some(item), - _ => None, - } + pub fn name_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn as_html_single_text_expression(&self) -> Option<&HtmlSingleTextExpression> { - match &self { - Self::HtmlSingleTextExpression(item) => Some(item), - _ => None, - } + pub fn arg(&self) -> Option { + support::node(&self.syntax, 1usize) + } + pub fn modifiers(&self) -> VueModifierList { + support::list(&self.syntax, 2usize) + } + pub fn initializer(&self) -> Option { + support::node(&self.syntax, 3usize) } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnySvelteBlock { - SvelteBogusBlock(SvelteBogusBlock), - SvelteConstBlock(SvelteConstBlock), - SvelteDebugBlock(SvelteDebugBlock), - SvelteEachBlock(SvelteEachBlock), - SvelteHtmlBlock(SvelteHtmlBlock), - SvelteIfBlock(SvelteIfBlock), - SvelteKeyBlock(SvelteKeyBlock), - SvelteRenderBlock(SvelteRenderBlock), +impl Serialize for VueDirective { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } } -impl AnySvelteBlock { - pub fn as_svelte_bogus_block(&self) -> Option<&SvelteBogusBlock> { - match &self { - Self::SvelteBogusBlock(item) => Some(item), - _ => None, - } +#[derive(Serialize)] +pub struct VueDirectiveFields { + pub name_token: SyntaxResult, + pub arg: Option, + pub modifiers: VueModifierList, + pub initializer: Option, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueDirectiveArgument { + pub(crate) syntax: SyntaxNode, +} +impl VueDirectiveArgument { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_svelte_const_block(&self) -> Option<&SvelteConstBlock> { - match &self { - Self::SvelteConstBlock(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> VueDirectiveArgumentFields { + VueDirectiveArgumentFields { + colon_token: self.colon_token(), + arg: self.arg(), } } - pub fn as_svelte_debug_block(&self) -> Option<&SvelteDebugBlock> { - match &self { - Self::SvelteDebugBlock(item) => Some(item), - _ => None, - } + pub fn colon_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn as_svelte_each_block(&self) -> Option<&SvelteEachBlock> { - match &self { - Self::SvelteEachBlock(item) => Some(item), - _ => None, - } + pub fn arg(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) } - pub fn as_svelte_html_block(&self) -> Option<&SvelteHtmlBlock> { - match &self { - Self::SvelteHtmlBlock(item) => Some(item), - _ => None, - } +} +impl Serialize for VueDirectiveArgument { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) } - pub fn as_svelte_if_block(&self) -> Option<&SvelteIfBlock> { - match &self { - Self::SvelteIfBlock(item) => Some(item), - _ => None, - } +} +#[derive(Serialize)] +pub struct VueDirectiveArgumentFields { + pub colon_token: SyntaxResult, + pub arg: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueDynamicArgument { + pub(crate) syntax: SyntaxNode, +} +impl VueDynamicArgument { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_svelte_key_block(&self) -> Option<&SvelteKeyBlock> { - match &self { - Self::SvelteKeyBlock(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> VueDynamicArgumentFields { + VueDynamicArgumentFields { + l_brack_token: self.l_brack_token(), + name_token: self.name_token(), + r_brack_token: self.r_brack_token(), } } - pub fn as_svelte_render_block(&self) -> Option<&SvelteRenderBlock> { - match &self { - Self::SvelteRenderBlock(item) => Some(item), - _ => None, - } + pub fn l_brack_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn name_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn r_brack_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 2usize) } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnySvelteBlockItem { - SvelteEachAsKeyedItem(SvelteEachAsKeyedItem), - SvelteEachKeyedItem(SvelteEachKeyedItem), +impl Serialize for VueDynamicArgument { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } } -impl AnySvelteBlockItem { - pub fn as_svelte_each_as_keyed_item(&self) -> Option<&SvelteEachAsKeyedItem> { - match &self { - Self::SvelteEachAsKeyedItem(item) => Some(item), - _ => None, - } +#[derive(Serialize)] +pub struct VueDynamicArgumentFields { + pub l_brack_token: SyntaxResult, + pub name_token: SyntaxResult, + pub r_brack_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueModifier { + pub(crate) syntax: SyntaxNode, +} +impl VueModifier { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_svelte_each_keyed_item(&self) -> Option<&SvelteEachKeyedItem> { - match &self { - Self::SvelteEachKeyedItem(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> VueModifierFields { + VueModifierFields { + dot_token: self.dot_token(), + modifier_token: self.modifier_token(), } } + pub fn dot_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn modifier_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyVueDirective { - VueBogusDirective(VueBogusDirective), - VueDirective(VueDirective), - VueVBindShorthandDirective(VueVBindShorthandDirective), - VueVOnShorthandDirective(VueVOnShorthandDirective), - VueVSlotShorthandDirective(VueVSlotShorthandDirective), +impl Serialize for VueModifier { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } } -impl AnyVueDirective { - pub fn as_vue_bogus_directive(&self) -> Option<&VueBogusDirective> { - match &self { - Self::VueBogusDirective(item) => Some(item), - _ => None, - } +#[derive(Serialize)] +pub struct VueModifierFields { + pub dot_token: SyntaxResult, + pub modifier_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueStaticArgument { + pub(crate) syntax: SyntaxNode, +} +impl VueStaticArgument { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } } - pub fn as_vue_directive(&self) -> Option<&VueDirective> { - match &self { - Self::VueDirective(item) => Some(item), - _ => None, + pub fn as_fields(&self) -> VueStaticArgumentFields { + VueStaticArgumentFields { + name_token: self.name_token(), } } - pub fn as_vue_v_bind_shorthand_directive(&self) -> Option<&VueVBindShorthandDirective> { - match &self { - Self::VueVBindShorthandDirective(item) => Some(item), - _ => None, - } + pub fn name_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) } - pub fn as_vue_v_on_shorthand_directive(&self) -> Option<&VueVOnShorthandDirective> { - match &self { - Self::VueVOnShorthandDirective(item) => Some(item), - _ => None, - } +} +impl Serialize for VueStaticArgument { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) } - pub fn as_vue_v_slot_shorthand_directive(&self) -> Option<&VueVSlotShorthandDirective> { - match &self { - Self::VueVSlotShorthandDirective(item) => Some(item), - _ => None, +} +#[derive(Serialize)] +pub struct VueStaticArgumentFields { + pub name_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueVBindShorthandDirective { + pub(crate) syntax: SyntaxNode, +} +impl VueVBindShorthandDirective { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> VueVBindShorthandDirectiveFields { + VueVBindShorthandDirectiveFields { + arg: self.arg(), + modifiers: self.modifiers(), + initializer: self.initializer(), } } + pub fn arg(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) + } + pub fn modifiers(&self) -> VueModifierList { + support::list(&self.syntax, 1usize) + } + pub fn initializer(&self) -> Option { + support::node(&self.syntax, 2usize) + } } -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub enum AnyVueDirectiveArgument { - VueBogusDirectiveArgument(VueBogusDirectiveArgument), - VueDynamicArgument(VueDynamicArgument), - VueStaticArgument(VueStaticArgument), +impl Serialize for VueVBindShorthandDirective { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } } -impl AnyVueDirectiveArgument { - pub fn as_vue_bogus_directive_argument(&self) -> Option<&VueBogusDirectiveArgument> { - match &self { - Self::VueBogusDirectiveArgument(item) => Some(item), - _ => None, +#[derive(Serialize)] +pub struct VueVBindShorthandDirectiveFields { + pub arg: SyntaxResult, + pub modifiers: VueModifierList, + pub initializer: Option, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueVOnShorthandDirective { + pub(crate) syntax: SyntaxNode, +} +impl VueVOnShorthandDirective { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> VueVOnShorthandDirectiveFields { + VueVOnShorthandDirectiveFields { + at_token: self.at_token(), + arg: self.arg(), + modifiers: self.modifiers(), + initializer: self.initializer(), } } - pub fn as_vue_dynamic_argument(&self) -> Option<&VueDynamicArgument> { - match &self { - Self::VueDynamicArgument(item) => Some(item), - _ => None, - } + pub fn at_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn arg(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } + pub fn modifiers(&self) -> VueModifierList { + support::list(&self.syntax, 2usize) + } + pub fn initializer(&self) -> Option { + support::node(&self.syntax, 3usize) + } +} +impl Serialize for VueVOnShorthandDirective { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[derive(Serialize)] +pub struct VueVOnShorthandDirectiveFields { + pub at_token: SyntaxResult, + pub arg: SyntaxResult, + pub modifiers: VueModifierList, + pub initializer: Option, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VueVSlotShorthandDirective { + pub(crate) syntax: SyntaxNode, +} +impl VueVSlotShorthandDirective { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> VueVSlotShorthandDirectiveFields { + VueVSlotShorthandDirectiveFields { + hash_token: self.hash_token(), + arg: self.arg(), + modifiers: self.modifiers(), + initializer: self.initializer(), + } + } + pub fn hash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn arg(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } + pub fn modifiers(&self) -> VueModifierList { + support::list(&self.syntax, 2usize) + } + pub fn initializer(&self) -> Option { + support::node(&self.syntax, 3usize) + } +} +impl Serialize for VueVSlotShorthandDirective { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[derive(Serialize)] +pub struct VueVSlotShorthandDirectiveFields { + pub hash_token: SyntaxResult, + pub arg: SyntaxResult, + pub modifiers: VueModifierList, + pub initializer: Option, +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyAstroFrontmatterElement { + AstroBogusFrontmatter(AstroBogusFrontmatter), + AstroFrontmatterElement(AstroFrontmatterElement), +} +impl AnyAstroFrontmatterElement { + pub fn as_astro_bogus_frontmatter(&self) -> Option<&AstroBogusFrontmatter> { + match &self { + Self::AstroBogusFrontmatter(item) => Some(item), + _ => None, + } + } + pub fn as_astro_frontmatter_element(&self) -> Option<&AstroFrontmatterElement> { + match &self { + Self::AstroFrontmatterElement(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyHtmlAttribute { + AnyVueDirective(AnyVueDirective), + HtmlAttribute(HtmlAttribute), + HtmlBogusAttribute(HtmlBogusAttribute), + HtmlDoubleTextExpression(HtmlDoubleTextExpression), + HtmlSingleTextExpression(HtmlSingleTextExpression), + SvelteAttachAttribute(SvelteAttachAttribute), +} +impl AnyHtmlAttribute { + pub fn as_any_vue_directive(&self) -> Option<&AnyVueDirective> { + match &self { + Self::AnyVueDirective(item) => Some(item), + _ => None, + } + } + pub fn as_html_attribute(&self) -> Option<&HtmlAttribute> { + match &self { + Self::HtmlAttribute(item) => Some(item), + _ => None, + } + } + pub fn as_html_bogus_attribute(&self) -> Option<&HtmlBogusAttribute> { + match &self { + Self::HtmlBogusAttribute(item) => Some(item), + _ => None, + } + } + pub fn as_html_double_text_expression(&self) -> Option<&HtmlDoubleTextExpression> { + match &self { + Self::HtmlDoubleTextExpression(item) => Some(item), + _ => None, + } + } + pub fn as_html_single_text_expression(&self) -> Option<&HtmlSingleTextExpression> { + match &self { + Self::HtmlSingleTextExpression(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_attach_attribute(&self) -> Option<&SvelteAttachAttribute> { + match &self { + Self::SvelteAttachAttribute(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyHtmlAttributeInitializer { + HtmlSingleTextExpression(HtmlSingleTextExpression), + HtmlString(HtmlString), +} +impl AnyHtmlAttributeInitializer { + pub fn as_html_single_text_expression(&self) -> Option<&HtmlSingleTextExpression> { + match &self { + Self::HtmlSingleTextExpression(item) => Some(item), + _ => None, + } + } + pub fn as_html_string(&self) -> Option<&HtmlString> { + match &self { + Self::HtmlString(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyHtmlContent { + AnyHtmlTextExpression(AnyHtmlTextExpression), + HtmlContent(HtmlContent), + HtmlEmbeddedContent(HtmlEmbeddedContent), +} +impl AnyHtmlContent { + pub fn as_any_html_text_expression(&self) -> Option<&AnyHtmlTextExpression> { + match &self { + Self::AnyHtmlTextExpression(item) => Some(item), + _ => None, + } + } + pub fn as_html_content(&self) -> Option<&HtmlContent> { + match &self { + Self::HtmlContent(item) => Some(item), + _ => None, + } + } + pub fn as_html_embedded_content(&self) -> Option<&HtmlEmbeddedContent> { + match &self { + Self::HtmlEmbeddedContent(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyHtmlElement { + AnyHtmlContent(AnyHtmlContent), + HtmlBogusElement(HtmlBogusElement), + HtmlCdataSection(HtmlCdataSection), + HtmlElement(HtmlElement), + HtmlSelfClosingElement(HtmlSelfClosingElement), +} +impl AnyHtmlElement { + pub fn as_any_html_content(&self) -> Option<&AnyHtmlContent> { + match &self { + Self::AnyHtmlContent(item) => Some(item), + _ => None, + } + } + pub fn as_html_bogus_element(&self) -> Option<&HtmlBogusElement> { + match &self { + Self::HtmlBogusElement(item) => Some(item), + _ => None, + } + } + pub fn as_html_cdata_section(&self) -> Option<&HtmlCdataSection> { + match &self { + Self::HtmlCdataSection(item) => Some(item), + _ => None, + } + } + pub fn as_html_element(&self) -> Option<&HtmlElement> { + match &self { + Self::HtmlElement(item) => Some(item), + _ => None, + } + } + pub fn as_html_self_closing_element(&self) -> Option<&HtmlSelfClosingElement> { + match &self { + Self::HtmlSelfClosingElement(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyHtmlTextExpression { + AnySvelteBlock(AnySvelteBlock), + HtmlBogusTextExpression(HtmlBogusTextExpression), + HtmlDoubleTextExpression(HtmlDoubleTextExpression), + HtmlSingleTextExpression(HtmlSingleTextExpression), +} +impl AnyHtmlTextExpression { + pub fn as_any_svelte_block(&self) -> Option<&AnySvelteBlock> { + match &self { + Self::AnySvelteBlock(item) => Some(item), + _ => None, + } + } + pub fn as_html_bogus_text_expression(&self) -> Option<&HtmlBogusTextExpression> { + match &self { + Self::HtmlBogusTextExpression(item) => Some(item), + _ => None, + } + } + pub fn as_html_double_text_expression(&self) -> Option<&HtmlDoubleTextExpression> { + match &self { + Self::HtmlDoubleTextExpression(item) => Some(item), + _ => None, + } + } + pub fn as_html_single_text_expression(&self) -> Option<&HtmlSingleTextExpression> { + match &self { + Self::HtmlSingleTextExpression(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnySvelteAwaitClauses { + SvelteAwaitCatchBlock(SvelteAwaitCatchBlock), + SvelteAwaitThenBlock(SvelteAwaitThenBlock), + SvelteBogusBlock(SvelteBogusBlock), +} +impl AnySvelteAwaitClauses { + pub fn as_svelte_await_catch_block(&self) -> Option<&SvelteAwaitCatchBlock> { + match &self { + Self::SvelteAwaitCatchBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_await_then_block(&self) -> Option<&SvelteAwaitThenBlock> { + match &self { + Self::SvelteAwaitThenBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_bogus_block(&self) -> Option<&SvelteBogusBlock> { + match &self { + Self::SvelteBogusBlock(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnySvelteBlock { + SvelteAwaitBlock(SvelteAwaitBlock), + SvelteBogusBlock(SvelteBogusBlock), + SvelteConstBlock(SvelteConstBlock), + SvelteDebugBlock(SvelteDebugBlock), + SvelteEachBlock(SvelteEachBlock), + SvelteHtmlBlock(SvelteHtmlBlock), + SvelteIfBlock(SvelteIfBlock), + SvelteKeyBlock(SvelteKeyBlock), + SvelteRenderBlock(SvelteRenderBlock), + SvelteSnippetBlock(SvelteSnippetBlock), +} +impl AnySvelteBlock { + pub fn as_svelte_await_block(&self) -> Option<&SvelteAwaitBlock> { + match &self { + Self::SvelteAwaitBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_bogus_block(&self) -> Option<&SvelteBogusBlock> { + match &self { + Self::SvelteBogusBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_const_block(&self) -> Option<&SvelteConstBlock> { + match &self { + Self::SvelteConstBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_debug_block(&self) -> Option<&SvelteDebugBlock> { + match &self { + Self::SvelteDebugBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_each_block(&self) -> Option<&SvelteEachBlock> { + match &self { + Self::SvelteEachBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_html_block(&self) -> Option<&SvelteHtmlBlock> { + match &self { + Self::SvelteHtmlBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_if_block(&self) -> Option<&SvelteIfBlock> { + match &self { + Self::SvelteIfBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_key_block(&self) -> Option<&SvelteKeyBlock> { + match &self { + Self::SvelteKeyBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_render_block(&self) -> Option<&SvelteRenderBlock> { + match &self { + Self::SvelteRenderBlock(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_snippet_block(&self) -> Option<&SvelteSnippetBlock> { + match &self { + Self::SvelteSnippetBlock(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnySvelteBlockItem { + SvelteEachAsKeyedItem(SvelteEachAsKeyedItem), + SvelteEachKeyedItem(SvelteEachKeyedItem), +} +impl AnySvelteBlockItem { + pub fn as_svelte_each_as_keyed_item(&self) -> Option<&SvelteEachAsKeyedItem> { + match &self { + Self::SvelteEachAsKeyedItem(item) => Some(item), + _ => None, + } + } + pub fn as_svelte_each_keyed_item(&self) -> Option<&SvelteEachKeyedItem> { + match &self { + Self::SvelteEachKeyedItem(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyVueDirective { + VueBogusDirective(VueBogusDirective), + VueDirective(VueDirective), + VueVBindShorthandDirective(VueVBindShorthandDirective), + VueVOnShorthandDirective(VueVOnShorthandDirective), + VueVSlotShorthandDirective(VueVSlotShorthandDirective), +} +impl AnyVueDirective { + pub fn as_vue_bogus_directive(&self) -> Option<&VueBogusDirective> { + match &self { + Self::VueBogusDirective(item) => Some(item), + _ => None, + } + } + pub fn as_vue_directive(&self) -> Option<&VueDirective> { + match &self { + Self::VueDirective(item) => Some(item), + _ => None, + } + } + pub fn as_vue_v_bind_shorthand_directive(&self) -> Option<&VueVBindShorthandDirective> { + match &self { + Self::VueVBindShorthandDirective(item) => Some(item), + _ => None, + } + } + pub fn as_vue_v_on_shorthand_directive(&self) -> Option<&VueVOnShorthandDirective> { + match &self { + Self::VueVOnShorthandDirective(item) => Some(item), + _ => None, + } + } + pub fn as_vue_v_slot_shorthand_directive(&self) -> Option<&VueVSlotShorthandDirective> { + match &self { + Self::VueVSlotShorthandDirective(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyVueDirectiveArgument { + VueBogusDirectiveArgument(VueBogusDirectiveArgument), + VueDynamicArgument(VueDynamicArgument), + VueStaticArgument(VueStaticArgument), +} +impl AnyVueDirectiveArgument { + pub fn as_vue_bogus_directive_argument(&self) -> Option<&VueBogusDirectiveArgument> { + match &self { + Self::VueBogusDirectiveArgument(item) => Some(item), + _ => None, + } + } + pub fn as_vue_dynamic_argument(&self) -> Option<&VueDynamicArgument> { + match &self { + Self::VueDynamicArgument(item) => Some(item), + _ => None, + } + } + pub fn as_vue_static_argument(&self) -> Option<&VueStaticArgument> { + match &self { + Self::VueStaticArgument(item) => Some(item), + _ => None, + } + } +} +impl AstNode for AstroEmbeddedContent { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(ASTRO_EMBEDDED_CONTENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == ASTRO_EMBEDDED_CONTENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for AstroEmbeddedContent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("AstroEmbeddedContent") + .field( + "content_token", + &support::DebugOptionalElement(self.content_token()), + ) + .finish() + } else { + f.debug_struct("AstroEmbeddedContent").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: AstroEmbeddedContent) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: AstroEmbeddedContent) -> Self { + n.syntax.into() + } +} +impl AstNode for AstroFrontmatterElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(ASTRO_FRONTMATTER_ELEMENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == ASTRO_FRONTMATTER_ELEMENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for AstroFrontmatterElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("AstroFrontmatterElement") + .field( + "l_fence_token", + &support::DebugSyntaxResult(self.l_fence_token()), + ) + .field("content", &support::DebugSyntaxResult(self.content())) + .field( + "r_fence_token", + &support::DebugSyntaxResult(self.r_fence_token()), + ) + .finish() + } else { + f.debug_struct("AstroFrontmatterElement").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: AstroFrontmatterElement) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: AstroFrontmatterElement) -> Self { + n.syntax.into() + } +} +impl AstNode for HtmlAttribute { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ATTRIBUTE + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlAttribute { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("HtmlAttribute") + .field("name", &support::DebugSyntaxResult(self.name())) + .field( + "initializer", + &support::DebugOptionalElement(self.initializer()), + ) + .finish() + } else { + f.debug_struct("HtmlAttribute").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: HtmlAttribute) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlAttribute) -> Self { + n.syntax.into() + } +} +impl AstNode for HtmlAttributeInitializerClause { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE_INITIALIZER_CLAUSE as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ATTRIBUTE_INITIALIZER_CLAUSE + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlAttributeInitializerClause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("HtmlAttributeInitializerClause") + .field("eq_token", &support::DebugSyntaxResult(self.eq_token())) + .field("value", &support::DebugSyntaxResult(self.value())) + .finish() + } else { + f.debug_struct("HtmlAttributeInitializerClause").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: HtmlAttributeInitializerClause) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlAttributeInitializerClause) -> Self { + n.syntax.into() + } +} +impl AstNode for HtmlAttributeName { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE_NAME as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ATTRIBUTE_NAME + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlAttributeName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("HtmlAttributeName") + .field( + "value_token", + &support::DebugSyntaxResult(self.value_token()), + ) + .finish() + } else { + f.debug_struct("HtmlAttributeName").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: HtmlAttributeName) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlAttributeName) -> Self { + n.syntax.into() + } +} +impl AstNode for HtmlCdataSection { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CDATA_SECTION as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_CDATA_SECTION + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlCdataSection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("HtmlCdataSection") + .field( + "cdata_start_token", + &support::DebugSyntaxResult(self.cdata_start_token()), + ) + .field( + "content_token", + &support::DebugSyntaxResult(self.content_token()), + ) + .field( + "cdata_end_token", + &support::DebugSyntaxResult(self.cdata_end_token()), + ) + .finish() + } else { + f.debug_struct("HtmlCdataSection").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: HtmlCdataSection) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlCdataSection) -> Self { + n.syntax.into() + } +} +impl AstNode for HtmlClosingElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CLOSING_ELEMENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_CLOSING_ELEMENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlClosingElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("HtmlClosingElement") + .field( + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), + ) + .field( + "slash_token", + &support::DebugSyntaxResult(self.slash_token()), + ) + .field("name", &support::DebugSyntaxResult(self.name())) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), + ) + .finish() + } else { + f.debug_struct("HtmlClosingElement").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: HtmlClosingElement) -> Self { + n.syntax } - pub fn as_vue_static_argument(&self) -> Option<&VueStaticArgument> { - match &self { - Self::VueStaticArgument(item) => Some(item), - _ => None, - } +} +impl From for SyntaxElement { + fn from(n: HtmlClosingElement) -> Self { + n.syntax.into() } } -impl AstNode for AstroEmbeddedContent { +impl AstNode for HtmlContent { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(ASTRO_EMBEDDED_CONTENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CONTENT as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == ASTRO_EMBEDDED_CONTENT + kind == HTML_CONTENT } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2560,41 +3456,41 @@ impl AstNode for AstroEmbeddedContent { self.syntax } } -impl std::fmt::Debug for AstroEmbeddedContent { +impl std::fmt::Debug for HtmlContent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("AstroEmbeddedContent") + f.debug_struct("HtmlContent") .field( - "content_token", - &support::DebugOptionalElement(self.content_token()), + "value_token", + &support::DebugSyntaxResult(self.value_token()), ) .finish() } else { - f.debug_struct("AstroEmbeddedContent").finish() + f.debug_struct("HtmlContent").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: AstroEmbeddedContent) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlContent) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: AstroEmbeddedContent) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlContent) -> Self { n.syntax.into() } } -impl AstNode for AstroFrontmatterElement { +impl AstNode for HtmlDirective { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(ASTRO_FRONTMATTER_ELEMENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_DIRECTIVE as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == ASTRO_FRONTMATTER_ELEMENT + kind == HTML_DIRECTIVE } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2610,46 +3506,66 @@ impl AstNode for AstroFrontmatterElement { self.syntax } } -impl std::fmt::Debug for AstroFrontmatterElement { +impl std::fmt::Debug for HtmlDirective { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("AstroFrontmatterElement") + f.debug_struct("HtmlDirective") .field( - "l_fence_token", - &support::DebugSyntaxResult(self.l_fence_token()), + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), ) - .field("content", &support::DebugSyntaxResult(self.content())) + .field("excl_token", &support::DebugSyntaxResult(self.excl_token())) .field( - "r_fence_token", - &support::DebugSyntaxResult(self.r_fence_token()), + "doctype_token", + &support::DebugSyntaxResult(self.doctype_token()), + ) + .field( + "html_token", + &support::DebugOptionalElement(self.html_token()), + ) + .field( + "quirk_token", + &support::DebugOptionalElement(self.quirk_token()), + ) + .field( + "public_id_token", + &support::DebugOptionalElement(self.public_id_token()), + ) + .field( + "system_id_token", + &support::DebugOptionalElement(self.system_id_token()), + ) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), ) .finish() } else { - f.debug_struct("AstroFrontmatterElement").finish() + f.debug_struct("HtmlDirective").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: AstroFrontmatterElement) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlDirective) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: AstroFrontmatterElement) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlDirective) -> Self { n.syntax.into() } } -impl AstNode for HtmlAttribute { +impl AstNode for HtmlDoubleTextExpression { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_DOUBLE_TEXT_EXPRESSION as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_ATTRIBUTE + kind == HTML_DOUBLE_TEXT_EXPRESSION } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2665,42 +3581,46 @@ impl AstNode for HtmlAttribute { self.syntax } } -impl std::fmt::Debug for HtmlAttribute { +impl std::fmt::Debug for HtmlDoubleTextExpression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlAttribute") - .field("name", &support::DebugSyntaxResult(self.name())) + f.debug_struct("HtmlDoubleTextExpression") .field( - "initializer", - &support::DebugOptionalElement(self.initializer()), + "l_double_curly_token", + &support::DebugSyntaxResult(self.l_double_curly_token()), + ) + .field("expression", &support::DebugSyntaxResult(self.expression())) + .field( + "r_double_curly_token", + &support::DebugSyntaxResult(self.r_double_curly_token()), ) .finish() } else { - f.debug_struct("HtmlAttribute").finish() + f.debug_struct("HtmlDoubleTextExpression").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlAttribute) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlDoubleTextExpression) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlAttribute) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlDoubleTextExpression) -> Self { n.syntax.into() } } -impl AstNode for HtmlAttributeInitializerClause { +impl AstNode for HtmlElement { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE_INITIALIZER_CLAUSE as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ELEMENT as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_ATTRIBUTE_INITIALIZER_CLAUSE + kind == HTML_ELEMENT } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2716,39 +3636,46 @@ impl AstNode for HtmlAttributeInitializerClause { self.syntax } } -impl std::fmt::Debug for HtmlAttributeInitializerClause { +impl std::fmt::Debug for HtmlElement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlAttributeInitializerClause") - .field("eq_token", &support::DebugSyntaxResult(self.eq_token())) - .field("value", &support::DebugSyntaxResult(self.value())) + f.debug_struct("HtmlElement") + .field( + "opening_element", + &support::DebugSyntaxResult(self.opening_element()), + ) + .field("children", &self.children()) + .field( + "closing_element", + &support::DebugSyntaxResult(self.closing_element()), + ) .finish() } else { - f.debug_struct("HtmlAttributeInitializerClause").finish() + f.debug_struct("HtmlElement").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlAttributeInitializerClause) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlElement) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlAttributeInitializerClause) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlElement) -> Self { n.syntax.into() } } -impl AstNode for HtmlAttributeName { +impl AstNode for HtmlEmbeddedContent { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE_NAME as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_EMBEDDED_CONTENT as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_ATTRIBUTE_NAME + kind == HTML_EMBEDDED_CONTENT } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2764,41 +3691,41 @@ impl AstNode for HtmlAttributeName { self.syntax } } -impl std::fmt::Debug for HtmlAttributeName { +impl std::fmt::Debug for HtmlEmbeddedContent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlAttributeName") + f.debug_struct("HtmlEmbeddedContent") .field( "value_token", &support::DebugSyntaxResult(self.value_token()), ) .finish() } else { - f.debug_struct("HtmlAttributeName").finish() + f.debug_struct("HtmlEmbeddedContent").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlAttributeName) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlEmbeddedContent) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlAttributeName) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlEmbeddedContent) -> Self { n.syntax.into() } } -impl AstNode for HtmlCdataSection { +impl AstNode for HtmlOpeningElement { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CDATA_SECTION as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_OPENING_ELEMENT as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_CDATA_SECTION + kind == HTML_OPENING_ELEMENT } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2814,49 +3741,47 @@ impl AstNode for HtmlCdataSection { self.syntax } } -impl std::fmt::Debug for HtmlCdataSection { +impl std::fmt::Debug for HtmlOpeningElement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlCdataSection") - .field( - "cdata_start_token", - &support::DebugSyntaxResult(self.cdata_start_token()), - ) + f.debug_struct("HtmlOpeningElement") .field( - "content_token", - &support::DebugSyntaxResult(self.content_token()), + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), ) + .field("name", &support::DebugSyntaxResult(self.name())) + .field("attributes", &self.attributes()) .field( - "cdata_end_token", - &support::DebugSyntaxResult(self.cdata_end_token()), + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), ) .finish() } else { - f.debug_struct("HtmlCdataSection").finish() + f.debug_struct("HtmlOpeningElement").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlCdataSection) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlOpeningElement) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlCdataSection) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlOpeningElement) -> Self { n.syntax.into() } } -impl AstNode for HtmlClosingElement { +impl AstNode for HtmlRoot { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CLOSING_ELEMENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ROOT as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_CLOSING_ELEMENT + kind == HTML_ROOT } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2872,50 +3797,51 @@ impl AstNode for HtmlClosingElement { self.syntax } } -impl std::fmt::Debug for HtmlClosingElement { +impl std::fmt::Debug for HtmlRoot { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlClosingElement") + f.debug_struct("HtmlRoot") .field( - "l_angle_token", - &support::DebugSyntaxResult(self.l_angle_token()), + "bom_token", + &support::DebugOptionalElement(self.bom_token()), ) .field( - "slash_token", - &support::DebugSyntaxResult(self.slash_token()), + "frontmatter", + &support::DebugOptionalElement(self.frontmatter()), ) - .field("name", &support::DebugSyntaxResult(self.name())) .field( - "r_angle_token", - &support::DebugSyntaxResult(self.r_angle_token()), + "directive", + &support::DebugOptionalElement(self.directive()), ) + .field("html", &self.html()) + .field("eof_token", &support::DebugSyntaxResult(self.eof_token())) .finish() } else { - f.debug_struct("HtmlClosingElement").finish() + f.debug_struct("HtmlRoot").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlClosingElement) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlRoot) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlClosingElement) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlRoot) -> Self { n.syntax.into() } } -impl AstNode for HtmlContent { +impl AstNode for HtmlSelfClosingElement { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CONTENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_SELF_CLOSING_ELEMENT as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_CONTENT + kind == HTML_SELF_CLOSING_ELEMENT } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2931,41 +3857,51 @@ impl AstNode for HtmlContent { self.syntax } } -impl std::fmt::Debug for HtmlContent { +impl std::fmt::Debug for HtmlSelfClosingElement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlContent") + f.debug_struct("HtmlSelfClosingElement") .field( - "value_token", - &support::DebugSyntaxResult(self.value_token()), + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), + ) + .field("name", &support::DebugSyntaxResult(self.name())) + .field("attributes", &self.attributes()) + .field( + "slash_token", + &support::DebugOptionalElement(self.slash_token()), + ) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), ) .finish() } else { - f.debug_struct("HtmlContent").finish() + f.debug_struct("HtmlSelfClosingElement").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlContent) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlSelfClosingElement) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlContent) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlSelfClosingElement) -> Self { n.syntax.into() } } -impl AstNode for HtmlDirective { +impl AstNode for HtmlSingleTextExpression { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_DIRECTIVE as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_SINGLE_TEXT_EXPRESSION as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_DIRECTIVE + kind == HTML_SINGLE_TEXT_EXPRESSION } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -2981,66 +3917,46 @@ impl AstNode for HtmlDirective { self.syntax } } -impl std::fmt::Debug for HtmlDirective { +impl std::fmt::Debug for HtmlSingleTextExpression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlDirective") - .field( - "l_angle_token", - &support::DebugSyntaxResult(self.l_angle_token()), - ) - .field("excl_token", &support::DebugSyntaxResult(self.excl_token())) - .field( - "doctype_token", - &support::DebugSyntaxResult(self.doctype_token()), - ) - .field( - "html_token", - &support::DebugOptionalElement(self.html_token()), - ) - .field( - "quirk_token", - &support::DebugOptionalElement(self.quirk_token()), - ) - .field( - "public_id_token", - &support::DebugOptionalElement(self.public_id_token()), - ) + f.debug_struct("HtmlSingleTextExpression") .field( - "system_id_token", - &support::DebugOptionalElement(self.system_id_token()), + "l_curly_token", + &support::DebugSyntaxResult(self.l_curly_token()), ) + .field("expression", &support::DebugSyntaxResult(self.expression())) .field( - "r_angle_token", - &support::DebugSyntaxResult(self.r_angle_token()), + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) .finish() } else { - f.debug_struct("HtmlDirective").finish() + f.debug_struct("HtmlSingleTextExpression").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlDirective) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlSingleTextExpression) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlDirective) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlSingleTextExpression) -> Self { n.syntax.into() } } -impl AstNode for HtmlDoubleTextExpression { +impl AstNode for HtmlString { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_DOUBLE_TEXT_EXPRESSION as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_STRING as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_DOUBLE_TEXT_EXPRESSION + kind == HTML_STRING } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3056,46 +3972,41 @@ impl AstNode for HtmlDoubleTextExpression { self.syntax } } -impl std::fmt::Debug for HtmlDoubleTextExpression { +impl std::fmt::Debug for HtmlString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlDoubleTextExpression") - .field( - "l_double_curly_token", - &support::DebugSyntaxResult(self.l_double_curly_token()), - ) - .field("expression", &support::DebugSyntaxResult(self.expression())) + f.debug_struct("HtmlString") .field( - "r_double_curly_token", - &support::DebugSyntaxResult(self.r_double_curly_token()), + "value_token", + &support::DebugSyntaxResult(self.value_token()), ) .finish() } else { - f.debug_struct("HtmlDoubleTextExpression").finish() + f.debug_struct("HtmlString").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlDoubleTextExpression) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlString) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlDoubleTextExpression) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlString) -> Self { n.syntax.into() } } -impl AstNode for HtmlElement { +impl AstNode for HtmlTagName { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ELEMENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_TAG_NAME as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_ELEMENT + kind == HTML_TAG_NAME } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3111,46 +4022,41 @@ impl AstNode for HtmlElement { self.syntax } } -impl std::fmt::Debug for HtmlElement { +impl std::fmt::Debug for HtmlTagName { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlElement") - .field( - "opening_element", - &support::DebugSyntaxResult(self.opening_element()), - ) - .field("children", &self.children()) + f.debug_struct("HtmlTagName") .field( - "closing_element", - &support::DebugSyntaxResult(self.closing_element()), + "value_token", + &support::DebugSyntaxResult(self.value_token()), ) .finish() } else { - f.debug_struct("HtmlElement").finish() + f.debug_struct("HtmlTagName").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlElement) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlTagName) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlElement) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlTagName) -> Self { n.syntax.into() } } -impl AstNode for HtmlEmbeddedContent { +impl AstNode for HtmlTextExpression { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_EMBEDDED_CONTENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_TEXT_EXPRESSION as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_EMBEDDED_CONTENT + kind == HTML_TEXT_EXPRESSION } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3166,41 +4072,41 @@ impl AstNode for HtmlEmbeddedContent { self.syntax } } -impl std::fmt::Debug for HtmlEmbeddedContent { +impl std::fmt::Debug for HtmlTextExpression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlEmbeddedContent") + f.debug_struct("HtmlTextExpression") .field( - "value_token", - &support::DebugSyntaxResult(self.value_token()), + "html_literal_token", + &support::DebugSyntaxResult(self.html_literal_token()), ) .finish() } else { - f.debug_struct("HtmlEmbeddedContent").finish() + f.debug_struct("HtmlTextExpression").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlEmbeddedContent) -> Self { +impl From for SyntaxNode { + fn from(n: HtmlTextExpression) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlEmbeddedContent) -> Self { +impl From for SyntaxElement { + fn from(n: HtmlTextExpression) -> Self { n.syntax.into() } } -impl AstNode for HtmlOpeningElement { +impl AstNode for SvelteAttachAttribute { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_OPENING_ELEMENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_ATTACH_ATTRIBUTE as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_OPENING_ELEMENT + kind == SVELTE_ATTACH_ATTRIBUTE } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3216,47 +4122,50 @@ impl AstNode for HtmlOpeningElement { self.syntax } } -impl std::fmt::Debug for HtmlOpeningElement { +impl std::fmt::Debug for SvelteAttachAttribute { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlOpeningElement") + f.debug_struct("SvelteAttachAttribute") .field( - "l_angle_token", - &support::DebugSyntaxResult(self.l_angle_token()), + "sv_curly_at_token", + &support::DebugSyntaxResult(self.sv_curly_at_token()), ) - .field("name", &support::DebugSyntaxResult(self.name())) - .field("attributes", &self.attributes()) .field( - "r_angle_token", - &support::DebugSyntaxResult(self.r_angle_token()), + "attach_token", + &support::DebugSyntaxResult(self.attach_token()), + ) + .field("expression", &support::DebugSyntaxResult(self.expression())) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) .finish() } else { - f.debug_struct("HtmlOpeningElement").finish() + f.debug_struct("SvelteAttachAttribute").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlOpeningElement) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAttachAttribute) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlOpeningElement) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAttachAttribute) -> Self { n.syntax.into() } } -impl AstNode for HtmlRoot { +impl AstNode for SvelteAwaitBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ROOT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_ROOT + kind == SVELTE_AWAIT_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3272,51 +4181,46 @@ impl AstNode for HtmlRoot { self.syntax } } -impl std::fmt::Debug for HtmlRoot { +impl std::fmt::Debug for SvelteAwaitBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlRoot") + f.debug_struct("SvelteAwaitBlock") .field( - "bom_token", - &support::DebugOptionalElement(self.bom_token()), - ) - .field( - "frontmatter", - &support::DebugOptionalElement(self.frontmatter()), + "opening_block", + &support::DebugSyntaxResult(self.opening_block()), ) + .field("clauses", &self.clauses()) .field( - "directive", - &support::DebugOptionalElement(self.directive()), + "closing_block", + &support::DebugSyntaxResult(self.closing_block()), ) - .field("html", &self.html()) - .field("eof_token", &support::DebugSyntaxResult(self.eof_token())) .finish() } else { - f.debug_struct("HtmlRoot").finish() + f.debug_struct("SvelteAwaitBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlRoot) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlRoot) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitBlock) -> Self { n.syntax.into() } } -impl AstNode for HtmlSelfClosingElement { +impl AstNode for SvelteAwaitCatchBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_SELF_CLOSING_ELEMENT as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_CATCH_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_SELF_CLOSING_ELEMENT + kind == SVELTE_AWAIT_CATCH_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3332,51 +4236,51 @@ impl AstNode for HtmlSelfClosingElement { self.syntax } } -impl std::fmt::Debug for HtmlSelfClosingElement { +impl std::fmt::Debug for SvelteAwaitCatchBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlSelfClosingElement") + f.debug_struct("SvelteAwaitCatchBlock") .field( - "l_angle_token", - &support::DebugSyntaxResult(self.l_angle_token()), + "sv_curly_colon_token", + &support::DebugSyntaxResult(self.sv_curly_colon_token()), ) - .field("name", &support::DebugSyntaxResult(self.name())) - .field("attributes", &self.attributes()) .field( - "slash_token", - &support::DebugOptionalElement(self.slash_token()), + "catch_token", + &support::DebugSyntaxResult(self.catch_token()), ) + .field("name", &support::DebugSyntaxResult(self.name())) .field( - "r_angle_token", - &support::DebugSyntaxResult(self.r_angle_token()), + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) + .field("children", &self.children()) .finish() } else { - f.debug_struct("HtmlSelfClosingElement").finish() + f.debug_struct("SvelteAwaitCatchBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlSelfClosingElement) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitCatchBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlSelfClosingElement) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitCatchBlock) -> Self { n.syntax.into() } } -impl AstNode for HtmlSingleTextExpression { +impl AstNode for SvelteAwaitCatchClause { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_SINGLE_TEXT_EXPRESSION as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_CATCH_CLAUSE as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_SINGLE_TEXT_EXPRESSION + kind == SVELTE_AWAIT_CATCH_CLAUSE } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3392,46 +4296,42 @@ impl AstNode for HtmlSingleTextExpression { self.syntax } } -impl std::fmt::Debug for HtmlSingleTextExpression { +impl std::fmt::Debug for SvelteAwaitCatchClause { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlSingleTextExpression") + f.debug_struct("SvelteAwaitCatchClause") .field( - "l_curly_token", - &support::DebugSyntaxResult(self.l_curly_token()), - ) - .field("expression", &support::DebugSyntaxResult(self.expression())) - .field( - "r_curly_token", - &support::DebugSyntaxResult(self.r_curly_token()), + "catch_token", + &support::DebugSyntaxResult(self.catch_token()), ) + .field("name", &support::DebugSyntaxResult(self.name())) .finish() } else { - f.debug_struct("HtmlSingleTextExpression").finish() + f.debug_struct("SvelteAwaitCatchClause").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlSingleTextExpression) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitCatchClause) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlSingleTextExpression) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitCatchClause) -> Self { n.syntax.into() } } -impl AstNode for HtmlString { +impl AstNode for SvelteAwaitClosingBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_STRING as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_CLOSING_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_STRING + kind == SVELTE_AWAIT_CLOSING_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3447,41 +4347,49 @@ impl AstNode for HtmlString { self.syntax } } -impl std::fmt::Debug for HtmlString { +impl std::fmt::Debug for SvelteAwaitClosingBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlString") + f.debug_struct("SvelteAwaitClosingBlock") .field( - "value_token", - &support::DebugSyntaxResult(self.value_token()), + "sv_curly_slash_token", + &support::DebugSyntaxResult(self.sv_curly_slash_token()), + ) + .field( + "await_token", + &support::DebugSyntaxResult(self.await_token()), + ) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) .finish() } else { - f.debug_struct("HtmlString").finish() + f.debug_struct("SvelteAwaitClosingBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlString) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitClosingBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlString) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitClosingBlock) -> Self { n.syntax.into() } } -impl AstNode for HtmlTagName { +impl AstNode for SvelteAwaitOpeningBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_TAG_NAME as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_OPENING_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_TAG_NAME + kind == SVELTE_AWAIT_OPENING_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3497,41 +4405,59 @@ impl AstNode for HtmlTagName { self.syntax } } -impl std::fmt::Debug for HtmlTagName { +impl std::fmt::Debug for SvelteAwaitOpeningBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlTagName") + f.debug_struct("SvelteAwaitOpeningBlock") .field( - "value_token", - &support::DebugSyntaxResult(self.value_token()), + "sv_curly_hash_token", + &support::DebugSyntaxResult(self.sv_curly_hash_token()), + ) + .field( + "await_token", + &support::DebugSyntaxResult(self.await_token()), + ) + .field("expression", &support::DebugSyntaxResult(self.expression())) + .field( + "then_clause", + &support::DebugOptionalElement(self.then_clause()), + ) + .field( + "catch_clause", + &support::DebugOptionalElement(self.catch_clause()), + ) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) + .field("children", &self.children()) .finish() } else { - f.debug_struct("HtmlTagName").finish() + f.debug_struct("SvelteAwaitOpeningBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlTagName) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitOpeningBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlTagName) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitOpeningBlock) -> Self { n.syntax.into() } } -impl AstNode for HtmlTextExpression { +impl AstNode for SvelteAwaitThenBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(HTML_TEXT_EXPRESSION as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_THEN_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == HTML_TEXT_EXPRESSION + kind == SVELTE_AWAIT_THEN_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3547,41 +4473,48 @@ impl AstNode for HtmlTextExpression { self.syntax } } -impl std::fmt::Debug for HtmlTextExpression { +impl std::fmt::Debug for SvelteAwaitThenBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("HtmlTextExpression") + f.debug_struct("SvelteAwaitThenBlock") .field( - "html_literal_token", - &support::DebugSyntaxResult(self.html_literal_token()), + "sv_curly_colon_token", + &support::DebugSyntaxResult(self.sv_curly_colon_token()), + ) + .field("then_token", &support::DebugSyntaxResult(self.then_token())) + .field("name", &support::DebugSyntaxResult(self.name())) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) + .field("children", &self.children()) .finish() } else { - f.debug_struct("HtmlTextExpression").finish() + f.debug_struct("SvelteAwaitThenBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: HtmlTextExpression) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitThenBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: HtmlTextExpression) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitThenBlock) -> Self { n.syntax.into() } } -impl AstNode for SvelteAttachAttribute { +impl AstNode for SvelteAwaitThenClause { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_ATTACH_ATTRIBUTE as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_THEN_CLAUSE as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == SVELTE_ATTACH_ATTRIBUTE + kind == SVELTE_AWAIT_THEN_CLAUSE } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -3597,41 +4530,30 @@ impl AstNode for SvelteAttachAttribute { self.syntax } } -impl std::fmt::Debug for SvelteAttachAttribute { +impl std::fmt::Debug for SvelteAwaitThenClause { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("SvelteAttachAttribute") - .field( - "sv_curly_at_token", - &support::DebugSyntaxResult(self.sv_curly_at_token()), - ) - .field( - "attach_token", - &support::DebugSyntaxResult(self.attach_token()), - ) - .field("expression", &support::DebugSyntaxResult(self.expression())) - .field( - "r_curly_token", - &support::DebugSyntaxResult(self.r_curly_token()), - ) + f.debug_struct("SvelteAwaitThenClause") + .field("then_token", &support::DebugSyntaxResult(self.then_token())) + .field("name", &support::DebugSyntaxResult(self.name())) .finish() } else { - f.debug_struct("SvelteAttachAttribute").finish() + f.debug_struct("SvelteAwaitThenClause").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: SvelteAttachAttribute) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteAwaitThenClause) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: SvelteAttachAttribute) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteAwaitThenClause) -> Self { n.syntax.into() } } @@ -4513,22 +5435,183 @@ impl std::fmt::Debug for SvelteKeyBlock { result } } -impl From for SyntaxNode { - fn from(n: SvelteKeyBlock) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteKeyBlock) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: SvelteKeyBlock) -> Self { + n.syntax.into() + } +} +impl AstNode for SvelteKeyClosingBlock { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_KEY_CLOSING_BLOCK as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == SVELTE_KEY_CLOSING_BLOCK + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for SvelteKeyClosingBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("SvelteKeyClosingBlock") + .field( + "sv_curly_slash_token", + &support::DebugSyntaxResult(self.sv_curly_slash_token()), + ) + .field("key_token", &support::DebugSyntaxResult(self.key_token())) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), + ) + .finish() + } else { + f.debug_struct("SvelteKeyClosingBlock").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: SvelteKeyClosingBlock) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: SvelteKeyClosingBlock) -> Self { + n.syntax.into() + } +} +impl AstNode for SvelteKeyOpeningBlock { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_KEY_OPENING_BLOCK as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == SVELTE_KEY_OPENING_BLOCK + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for SvelteKeyOpeningBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("SvelteKeyOpeningBlock") + .field( + "sv_curly_hash_token", + &support::DebugSyntaxResult(self.sv_curly_hash_token()), + ) + .field("key_token", &support::DebugSyntaxResult(self.key_token())) + .field("expression", &support::DebugSyntaxResult(self.expression())) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), + ) + .finish() + } else { + f.debug_struct("SvelteKeyOpeningBlock").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: SvelteKeyOpeningBlock) -> Self { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: SvelteKeyOpeningBlock) -> Self { + n.syntax.into() + } +} +impl AstNode for SvelteName { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_NAME as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == SVELTE_NAME + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for SvelteName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; + let current_depth = DEPTH.get(); + let result = if current_depth < 16 { + DEPTH.set(current_depth + 1); + f.debug_struct("SvelteName") + .field( + "ident_token", + &support::DebugSyntaxResult(self.ident_token()), + ) + .finish() + } else { + f.debug_struct("SvelteName").finish() + }; + DEPTH.set(current_depth); + result + } +} +impl From for SyntaxNode { + fn from(n: SvelteName) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: SvelteKeyBlock) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteName) -> Self { n.syntax.into() } } -impl AstNode for SvelteKeyClosingBlock { +impl AstNode for SvelteRenderBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_KEY_CLOSING_BLOCK as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_RENDER_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == SVELTE_KEY_CLOSING_BLOCK + kind == SVELTE_RENDER_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -4544,46 +5627,50 @@ impl AstNode for SvelteKeyClosingBlock { self.syntax } } -impl std::fmt::Debug for SvelteKeyClosingBlock { +impl std::fmt::Debug for SvelteRenderBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("SvelteKeyClosingBlock") + f.debug_struct("SvelteRenderBlock") .field( - "sv_curly_slash_token", - &support::DebugSyntaxResult(self.sv_curly_slash_token()), + "sv_curly_at_token", + &support::DebugSyntaxResult(self.sv_curly_at_token()), ) - .field("key_token", &support::DebugSyntaxResult(self.key_token())) + .field( + "render_token", + &support::DebugSyntaxResult(self.render_token()), + ) + .field("expression", &support::DebugSyntaxResult(self.expression())) .field( "r_curly_token", &support::DebugSyntaxResult(self.r_curly_token()), ) .finish() } else { - f.debug_struct("SvelteKeyClosingBlock").finish() + f.debug_struct("SvelteRenderBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: SvelteKeyClosingBlock) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteRenderBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: SvelteKeyClosingBlock) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteRenderBlock) -> Self { n.syntax.into() } } -impl AstNode for SvelteKeyOpeningBlock { +impl AstNode for SvelteSnippetBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_KEY_OPENING_BLOCK as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_SNIPPET_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == SVELTE_KEY_OPENING_BLOCK + kind == SVELTE_SNIPPET_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -4599,47 +5686,45 @@ impl AstNode for SvelteKeyOpeningBlock { self.syntax } } -impl std::fmt::Debug for SvelteKeyOpeningBlock { +impl std::fmt::Debug for SvelteSnippetBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("SvelteKeyOpeningBlock") + f.debug_struct("SvelteSnippetBlock") .field( - "sv_curly_hash_token", - &support::DebugSyntaxResult(self.sv_curly_hash_token()), + "opening_block", + &support::DebugSyntaxResult(self.opening_block()), ) - .field("key_token", &support::DebugSyntaxResult(self.key_token())) - .field("expression", &support::DebugSyntaxResult(self.expression())) .field( - "r_curly_token", - &support::DebugSyntaxResult(self.r_curly_token()), + "closing_block", + &support::DebugSyntaxResult(self.closing_block()), ) .finish() } else { - f.debug_struct("SvelteKeyOpeningBlock").finish() + f.debug_struct("SvelteSnippetBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: SvelteKeyOpeningBlock) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteSnippetBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: SvelteKeyOpeningBlock) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteSnippetBlock) -> Self { n.syntax.into() } } -impl AstNode for SvelteName { +impl AstNode for SvelteSnippetClosingBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_NAME as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_SNIPPET_CLOSING_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == SVELTE_NAME + kind == SVELTE_SNIPPET_CLOSING_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -4655,41 +5740,49 @@ impl AstNode for SvelteName { self.syntax } } -impl std::fmt::Debug for SvelteName { +impl std::fmt::Debug for SvelteSnippetClosingBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("SvelteName") + f.debug_struct("SvelteSnippetClosingBlock") .field( - "ident_token", - &support::DebugSyntaxResult(self.ident_token()), + "sv_curly_slash_token", + &support::DebugSyntaxResult(self.sv_curly_slash_token()), + ) + .field( + "snippet_token", + &support::DebugSyntaxResult(self.snippet_token()), + ) + .field( + "r_curly_token", + &support::DebugSyntaxResult(self.r_curly_token()), ) .finish() } else { - f.debug_struct("SvelteName").finish() + f.debug_struct("SvelteSnippetClosingBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: SvelteName) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteSnippetClosingBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: SvelteName) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteSnippetClosingBlock) -> Self { n.syntax.into() } } -impl AstNode for SvelteRenderBlock { +impl AstNode for SvelteSnippetOpeningBlock { type Language = Language; const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_RENDER_BLOCK as u16)); + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_SNIPPET_OPENING_BLOCK as u16)); fn can_cast(kind: SyntaxKind) -> bool { - kind == SVELTE_RENDER_BLOCK + kind == SVELTE_SNIPPET_OPENING_BLOCK } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -4705,41 +5798,42 @@ impl AstNode for SvelteRenderBlock { self.syntax } } -impl std::fmt::Debug for SvelteRenderBlock { +impl std::fmt::Debug for SvelteSnippetOpeningBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { thread_local! { static DEPTH : std :: cell :: Cell < u8 > = const { std :: cell :: Cell :: new (0) } }; let current_depth = DEPTH.get(); let result = if current_depth < 16 { DEPTH.set(current_depth + 1); - f.debug_struct("SvelteRenderBlock") + f.debug_struct("SvelteSnippetOpeningBlock") .field( - "sv_curly_at_token", - &support::DebugSyntaxResult(self.sv_curly_at_token()), + "sv_curly_hash_token", + &support::DebugSyntaxResult(self.sv_curly_hash_token()), ) .field( - "render_token", - &support::DebugSyntaxResult(self.render_token()), + "snippet_token", + &support::DebugSyntaxResult(self.snippet_token()), ) .field("expression", &support::DebugSyntaxResult(self.expression())) .field( "r_curly_token", &support::DebugSyntaxResult(self.r_curly_token()), ) + .field("children", &self.children()) .finish() } else { - f.debug_struct("SvelteRenderBlock").finish() + f.debug_struct("SvelteSnippetOpeningBlock").finish() }; DEPTH.set(current_depth); result } } -impl From for SyntaxNode { - fn from(n: SvelteRenderBlock) -> Self { +impl From for SyntaxNode { + fn from(n: SvelteSnippetOpeningBlock) -> Self { n.syntax } } -impl From for SyntaxElement { - fn from(n: SvelteRenderBlock) -> Self { +impl From for SyntaxElement { + fn from(n: SvelteSnippetOpeningBlock) -> Self { n.syntax.into() } } @@ -5668,6 +6762,87 @@ impl From for SyntaxElement { node.into() } } +impl From for AnySvelteAwaitClauses { + fn from(node: SvelteAwaitCatchBlock) -> Self { + Self::SvelteAwaitCatchBlock(node) + } +} +impl From for AnySvelteAwaitClauses { + fn from(node: SvelteAwaitThenBlock) -> Self { + Self::SvelteAwaitThenBlock(node) + } +} +impl From for AnySvelteAwaitClauses { + fn from(node: SvelteBogusBlock) -> Self { + Self::SvelteBogusBlock(node) + } +} +impl AstNode for AnySvelteAwaitClauses { + type Language = Language; + const KIND_SET: SyntaxKindSet = SvelteAwaitCatchBlock::KIND_SET + .union(SvelteAwaitThenBlock::KIND_SET) + .union(SvelteBogusBlock::KIND_SET); + fn can_cast(kind: SyntaxKind) -> bool { + matches!( + kind, + SVELTE_AWAIT_CATCH_BLOCK | SVELTE_AWAIT_THEN_BLOCK | SVELTE_BOGUS_BLOCK + ) + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + SVELTE_AWAIT_CATCH_BLOCK => { + Self::SvelteAwaitCatchBlock(SvelteAwaitCatchBlock { syntax }) + } + SVELTE_AWAIT_THEN_BLOCK => Self::SvelteAwaitThenBlock(SvelteAwaitThenBlock { syntax }), + SVELTE_BOGUS_BLOCK => Self::SvelteBogusBlock(SvelteBogusBlock { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Self::SvelteAwaitCatchBlock(it) => it.syntax(), + Self::SvelteAwaitThenBlock(it) => it.syntax(), + Self::SvelteBogusBlock(it) => it.syntax(), + } + } + fn into_syntax(self) -> SyntaxNode { + match self { + Self::SvelteAwaitCatchBlock(it) => it.into_syntax(), + Self::SvelteAwaitThenBlock(it) => it.into_syntax(), + Self::SvelteBogusBlock(it) => it.into_syntax(), + } + } +} +impl std::fmt::Debug for AnySvelteAwaitClauses { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::SvelteAwaitCatchBlock(it) => std::fmt::Debug::fmt(it, f), + Self::SvelteAwaitThenBlock(it) => std::fmt::Debug::fmt(it, f), + Self::SvelteBogusBlock(it) => std::fmt::Debug::fmt(it, f), + } + } +} +impl From for SyntaxNode { + fn from(n: AnySvelteAwaitClauses) -> Self { + match n { + AnySvelteAwaitClauses::SvelteAwaitCatchBlock(it) => it.into_syntax(), + AnySvelteAwaitClauses::SvelteAwaitThenBlock(it) => it.into_syntax(), + AnySvelteAwaitClauses::SvelteBogusBlock(it) => it.into_syntax(), + } + } +} +impl From for SyntaxElement { + fn from(n: AnySvelteAwaitClauses) -> Self { + let node: SyntaxNode = n.into(); + node.into() + } +} +impl From for AnySvelteBlock { + fn from(node: SvelteAwaitBlock) -> Self { + Self::SvelteAwaitBlock(node) + } +} impl From for AnySvelteBlock { fn from(node: SvelteBogusBlock) -> Self { Self::SvelteBogusBlock(node) @@ -5708,20 +6883,28 @@ impl From for AnySvelteBlock { Self::SvelteRenderBlock(node) } } +impl From for AnySvelteBlock { + fn from(node: SvelteSnippetBlock) -> Self { + Self::SvelteSnippetBlock(node) + } +} impl AstNode for AnySvelteBlock { type Language = Language; - const KIND_SET: SyntaxKindSet = SvelteBogusBlock::KIND_SET + const KIND_SET: SyntaxKindSet = SvelteAwaitBlock::KIND_SET + .union(SvelteBogusBlock::KIND_SET) .union(SvelteConstBlock::KIND_SET) .union(SvelteDebugBlock::KIND_SET) .union(SvelteEachBlock::KIND_SET) .union(SvelteHtmlBlock::KIND_SET) .union(SvelteIfBlock::KIND_SET) .union(SvelteKeyBlock::KIND_SET) - .union(SvelteRenderBlock::KIND_SET); + .union(SvelteRenderBlock::KIND_SET) + .union(SvelteSnippetBlock::KIND_SET); fn can_cast(kind: SyntaxKind) -> bool { matches!( kind, - SVELTE_BOGUS_BLOCK + SVELTE_AWAIT_BLOCK + | SVELTE_BOGUS_BLOCK | SVELTE_CONST_BLOCK | SVELTE_DEBUG_BLOCK | SVELTE_EACH_BLOCK @@ -5729,10 +6912,12 @@ impl AstNode for AnySvelteBlock { | SVELTE_IF_BLOCK | SVELTE_KEY_BLOCK | SVELTE_RENDER_BLOCK + | SVELTE_SNIPPET_BLOCK ) } fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { + SVELTE_AWAIT_BLOCK => Self::SvelteAwaitBlock(SvelteAwaitBlock { syntax }), SVELTE_BOGUS_BLOCK => Self::SvelteBogusBlock(SvelteBogusBlock { syntax }), SVELTE_CONST_BLOCK => Self::SvelteConstBlock(SvelteConstBlock { syntax }), SVELTE_DEBUG_BLOCK => Self::SvelteDebugBlock(SvelteDebugBlock { syntax }), @@ -5741,12 +6926,14 @@ impl AstNode for AnySvelteBlock { SVELTE_IF_BLOCK => Self::SvelteIfBlock(SvelteIfBlock { syntax }), SVELTE_KEY_BLOCK => Self::SvelteKeyBlock(SvelteKeyBlock { syntax }), SVELTE_RENDER_BLOCK => Self::SvelteRenderBlock(SvelteRenderBlock { syntax }), + SVELTE_SNIPPET_BLOCK => Self::SvelteSnippetBlock(SvelteSnippetBlock { syntax }), _ => return None, }; Some(res) } fn syntax(&self) -> &SyntaxNode { match self { + Self::SvelteAwaitBlock(it) => it.syntax(), Self::SvelteBogusBlock(it) => it.syntax(), Self::SvelteConstBlock(it) => it.syntax(), Self::SvelteDebugBlock(it) => it.syntax(), @@ -5755,10 +6942,12 @@ impl AstNode for AnySvelteBlock { Self::SvelteIfBlock(it) => it.syntax(), Self::SvelteKeyBlock(it) => it.syntax(), Self::SvelteRenderBlock(it) => it.syntax(), + Self::SvelteSnippetBlock(it) => it.syntax(), } } fn into_syntax(self) -> SyntaxNode { match self { + Self::SvelteAwaitBlock(it) => it.into_syntax(), Self::SvelteBogusBlock(it) => it.into_syntax(), Self::SvelteConstBlock(it) => it.into_syntax(), Self::SvelteDebugBlock(it) => it.into_syntax(), @@ -5767,12 +6956,14 @@ impl AstNode for AnySvelteBlock { Self::SvelteIfBlock(it) => it.into_syntax(), Self::SvelteKeyBlock(it) => it.into_syntax(), Self::SvelteRenderBlock(it) => it.into_syntax(), + Self::SvelteSnippetBlock(it) => it.into_syntax(), } } } impl std::fmt::Debug for AnySvelteBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + Self::SvelteAwaitBlock(it) => std::fmt::Debug::fmt(it, f), Self::SvelteBogusBlock(it) => std::fmt::Debug::fmt(it, f), Self::SvelteConstBlock(it) => std::fmt::Debug::fmt(it, f), Self::SvelteDebugBlock(it) => std::fmt::Debug::fmt(it, f), @@ -5781,12 +6972,14 @@ impl std::fmt::Debug for AnySvelteBlock { Self::SvelteIfBlock(it) => std::fmt::Debug::fmt(it, f), Self::SvelteKeyBlock(it) => std::fmt::Debug::fmt(it, f), Self::SvelteRenderBlock(it) => std::fmt::Debug::fmt(it, f), + Self::SvelteSnippetBlock(it) => std::fmt::Debug::fmt(it, f), } } } impl From for SyntaxNode { fn from(n: AnySvelteBlock) -> Self { match n { + AnySvelteBlock::SvelteAwaitBlock(it) => it.into_syntax(), AnySvelteBlock::SvelteBogusBlock(it) => it.into_syntax(), AnySvelteBlock::SvelteConstBlock(it) => it.into_syntax(), AnySvelteBlock::SvelteDebugBlock(it) => it.into_syntax(), @@ -5795,6 +6988,7 @@ impl From for SyntaxNode { AnySvelteBlock::SvelteIfBlock(it) => it.into_syntax(), AnySvelteBlock::SvelteKeyBlock(it) => it.into_syntax(), AnySvelteBlock::SvelteRenderBlock(it) => it.into_syntax(), + AnySvelteBlock::SvelteSnippetBlock(it) => it.into_syntax(), } } } @@ -6078,6 +7272,11 @@ impl std::fmt::Display for AnyHtmlTextExpression { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AnySvelteAwaitClauses { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AnySvelteBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -6198,6 +7397,41 @@ impl std::fmt::Display for SvelteAttachAttribute { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for SvelteAwaitBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteAwaitCatchBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteAwaitCatchClause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteAwaitClosingBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteAwaitOpeningBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteAwaitThenBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteAwaitThenClause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for SvelteConstBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -6298,6 +7532,21 @@ impl std::fmt::Display for SvelteRenderBlock { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for SvelteSnippetBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteSnippetClosingBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for SvelteSnippetOpeningBlock { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for VueDirective { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -6952,6 +8201,88 @@ impl IntoIterator for HtmlElementList { } } #[derive(Clone, Eq, PartialEq, Hash)] +pub struct SvelteAwaitClausesList { + syntax_list: SyntaxList, +} +impl SvelteAwaitClausesList { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { + syntax_list: syntax.into_list(), + } + } +} +impl AstNode for SvelteAwaitClausesList { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(SVELTE_AWAIT_CLAUSES_LIST as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == SVELTE_AWAIT_CLAUSES_LIST + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { + syntax_list: syntax.into_list(), + }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + self.syntax_list.node() + } + fn into_syntax(self) -> SyntaxNode { + self.syntax_list.into_node() + } +} +impl Serialize for SvelteAwaitClausesList { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.len()))?; + for e in self.iter() { + seq.serialize_element(&e)?; + } + seq.end() + } +} +impl AstNodeList for SvelteAwaitClausesList { + type Language = Language; + type Node = AnySvelteAwaitClauses; + fn syntax_list(&self) -> &SyntaxList { + &self.syntax_list + } + fn into_syntax_list(self) -> SyntaxList { + self.syntax_list + } +} +impl Debug for SvelteAwaitClausesList { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str("SvelteAwaitClausesList ")?; + f.debug_list().entries(self.iter()).finish() + } +} +impl IntoIterator for &SvelteAwaitClausesList { + type Item = AnySvelteAwaitClauses; + type IntoIter = AstNodeListIterator; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl IntoIterator for SvelteAwaitClausesList { + type Item = AnySvelteAwaitClauses; + type IntoIter = AstNodeListIterator; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +#[derive(Clone, Eq, PartialEq, Hash)] pub struct SvelteBindingList { syntax_list: SyntaxList, } diff --git a/crates/biome_html_syntax/src/generated/nodes_mut.rs b/crates/biome_html_syntax/src/generated/nodes_mut.rs index 4a6259e6c9c0..e690dfef61fd 100644 --- a/crates/biome_html_syntax/src/generated/nodes_mut.rs +++ b/crates/biome_html_syntax/src/generated/nodes_mut.rs @@ -379,6 +379,182 @@ impl SvelteAttachAttribute { ) } } +impl SvelteAwaitBlock { + pub fn with_opening_block(self, element: SvelteAwaitOpeningBlock) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_clauses(self, element: SvelteAwaitClausesList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_closing_block(self, element: SvelteAwaitClosingBlock) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl SvelteAwaitCatchBlock { + pub fn with_sv_curly_colon_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_catch_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlTextExpression) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_r_curly_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } + pub fn with_children(self, element: HtmlElementList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(4usize..=4usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl SvelteAwaitCatchClause { + pub fn with_catch_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlTextExpression) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl SvelteAwaitClosingBlock { + pub fn with_sv_curly_slash_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_await_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_r_curly_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into()))), + ) + } +} +impl SvelteAwaitOpeningBlock { + pub fn with_sv_curly_hash_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_await_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_expression(self, element: HtmlTextExpression) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_then_clause(self, element: Option) -> Self { + Self::unwrap_cast(self.syntax.splice_slots( + 3usize..=3usize, + once(element.map(|element| element.into_syntax().into())), + )) + } + pub fn with_catch_clause(self, element: Option) -> Self { + Self::unwrap_cast(self.syntax.splice_slots( + 4usize..=4usize, + once(element.map(|element| element.into_syntax().into())), + )) + } + pub fn with_r_curly_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(5usize..=5usize, once(Some(element.into()))), + ) + } + pub fn with_children(self, element: HtmlElementList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(6usize..=6usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl SvelteAwaitThenBlock { + pub fn with_sv_curly_colon_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_then_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlTextExpression) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_r_curly_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } + pub fn with_children(self, element: HtmlElementList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(4usize..=4usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl SvelteAwaitThenClause { + pub fn with_then_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlTextExpression) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } +} impl SvelteConstBlock { pub fn with_sv_curly_at_token(self, element: SyntaxToken) -> Self { Self::unwrap_cast( @@ -845,6 +1021,72 @@ impl SvelteRenderBlock { ) } } +impl SvelteSnippetBlock { + pub fn with_opening_block(self, element: SvelteSnippetOpeningBlock) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_closing_block(self, element: SvelteSnippetClosingBlock) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl SvelteSnippetClosingBlock { + pub fn with_sv_curly_slash_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_snippet_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_r_curly_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into()))), + ) + } +} +impl SvelteSnippetOpeningBlock { + pub fn with_sv_curly_hash_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_snippet_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_expression(self, element: HtmlTextExpression) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_r_curly_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } + pub fn with_children(self, element: HtmlElementList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(4usize..=4usize, once(Some(element.into_syntax().into()))), + ) + } +} impl VueDirective { pub fn with_name_token(self, element: SyntaxToken) -> Self { Self::unwrap_cast( diff --git a/xtask/codegen/html.ungram b/xtask/codegen/html.ungram index 6cfe7b5b265f..83b0f5763f8d 100644 --- a/xtask/codegen/html.ungram +++ b/xtask/codegen/html.ungram @@ -200,6 +200,8 @@ AnySvelteBlock = | SvelteConstBlock | SvelteIfBlock | SvelteEachBlock + | SvelteAwaitBlock + | SvelteSnippetBlock | SvelteBogusBlock // {@debug} @@ -369,6 +371,91 @@ SvelteEachClosingBlock = 'each' '}' +// {#await ...} {:then} {:catch} {/await} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +SvelteAwaitBlock = + opening_block: SvelteAwaitOpeningBlock + clauses: SvelteAwaitClausesList + closing_block: SvelteAwaitClosingBlock + + +// {#await ... } {:then} {:catch} {/await} +// ^^^^^^^^^^^^^ +SvelteAwaitOpeningBlock = + '{#' + 'await' + expression: HtmlTextExpression + then_clause: SvelteAwaitThenClause? + catch_clause: SvelteAwaitCatchClause? + '}' + children: HtmlElementList + +SvelteAwaitClausesList = AnySvelteAwaitClauses* + +AnySvelteAwaitClauses = + SvelteAwaitThenBlock + | SvelteAwaitCatchBlock + | SvelteBogusBlock + +// {#await ... then value} +// ^^^^^^^^^^ +SvelteAwaitThenClause = + 'then' + name: HtmlTextExpression + +// {#await ... catch value} +// ^^^^^^^^^^^ +SvelteAwaitCatchClause = + 'catch' + name: HtmlTextExpression + +// {#await ... } {:then name} .. {:catch} {/await} +// ^^^^^^^^^^^^^^^ +SvelteAwaitThenBlock = + '{:' + 'then' + name: HtmlTextExpression + '}' + children: HtmlElementList + + +// {#await ... } {:then} .. {:catch name} .. {/await} +// ^^^^^^^^^^^^^^^^ +SvelteAwaitCatchBlock = + '{:' + 'catch' + name: HtmlTextExpression + '}' + children: HtmlElementList + +// {#await ... } {:then} {:catch} {/await} +// ^^^^^^^^ +SvelteAwaitClosingBlock = + '{/' + 'await' + '}' + +// {#snippet f()} ... {/snippet} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +SvelteSnippetBlock = + opening_block: SvelteSnippetOpeningBlock + closing_block: SvelteSnippetClosingBlock + +// {#snippet f()} ... {/snippet} +// ^^^^^^^^^^^^^^^^^ +SvelteSnippetOpeningBlock = + '{#' + 'snippet' + expression: HtmlTextExpression + '}' + children: HtmlElementList + +// {#snippet f()} ... {/snippet} +// ^^^^^^^^^^ +SvelteSnippetClosingBlock = + '{/' + 'snippet' + '}' // Keep it different just for svelte SvelteName = 'ident' diff --git a/xtask/codegen/src/html_kinds_src.rs b/xtask/codegen/src/html_kinds_src.rs index 177cd5420163..81d13188438d 100644 --- a/xtask/codegen/src/html_kinds_src.rs +++ b/xtask/codegen/src/html_kinds_src.rs @@ -30,8 +30,28 @@ pub const HTML_KINDS_SRC: KindsSrc = KindsSrc { (")", "R_PAREN"), ], keywords: &[ - "null", "true", "false", "doctype", "html", // Svelte keywords - "debug", "key", "render", "const", "attach", "else", "if", "as", "each", + "null", + "true", + "false", + "doctype", + "html", + // rustfmt is weird and it goes on newline only if it sees + // a doc comment + #[expect(unused_doc_comments)] + /// Svelte keywords + "debug", + "key", + "render", + "const", + "attach", + "else", + "if", + "as", + "each", + "then", + "await", + "catch", + "snippet", ], literals: &["HTML_STRING_LITERAL", "HTML_LITERAL"], tokens: &["ERROR_TOKEN", "NEWLINE", "WHITESPACE", "IDENT"], @@ -84,6 +104,17 @@ pub const HTML_KINDS_SRC: KindsSrc = KindsSrc { "SVELTE_EACH_INDEX", "SVELTE_EACH_KEY", "SVELTE_EACH_CLOSING_BLOCK", + "SVELTE_AWAIT_BLOCK", + "SVELTE_AWAIT_OPENING_BLOCK", + "SVELTE_AWAIT_THEN_BLOCK", + "SVELTE_AWAIT_CLAUSES_LIST", + "SVELTE_AWAIT_CATCH_BLOCK", + "SVELTE_AWAIT_CLOSING_BLOCK", + "SVELTE_AWAIT_THEN_CLAUSE", + "SVELTE_AWAIT_CATCH_CLAUSE", + "SVELTE_SNIPPET_BLOCK", + "SVELTE_SNIPPET_OPENING_BLOCK", + "SVELTE_SNIPPET_CLOSING_BLOCK", // Vue nodes "VUE_DIRECTIVE", "VUE_DIRECTIVE_ARGUMENT",