Skip to content

Commit de0d2d6

Browse files
authored
feat(htmlish): implement indentScriptAndStyle option (#7333)
1 parent 272632f commit de0d2d6

File tree

50 files changed

+581
-90
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+581
-90
lines changed

.changeset/few-bees-reply.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
"@biomejs/biome": minor
3+
---
4+
5+
Implemented the `indentScriptAndStyle` option for vue and svelte files, with the default set to `false` to match [Prettier's `vueIndentScriptAndStyle` option](https://prettier.io/docs/options#vue-files-script-and-style-tags-indentation). When enabled, this option indents the content within `<script>` and `<style>` tags to align with the surrounding HTML structure.
6+
7+
It can be enabled with this configuration:
8+
9+
```json
10+
{
11+
"html": {
12+
"formatter": {
13+
"indentScriptAndStyle": true
14+
}
15+
}
16+
}
17+
```
18+
19+
Which will format this code to:
20+
```vue
21+
<script>
22+
import Component from "./Component.vue";
23+
</script>
24+
```

crates/biome_cli/src/execute/migrate/prettier.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ pub(crate) struct PrettierConfiguration {
6161
end_of_line: EndOfLine,
6262
/// https://prettier.io/docs/options#object-wrap
6363
object_wrap: ObjectWrap,
64+
/// https://prettier.io/docs/options#vue-files-script-and-style-tags-indentation
65+
vue_indent_script_and_style: bool,
6466
/// https://prettier.io/docs/en/configuration.html#configuration-overrides
6567
overrides: Vec<Override>,
6668
}
@@ -81,6 +83,7 @@ impl Default for PrettierConfiguration {
8183
arrow_parens: ArrowParens::default(),
8284
end_of_line: EndOfLine::default(),
8385
object_wrap: ObjectWrap::default(),
86+
vue_indent_script_and_style: false,
8487
overrides: vec![],
8588
}
8689
}
@@ -282,6 +285,7 @@ impl TryFrom<PrettierConfiguration> for biome_configuration::Configuration {
282285
};
283286
let html_formatter_config = HtmlFormatterConfiguration {
284287
self_close_void_elements: Some(SelfCloseVoidElements::Always),
288+
indent_script_and_style: Some(value.vue_indent_script_and_style.into()),
285289
..Default::default()
286290
};
287291

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
use crate::run_cli;
2+
use crate::snap_test::{SnapshotPayload, assert_cli_snapshot, assert_file_contents};
3+
use biome_console::BufferConsole;
4+
use biome_fs::MemoryFileSystem;
5+
use bpaf::Args;
6+
use camino::Utf8Path;
7+
8+
const BIOME_CONFIG_INDENT: &str = r#"
9+
{
10+
"html": {
11+
"formatter": {
12+
"indentScriptAndStyle": true
13+
}
14+
}
15+
}
16+
"#;
17+
18+
const VUE_FILE_UNFORMATTED: &str = r#"<script>
19+
import { something } from "file.vue";
20+
statement ( ) ;
21+
</script>
22+
<template></template>"#;
23+
24+
const VUE_FILE_FORMATTED_INDENTED: &str = r#"<script>
25+
import { something } from "file.vue";
26+
statement();
27+
</script>
28+
<template></template>"#;
29+
30+
const VUE_FILE_FORMATTED_UNINDENTED: &str = r#"<script>
31+
import { something } from "file.vue";
32+
statement();
33+
</script>
34+
<template></template>"#;
35+
36+
#[test]
37+
fn unindent_vue_by_default() {
38+
let fs = MemoryFileSystem::default();
39+
let mut console = BufferConsole::default();
40+
41+
let vue_file_path = Utf8Path::new("file.vue");
42+
fs.insert(vue_file_path.into(), VUE_FILE_UNFORMATTED.as_bytes());
43+
44+
let (fs, result) = run_cli(
45+
fs,
46+
&mut console,
47+
Args::from(["format", "--write"].as_slice()),
48+
);
49+
50+
assert!(result.is_ok(), "run_cli returned {result:?}");
51+
52+
assert_file_contents(&fs, vue_file_path, VUE_FILE_FORMATTED_UNINDENTED);
53+
54+
assert_cli_snapshot(SnapshotPayload::new(
55+
module_path!(),
56+
"unindent_vue_by_default",
57+
fs,
58+
console,
59+
result,
60+
));
61+
}
62+
63+
#[test]
64+
fn indent_vue_by_cli() {
65+
let fs = MemoryFileSystem::default();
66+
let mut console = BufferConsole::default();
67+
68+
let vue_file_path = Utf8Path::new("file.vue");
69+
fs.insert(vue_file_path.into(), VUE_FILE_UNFORMATTED.as_bytes());
70+
71+
let (fs, result) = run_cli(
72+
fs,
73+
&mut console,
74+
Args::from(
75+
[
76+
"format",
77+
"--write",
78+
"--html-formatter-indent-script-and-style=true",
79+
]
80+
.as_slice(),
81+
),
82+
);
83+
84+
assert!(result.is_ok(), "run_cli returned {result:?}");
85+
86+
assert_file_contents(&fs, vue_file_path, VUE_FILE_FORMATTED_INDENTED);
87+
88+
assert_cli_snapshot(SnapshotPayload::new(
89+
module_path!(),
90+
"indent_vue_by_cli",
91+
fs,
92+
console,
93+
result,
94+
));
95+
}
96+
97+
#[test]
98+
fn indent_vue_by_config() {
99+
let fs = MemoryFileSystem::default();
100+
let mut console = BufferConsole::default();
101+
102+
let vue_file_path = Utf8Path::new("file.vue");
103+
fs.insert(vue_file_path.into(), VUE_FILE_UNFORMATTED.as_bytes());
104+
let biome_config = Utf8Path::new("biome.json");
105+
fs.insert(biome_config.into(), BIOME_CONFIG_INDENT.as_bytes());
106+
107+
let (fs, result) = run_cli(
108+
fs,
109+
&mut console,
110+
Args::from(["format", "--write"].as_slice()),
111+
);
112+
113+
assert!(result.is_ok(), "run_cli returned {result:?}");
114+
115+
assert_file_contents(&fs, vue_file_path, VUE_FILE_FORMATTED_INDENTED);
116+
117+
assert_cli_snapshot(SnapshotPayload::new(
118+
module_path!(),
119+
"indent_vue_by_config",
120+
fs,
121+
console,
122+
result,
123+
));
124+
}
125+
126+
const SVELTE_FILE_UNFORMATTED: &str = r#"<script>
127+
import { something } from "file.svelte";
128+
statement ( ) ;
129+
</script>
130+
<div></div>"#;
131+
132+
const SVELTE_FILE_FORMATTED_INDENTED: &str = r#"<script>
133+
import { something } from "file.svelte";
134+
statement();
135+
</script>
136+
<div></div>"#;
137+
138+
const SVELTE_FILE_FORMATTED_UNINDENTED: &str = r#"<script>
139+
import { something } from "file.svelte";
140+
statement();
141+
</script>
142+
<div></div>"#;
143+
144+
#[test]
145+
fn unindent_svelte_by_default() {
146+
let fs = MemoryFileSystem::default();
147+
let mut console = BufferConsole::default();
148+
149+
let svelte_file_path = Utf8Path::new("file.svelte");
150+
fs.insert(svelte_file_path.into(), SVELTE_FILE_UNFORMATTED.as_bytes());
151+
152+
let (fs, result) = run_cli(
153+
fs,
154+
&mut console,
155+
Args::from(["format", "--write"].as_slice()),
156+
);
157+
158+
assert!(result.is_ok(), "run_cli returned {result:?}");
159+
160+
assert_file_contents(&fs, svelte_file_path, SVELTE_FILE_FORMATTED_UNINDENTED);
161+
162+
assert_cli_snapshot(SnapshotPayload::new(
163+
module_path!(),
164+
"indent_svelte_by_default",
165+
fs,
166+
console,
167+
result,
168+
));
169+
}
170+
171+
#[test]
172+
fn indent_svelte_by_cli() {
173+
let fs = MemoryFileSystem::default();
174+
let mut console = BufferConsole::default();
175+
176+
let svelte_file_path = Utf8Path::new("file.svelte");
177+
fs.insert(svelte_file_path.into(), SVELTE_FILE_UNFORMATTED.as_bytes());
178+
179+
let (fs, result) = run_cli(
180+
fs,
181+
&mut console,
182+
Args::from(
183+
[
184+
"format",
185+
"--write",
186+
"--html-formatter-indent-script-and-style=true",
187+
]
188+
.as_slice(),
189+
),
190+
);
191+
192+
assert!(result.is_ok(), "run_cli returned {result:?}");
193+
194+
assert_file_contents(&fs, svelte_file_path, SVELTE_FILE_FORMATTED_INDENTED);
195+
196+
assert_cli_snapshot(SnapshotPayload::new(
197+
module_path!(),
198+
"indent_svelte_by_cli",
199+
fs,
200+
console,
201+
result,
202+
));
203+
}
204+
205+
#[test]
206+
fn indent_svelte_by_config() {
207+
let fs = MemoryFileSystem::default();
208+
let mut console = BufferConsole::default();
209+
210+
let svelte_file_path = Utf8Path::new("file.svelte");
211+
fs.insert(svelte_file_path.into(), SVELTE_FILE_UNFORMATTED.as_bytes());
212+
let biome_config = Utf8Path::new("biome.json");
213+
fs.insert(biome_config.into(), BIOME_CONFIG_INDENT.as_bytes());
214+
215+
let (fs, result) = run_cli(
216+
fs,
217+
&mut console,
218+
Args::from(["format", "--write"].as_slice()),
219+
);
220+
221+
assert!(result.is_ok(), "run_cli returned {result:?}");
222+
223+
assert_file_contents(&fs, svelte_file_path, SVELTE_FILE_FORMATTED_INDENTED);
224+
225+
assert_cli_snapshot(SnapshotPayload::new(
226+
module_path!(),
227+
"indent_svelte_by_config",
228+
fs,
229+
console,
230+
result,
231+
));
232+
}

crates/biome_cli/tests/cases/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod handle_svelte_files;
1515
mod handle_vue_files;
1616
mod html;
1717
mod included_files;
18+
mod indent_script_and_style;
1819
mod linter_domains;
1920
mod linter_groups_plain;
2021
mod migrate_v2;

crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/check_stdin_write_successfully.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ var foo: string = "";
1919

2020
```block
2121
<script context="module" lang="ts">
22-
import Button from "./components/Button.svelte";
23-
import { Form } from "./components/Form.svelte";
22+
import Button from "./components/Button.svelte";
23+
import { Form } from "./components/Form.svelte";
2424
25-
debugger;
26-
statement();
27-
var foo: string = "";
25+
debugger;
26+
statement();
27+
var foo: string = "";
2828
</script>
2929
<div></div>
3030
```

crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/check_stdin_write_unsafe_successfully.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ var foo: string = "";
1919

2020
```block
2121
<script context="module" lang="ts">
22-
statement();
23-
var _foo: string = "";
22+
statement();
23+
var _foo: string = "";
2424
</script>
2525
<div></div>
2626
```

crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/format_stdin_successfully.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const hello : string = "world";
1616

1717
```block
1818
<script context="module" lang="ts">
19-
import Button from "./components/Button.svelte";
20-
const hello: string = "world";
19+
import Button from "./components/Button.svelte";
20+
const hello: string = "world";
2121
</script>
2222
<div></div>
2323
```

crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/format_stdin_write_successfully.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const hello : string = "world";
1616

1717
```block
1818
<script context="module" lang="ts">
19-
import Button from "./components/Button.svelte";
20-
const hello: string = "world";
19+
import Button from "./components/Button.svelte";
20+
const hello: string = "world";
2121
</script>
2222
<div></div>
2323
```

crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/format_svelte_carriage_return_line_feed_files.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ file.svelte format ━━━━━━━━━━━━━━━━━━━━
3131
3232
1 1 │ <script>␍
3333
2 │ - ··const·a····=·"b";␍
34-
2 │ + const·a·=·"b";
34+
2 │ + const·a·=·"b";
3535
3 3 │ </script>␍
3636
4 4 │ <div></div>
3737

crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/format_svelte_ts_context_module_files.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ file.svelte format ━━━━━━━━━━━━━━━━━━━━
3333
1 1 │ <script context="module" lang="ts">
3434
2 │ - import·····Button·····from·"./components/Button.svelte";
3535
3 │ - const·hello··:······string······=·"world";
36-
2 │ + import·Button·from·"./components/Button.svelte";
37-
3 │ + const·hello:·string·=·"world";
36+
2 │ + import·Button·from·"./components/Button.svelte";
37+
3 │ + const·hello:·string·=·"world";
3838
4 4 │ </script>
3939
5 5 │ <div></div>
4040

0 commit comments

Comments
 (0)