Skip to content

Commit d803d0e

Browse files
committed
feat(parse/html/vue): parse v-slot shorthand syntax
1 parent b537918 commit d803d0e

File tree

19 files changed

+575
-18
lines changed

19 files changed

+575
-18
lines changed

.changeset/forty-falcons-pick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed [#8222](https://github.com/biomejs/biome/issues/8222): The HTML parser, with Vue directives enabled, can now parse `v-slot` shorthand syntax, e.g. `<template #foo>`.

crates/biome_html_factory/src/generated/node_factory.rs

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_html_factory/src/generated/syntax_factory.rs

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_html_formatter/src/generated.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,38 @@ impl IntoFormat<HtmlFormatContext> for biome_html_syntax::VueVOnShorthandDirecti
14981498
FormatOwnedWithRule :: new (self , crate :: vue :: auxiliary :: v_on_shorthand_directive :: FormatVueVOnShorthandDirective :: default ())
14991499
}
15001500
}
1501+
impl FormatRule<biome_html_syntax::VueVSlotShorthandDirective>
1502+
for crate::vue::auxiliary::v_slot_shorthand_directive::FormatVueVSlotShorthandDirective
1503+
{
1504+
type Context = HtmlFormatContext;
1505+
#[inline(always)]
1506+
fn fmt(
1507+
&self,
1508+
node: &biome_html_syntax::VueVSlotShorthandDirective,
1509+
f: &mut HtmlFormatter,
1510+
) -> FormatResult<()> {
1511+
FormatNodeRule::<biome_html_syntax::VueVSlotShorthandDirective>::fmt(self, node, f)
1512+
}
1513+
}
1514+
impl AsFormat<HtmlFormatContext> for biome_html_syntax::VueVSlotShorthandDirective {
1515+
type Format<'a> = FormatRefWithRule<
1516+
'a,
1517+
biome_html_syntax::VueVSlotShorthandDirective,
1518+
crate::vue::auxiliary::v_slot_shorthand_directive::FormatVueVSlotShorthandDirective,
1519+
>;
1520+
fn format(&self) -> Self::Format<'_> {
1521+
FormatRefWithRule :: new (self , crate :: vue :: auxiliary :: v_slot_shorthand_directive :: FormatVueVSlotShorthandDirective :: default ())
1522+
}
1523+
}
1524+
impl IntoFormat<HtmlFormatContext> for biome_html_syntax::VueVSlotShorthandDirective {
1525+
type Format = FormatOwnedWithRule<
1526+
biome_html_syntax::VueVSlotShorthandDirective,
1527+
crate::vue::auxiliary::v_slot_shorthand_directive::FormatVueVSlotShorthandDirective,
1528+
>;
1529+
fn into_format(self) -> Self::Format {
1530+
FormatOwnedWithRule :: new (self , crate :: vue :: auxiliary :: v_slot_shorthand_directive :: FormatVueVSlotShorthandDirective :: default ())
1531+
}
1532+
}
15011533
impl AsFormat<HtmlFormatContext> for biome_html_syntax::HtmlAttributeList {
15021534
type Format<'a> = FormatRefWithRule<
15031535
'a,

crates/biome_html_formatter/src/vue/any/directive.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ impl FormatRule<AnyVueDirective> for FormatAnyVueDirective {
1212
AnyVueDirective::VueDirective(node) => node.format().fmt(f),
1313
AnyVueDirective::VueVBindShorthandDirective(node) => node.format().fmt(f),
1414
AnyVueDirective::VueVOnShorthandDirective(node) => node.format().fmt(f),
15+
AnyVueDirective::VueVSlotShorthandDirective(node) => node.format().fmt(f),
1516
}
1617
}
1718
}

crates/biome_html_formatter/src/vue/auxiliary/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ pub(crate) mod modifier;
77
pub(crate) mod static_argument;
88
pub(crate) mod v_bind_shorthand_directive;
99
pub(crate) mod v_on_shorthand_directive;
10+
pub(crate) mod v_slot_shorthand_directive;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::prelude::*;
2+
use biome_formatter::write;
3+
use biome_html_syntax::{VueVSlotShorthandDirective, VueVSlotShorthandDirectiveFields};
4+
5+
#[derive(Debug, Clone, Default)]
6+
pub(crate) struct FormatVueVSlotShorthandDirective;
7+
impl FormatNodeRule<VueVSlotShorthandDirective> for FormatVueVSlotShorthandDirective {
8+
fn fmt_fields(
9+
&self,
10+
node: &VueVSlotShorthandDirective,
11+
f: &mut HtmlFormatter,
12+
) -> FormatResult<()> {
13+
let VueVSlotShorthandDirectiveFields {
14+
hash_token,
15+
arg,
16+
modifiers,
17+
initializer,
18+
} = node.as_fields();
19+
20+
write!(
21+
f,
22+
[
23+
hash_token.format(),
24+
arg.format(),
25+
modifiers.format(),
26+
initializer.format()
27+
]
28+
)
29+
}
30+
}

crates/biome_html_parser/src/lexer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl<'src> HtmlLexer<'src> {
140140
b'.' => self.consume_byte(T![.]),
141141
b'[' => self.consume_byte(T!['[']),
142142
b']' => self.consume_byte(T![']']),
143+
b'#' => self.consume_byte(T![#]),
143144

144145
b'\'' | b'"' => self.consume_string_literal(current),
145146
_ if self.current_kind == T![<] && is_tag_name_byte(current) => {

crates/biome_html_parser/src/syntax/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::syntax::svelte::{
1212
};
1313
use crate::syntax::vue::{
1414
parse_vue_directive, parse_vue_v_bind_shorthand_directive, parse_vue_v_on_shorthand_directive,
15+
parse_vue_v_slot_shorthand_directive,
1516
};
1617
use crate::token_source::{
1718
HtmlEmbeddedLanguage, HtmlLexContext, HtmlReLexContext, TextExpressionKind,
@@ -369,6 +370,11 @@ fn parse_attribute(p: &mut HtmlParser) -> ParsedSyntax {
369370
parse_vue_v_on_shorthand_directive,
370371
|p, m| disabled_vue(p, m.range(p)),
371372
),
373+
T![#] => HtmlSyntaxFeatures::Vue.parse_exclusive_syntax(
374+
p,
375+
parse_vue_v_slot_shorthand_directive,
376+
|p, m| disabled_vue(p, m.range(p)),
377+
),
372378
T!['{'] => SingleTextExpressions.parse_exclusive_syntax(
373379
p,
374380
|p| parse_single_text_expression(p, HtmlLexContext::InsideTag),
@@ -398,8 +404,14 @@ fn parse_attribute(p: &mut HtmlParser) -> ParsedSyntax {
398404
}
399405

400406
fn is_at_attribute_start(p: &mut HtmlParser) -> bool {
401-
p.at_ts(token_set![HTML_LITERAL, T!["{{"], T!['{'], T![:], T![@]])
402-
|| (SingleTextExpressions.is_supported(p) && p.at(T!["{@"]))
407+
p.at_ts(token_set![
408+
HTML_LITERAL,
409+
T!["{{"],
410+
T!['{'],
411+
T![:],
412+
T![@],
413+
T![#],
414+
]) || (SingleTextExpressions.is_supported(p) && p.at(T!["{@"]))
403415
}
404416

405417
fn parse_literal(p: &mut HtmlParser, kind: HtmlSyntaxKind) -> ParsedSyntax {

crates/biome_html_parser/src/syntax/vue.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,25 @@ pub(crate) fn parse_vue_v_on_shorthand_directive(p: &mut HtmlParser) -> ParsedSy
8282
Present(m.complete(p, VUE_V_ON_SHORTHAND_DIRECTIVE))
8383
}
8484

85+
pub(crate) fn parse_vue_v_slot_shorthand_directive(p: &mut HtmlParser) -> ParsedSyntax {
86+
if !p.at(T![#]) {
87+
return Absent;
88+
}
89+
90+
let m = p.start();
91+
92+
p.bump_with_context(T![#], HtmlLexContext::InsideTagVue);
93+
parse_vue_dynamic_argument(p)
94+
.or_else(|| parse_vue_static_argument(p))
95+
.ok();
96+
VueModifierList.parse_list(p);
97+
if p.at(T![=]) {
98+
parse_attribute_initializer(p).ok();
99+
}
100+
101+
Present(m.complete(p, VUE_V_SLOT_SHORTHAND_DIRECTIVE))
102+
}
103+
85104
fn parse_vue_directive_argument(p: &mut HtmlParser) -> ParsedSyntax {
86105
if !p.at(T![:]) {
87106
return Absent;

0 commit comments

Comments
 (0)