Skip to content

Commit 922314c

Browse files
committed
feat: Suport html.experimentalFullSupportEnabled for vue with jsx/tsx script
1 parent 0b28f5f commit 922314c

File tree

5 files changed

+256
-0
lines changed

5 files changed

+256
-0
lines changed

crates/biome_cli/tests/cases/handle_vue_files.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,121 @@ const props: Props = { title: "Hello" };
568568
));
569569
}
570570

571+
#[test]
572+
fn full_support_tsx() {
573+
let fs = MemoryFileSystem::default();
574+
let mut console = BufferConsole::default();
575+
576+
fs.insert(
577+
"biome.json".into(),
578+
r#"{ "html": { "formatter": {"enabled": true}, "linter": {"enabled": true}, "experimentalFullSupportEnabled": true } }"#.as_bytes(),
579+
);
580+
581+
let vue_file_path = Utf8Path::new("file.vue");
582+
fs.insert(
583+
vue_file_path.into(),
584+
r#"<script lang="tsx">
585+
import z from "zod";
586+
import { sure } from "sure.js";
587+
import s from "src/utils";
588+
589+
interface Props {
590+
title: string;
591+
}
592+
593+
let schema = z.object().optional();
594+
schema + sure();
595+
const props: Props = { title: "Hello" };
596+
597+
function FunctionalComponent() {
598+
return <div></div>;
599+
}
600+
601+
</script>
602+
603+
<template>
604+
<div></div>
605+
</template>
606+
607+
<style>
608+
.class { background: red}
609+
</style>
610+
"#
611+
.as_bytes(),
612+
);
613+
614+
let (fs, result) = run_cli(
615+
fs,
616+
&mut console,
617+
Args::from(["check", "--write", "--unsafe", vue_file_path.as_str()].as_slice()),
618+
);
619+
620+
assert!(result.is_ok(), "run_cli returned {result:?}");
621+
622+
assert_cli_snapshot(SnapshotPayload::new(
623+
module_path!(),
624+
"full_support_tsx",
625+
fs,
626+
console,
627+
result,
628+
));
629+
}
630+
631+
#[test]
632+
fn full_support_jsx() {
633+
let fs = MemoryFileSystem::default();
634+
let mut console = BufferConsole::default();
635+
636+
fs.insert(
637+
"biome.json".into(),
638+
r#"{ "html": { "formatter": {"enabled": true}, "linter": {"enabled": true}, "experimentalFullSupportEnabled": true } }"#.as_bytes(),
639+
);
640+
641+
let vue_file_path = Utf8Path::new("file.vue");
642+
fs.insert(
643+
vue_file_path.into(),
644+
r#"<script lang="jsx">
645+
import z from "zod";
646+
import { sure } from "sure.js";
647+
import s from "src/utils";
648+
649+
let schema = z.object().optional();
650+
schema + sure();
651+
652+
function FunctionalComponent() {
653+
return <div></div>;
654+
}
655+
656+
</script>
657+
658+
<template>
659+
<div></div>
660+
</template>
661+
662+
<style>
663+
.class { background: red}
664+
</style>
665+
"#
666+
.as_bytes(),
667+
);
668+
669+
let (fs, result) = run_cli(
670+
fs,
671+
&mut console,
672+
Args::from(["check", "--write", "--unsafe", vue_file_path.as_str()].as_slice()),
673+
);
674+
675+
assert!(result.is_ok(), "run_cli returned {result:?}");
676+
677+
assert_cli_snapshot(SnapshotPayload::new(
678+
module_path!(),
679+
"full_support_jsx",
680+
fs,
681+
console,
682+
result,
683+
));
684+
}
685+
571686
#[test]
572687
fn format_stdin_successfully() {
573688
let fs = MemoryFileSystem::default();
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
source: crates/biome_cli/tests/snap_test.rs
3+
expression: redactor(content)
4+
---
5+
## `biome.json`
6+
7+
```json
8+
{
9+
"html": {
10+
"formatter": { "enabled": true },
11+
"linter": { "enabled": true },
12+
"experimentalFullSupportEnabled": true
13+
}
14+
}
15+
```
16+
17+
## `file.vue`
18+
19+
```vue
20+
<script lang="jsx">
21+
import { sure } from "sure.js";
22+
import z from "zod";
23+
24+
const schema = z.object().optional();
25+
schema + sure();
26+
27+
function _FunctionalComponent() {
28+
return <div></div>;
29+
}
30+
</script>
31+
32+
<template>
33+
<div></div>
34+
</template>
35+
36+
<style>
37+
.class {
38+
background: red;
39+
}
40+
</style>
41+
42+
```
43+
44+
# Emitted Messages
45+
46+
```block
47+
Checked 1 file in <TIME>. Fixed 1 file.
48+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
source: crates/biome_cli/tests/snap_test.rs
3+
expression: redactor(content)
4+
---
5+
## `biome.json`
6+
7+
```json
8+
{
9+
"html": {
10+
"formatter": { "enabled": true },
11+
"linter": { "enabled": true },
12+
"experimentalFullSupportEnabled": true
13+
}
14+
}
15+
```
16+
17+
## `file.vue`
18+
19+
```vue
20+
<script lang="tsx">
21+
import { sure } from "sure.js";
22+
import z from "zod";
23+
24+
interface Props {
25+
title: string;
26+
}
27+
28+
const schema = z.object().optional();
29+
schema + sure();
30+
const _props: Props = { title: "Hello" };
31+
32+
function _FunctionalComponent() {
33+
return <div></div>;
34+
}
35+
</script>
36+
37+
<template>
38+
<div></div>
39+
</template>
40+
41+
<style>
42+
.class {
43+
background: red;
44+
}
45+
</style>
46+
47+
```
48+
49+
# Emitted Messages
50+
51+
```block
52+
Checked 1 file in <TIME>. Fixed 1 file.
53+
```

crates/biome_html_syntax/src/element_ext.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,42 @@ impl HtmlElement {
202202
is_script && is_lang_typescript
203203
}
204204

205+
/// Returns `true` if the element is a `<script lang="jsx">`
206+
pub fn is_jsx_lang(&self) -> bool {
207+
let is_script = self.is_script_tag();
208+
let lang_attribute = self.find_attribute_by_name("lang");
209+
let is_lang_jsx = lang_attribute.is_some_and(|attribute| {
210+
attribute
211+
.initializer()
212+
.and_then(|initializer| initializer.value().ok())
213+
.and_then(|value| value.as_html_string().cloned())
214+
.and_then(|value| value.value_token().ok())
215+
.is_some_and(|token| {
216+
let text = inner_string_text(&token);
217+
text.eq_ignore_ascii_case("jsx")
218+
})
219+
});
220+
is_script && is_lang_jsx
221+
}
222+
223+
/// Returns `true` if the element is a `<script lang="tsx">`
224+
pub fn is_tsx_lang(&self) -> bool {
225+
let is_script = self.is_script_tag();
226+
let lang_attribute = self.find_attribute_by_name("lang");
227+
let is_lang_tsx = lang_attribute.is_some_and(|attribute| {
228+
attribute
229+
.initializer()
230+
.and_then(|initializer| initializer.value().ok())
231+
.and_then(|value| value.as_html_string().cloned())
232+
.and_then(|value| value.value_token().ok())
233+
.is_some_and(|token| {
234+
let text = inner_string_text(&token);
235+
text.eq_ignore_ascii_case("tsx")
236+
})
237+
});
238+
is_script && is_lang_tsx
239+
}
240+
205241
/// Returns `true` if the element is a `<style lang="sass">` or `<style lang="scss">`
206242
pub fn is_sass_lang(&self) -> bool {
207243
let is_style = self.is_style_tag();

crates/biome_service/src/file_handlers/html.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,10 @@ pub(crate) fn parse_embedded_script(
479479
let file_source = if html_file_source.is_svelte() || html_file_source.is_vue() {
480480
let mut file_source = if element.is_typescript_lang() {
481481
JsFileSource::ts()
482+
} else if element.is_jsx_lang() {
483+
JsFileSource::jsx()
484+
} else if element.is_tsx_lang() {
485+
JsFileSource::tsx()
482486
} else {
483487
JsFileSource::js_module()
484488
};

0 commit comments

Comments
 (0)