Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/dry-cooks-start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@biomejs/biome": patch
---

Fixed [#8174](https://github.com/biomejs/biome/issues/8174), where the HTML parser would parse 2 directives as a single directive because it would not reject whitespace in Vue directives. This would cause the formatter to erroneously merge the 2 directives into one, resulting in broken code.

```diff
- <Component v-else:property="123" />
+ <Component v-else :property="123" />
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<Component v-if="operation" :property="123" />
<Component v-else :property="123" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
source: crates/biome_formatter_test/src/snapshot_builder.rs
info: vue/issue-8174.vue
---
# Input

```vue
<Component v-if="operation" :property="123" />
<Component v-else :property="123" />

```


=============================

# 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
-----

```vue
<Component v-if="operation" :property="123"/>
<Component v-else :property="123"/>
```
9 changes: 9 additions & 0 deletions crates/biome_html_parser/src/syntax/vue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,18 @@ pub(crate) fn parse_vue_directive(p: &mut HtmlParser) -> ParsedSyntax {

let m = p.start();

let pos = p.source().position();
// FIXME: Ideally, the lexer would just lex VUE_IDENT directly
p.bump_remap_with_context(VUE_IDENT, HtmlLexContext::InsideTagVue);
if p.at(T![:]) {
// is there any trivia after the directive name and before the colon?
if let Some(last_trivia) = p.source().trivia_list.last()
&& pos < last_trivia.text_range().start()
{
// `v-else :foo="5"` is 2 directives, not `v-else:foo="5"`
p.start().complete(p, VUE_MODIFIER_LIST);
return Present(m.complete(p, VUE_DIRECTIVE));
}
parse_vue_directive_argument(p).ok();
}
VueModifierList.parse_list(p);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<Component v-if="operation" :property="123" />
<Component v-else :property="123" />
151 changes: 151 additions & 0 deletions crates/biome_html_parser/tests/html_specs/ok/vue/issue-8174.vue.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
source: crates/biome_html_parser/tests/spec_test.rs
expression: snapshot
---
## Input

```vue
<Component v-if="operation" :property="123" />
<Component v-else :property="123" />

```


## AST

```
HtmlRoot {
bom_token: missing (optional),
frontmatter: missing (optional),
directive: missing (optional),
html: HtmlElementList [
HtmlSelfClosingElement {
l_angle_token: [email protected] "<" [] [],
name: HtmlTagName {
value_token: [email protected] "Component" [] [Whitespace(" ")],
},
attributes: HtmlAttributeList [
VueDirective {
name_token: [email protected] "v-if" [] [],
arg: missing (optional),
modifiers: VueModifierList [],
initializer: HtmlAttributeInitializerClause {
eq_token: [email protected] "=" [] [],
value: HtmlString {
value_token: [email protected] "\"operation\"" [] [Whitespace(" ")],
},
},
},
VueVBindShorthandDirective {
arg: VueDirectiveArgument {
colon_token: [email protected] ":" [] [],
arg: VueStaticArgument {
name_token: [email protected] "property" [] [],
},
},
modifiers: VueModifierList [],
initializer: HtmlAttributeInitializerClause {
eq_token: [email protected] "=" [] [],
value: HtmlString {
value_token: [email protected] "\"123\"" [] [Whitespace(" ")],
},
},
},
],
slash_token: [email protected] "/" [] [],
r_angle_token: [email protected] ">" [] [],
},
HtmlSelfClosingElement {
l_angle_token: [email protected] "<" [Newline("\n")] [],
name: HtmlTagName {
value_token: [email protected] "Component" [] [Whitespace(" ")],
},
attributes: HtmlAttributeList [
VueDirective {
name_token: [email protected] "v-else" [] [Whitespace(" ")],
arg: missing (optional),
modifiers: VueModifierList [],
initializer: missing (optional),
},
VueVBindShorthandDirective {
arg: VueDirectiveArgument {
colon_token: [email protected] ":" [] [],
arg: VueStaticArgument {
name_token: [email protected] "property" [] [],
},
},
modifiers: VueModifierList [],
initializer: HtmlAttributeInitializerClause {
eq_token: [email protected] "=" [] [],
value: HtmlString {
value_token: [email protected] "\"123\"" [] [Whitespace(" ")],
},
},
},
],
slash_token: [email protected] "/" [] [],
r_angle_token: [email protected] ">" [] [],
},
],
eof_token: [email protected] "" [Newline("\n")] [],
}
```

## CST

```
0: [email protected]
0: (empty)
1: (empty)
2: (empty)
3: [email protected]
0: [email protected]
0: [email protected] "<" [] []
1: [email protected]
0: [email protected] "Component" [] [Whitespace(" ")]
2: [email protected]
0: [email protected]
0: [email protected] "v-if" [] []
1: (empty)
2: [email protected]
3: [email protected]
0: [email protected] "=" [] []
1: [email protected]
0: [email protected] "\"operation\"" [] [Whitespace(" ")]
1: [email protected]
0: [email protected]
0: [email protected] ":" [] []
1: [email protected]
0: [email protected] "property" [] []
1: [email protected]
2: [email protected]
0: [email protected] "=" [] []
1: [email protected]
0: [email protected] "\"123\"" [] [Whitespace(" ")]
3: [email protected] "/" [] []
4: [email protected] ">" [] []
1: [email protected]
0: [email protected] "<" [Newline("\n")] []
1: [email protected]
0: [email protected] "Component" [] [Whitespace(" ")]
2: [email protected]
0: [email protected]
0: [email protected] "v-else" [] [Whitespace(" ")]
1: (empty)
2: [email protected]
3: (empty)
1: [email protected]
0: [email protected]
0: [email protected] ":" [] []
1: [email protected]
0: [email protected] "property" [] []
1: [email protected]
2: [email protected]
0: [email protected] "=" [] []
1: [email protected]
0: [email protected] "\"123\"" [] [Whitespace(" ")]
3: [email protected] "/" [] []
4: [email protected] ">" [] []
4: [email protected] "" [Newline("\n")] []

```
Loading