diff --git a/CHANGELOG.md b/CHANGELOG.md index 59a0d0852835..ac03385e8a59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,16 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom
``` +- Add partial for `.vue` files. Biome is able to format the script block of Vue files. Contributed by @nhedger + + ```diff + + + + ``` #### Bug fixes diff --git a/crates/biome_cli/src/execute/process_file/format.rs b/crates/biome_cli/src/execute/process_file/format.rs index 733843c3a01f..563eafddfaa9 100644 --- a/crates/biome_cli/src/execute/process_file/format.rs +++ b/crates/biome_cli/src/execute/process_file/format.rs @@ -5,7 +5,7 @@ use crate::execute::process_file::{ }; use crate::execute::TraversalMode; use biome_diagnostics::{category, DiagnosticExt}; -use biome_service::file_handlers::ASTRO_FENCE; +use biome_service::file_handlers::{ASTRO_FENCE, VUE_FENCE}; use biome_service::workspace::RuleCategories; use std::path::Path; use std::sync::atomic::Ordering; @@ -84,6 +84,23 @@ pub(crate) fn format_with_guard<'ctx>( } } + if workspace_file.as_extension() == Some("vue") { + if output.is_empty() { + return Ok(FileStatus::Ignored); + } + if let Some(script) = VUE_FENCE + .captures(&input) + .and_then(|captures| captures.name("script")) + { + output = format!( + "{}{}{}", + &input[..script.start()], + output.as_str(), + &input[script.end()..] + ); + } + } + if output != input { if should_write { workspace_file.update_file(output)?; diff --git a/crates/biome_cli/tests/commands/format.rs b/crates/biome_cli/tests/commands/format.rs index b8296f51a68d..4f83618b2a6f 100644 --- a/crates/biome_cli/tests/commands/format.rs +++ b/crates/biome_cli/tests/commands/format.rs @@ -58,6 +58,42 @@ statement(); ---
"#; +const VUE_IMPLICIT_JS_FILE_UNFORMATTED: &str = r#" +"#; + +const VUE_IMPLICIT_JS_FILE_FORMATTED: &str = r#" +"#; + +const VUE_EXPLICIT_JS_FILE_UNFORMATTED: &str = r#" +"#; + +const VUE_EXPLICIT_JS_FILE_FORMATTED: &str = r#" +"#; + +const VUE_TS_FILE_UNFORMATTED: &str = r#" +"#; + +const VUE_TS_FILE_FORMATTED: &str = r#" +"#; + const APPLY_TRAILING_COMMA_BEFORE: &str = r#" const a = [ longlonglonglongItem1longlonglonglongItem1, @@ -3028,3 +3064,266 @@ fn format_empty_astro_files_write() { result, )); } + +#[test] +fn format_vue_implicit_js_files() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert( + vue_file_path.into(), + VUE_IMPLICIT_JS_FILE_UNFORMATTED.as_bytes(), + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), vue_file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, VUE_IMPLICIT_JS_FILE_UNFORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_vue_implicit_js_files", + fs, + console, + result, + )); +} + +#[test] +fn format_vue_implicit_js_files_write() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert( + vue_file_path.into(), + VUE_IMPLICIT_JS_FILE_UNFORMATTED.as_bytes(), + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--write", + vue_file_path.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, VUE_IMPLICIT_JS_FILE_FORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_vue_implicit_js_files_write", + fs, + console, + result, + )); +} + +#[test] +fn format_vue_explicit_js_files() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert( + vue_file_path.into(), + VUE_EXPLICIT_JS_FILE_UNFORMATTED.as_bytes(), + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), vue_file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, VUE_EXPLICIT_JS_FILE_UNFORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_vue_explicit_js_files", + fs, + console, + result, + )); +} + +#[test] +fn format_vue_explicit_js_files_write() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert( + vue_file_path.into(), + VUE_EXPLICIT_JS_FILE_UNFORMATTED.as_bytes(), + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--write", + vue_file_path.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, VUE_EXPLICIT_JS_FILE_FORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_vue_explicit_js_files_write", + fs, + console, + result, + )); +} + +#[test] +fn format_empty_vue_js_files_write() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert(vue_file_path.into(), "".as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--write", + vue_file_path.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, ""); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_empty_vue_js_files_write", + fs, + console, + result, + )); +} + +#[test] +fn format_vue_ts_files() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert(vue_file_path.into(), VUE_TS_FILE_UNFORMATTED.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), vue_file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, VUE_TS_FILE_UNFORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_vue_ts_files", + fs, + console, + result, + )); +} + +#[test] +fn format_vue_ts_files_write() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert(vue_file_path.into(), VUE_TS_FILE_UNFORMATTED.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--write", + vue_file_path.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, VUE_TS_FILE_FORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_vue_ts_files_write", + fs, + console, + result, + )); +} + +#[test] +fn format_empty_vue_ts_files_write() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let vue_file_path = Path::new("file.vue"); + fs.insert(vue_file_path.into(), "".as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--write", + vue_file_path.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, vue_file_path, ""); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_empty_vue_ts_files_write", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/snapshots/main_commands_format/format_empty_vue_js_files_write.snap b/crates/biome_cli/tests/snapshots/main_commands_format/format_empty_vue_js_files_write.snap new file mode 100644 index 000000000000..3803cc6a03db --- /dev/null +++ b/crates/biome_cli/tests/snapshots/main_commands_format/format_empty_vue_js_files_write.snap @@ -0,0 +1,15 @@ +--- +source: crates/biome_cli/tests/snap_test.rs +expression: content +--- +## `file.vue` + +```vue + +``` + +# Emitted Messages + +```block +Formatted 1 file(s) in