diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a8b0befc9c..b9d5432d6f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,20 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b Contributed by @Conaclos +- Add new command `biome clean`. Use this command to purge all the logs emitted by the Biome daemon. This command is really useful, because the Biome daemon tends + log many files and contents during its lifecycle. This means that if your editor is open for hours (or even days), the `biome-logs` folder could become quite heavy. Contributed by @ematipico + +- Add support for formatting and linting CSS files from the CLI. These operations are **opt-in** for the time being. + + If you don't have a configuration file, you can enable these features with `--css-formatter-enabled` and `--css-linter-enabled`: + + ```shell + biome check --css-formatter-enabled=true --css-linter-enabled=true ./ + ``` + Contributed by @ematipico + +- Add new CLI options to control the CSS formatting. Check the [CLI reference page](https://biomejs.dev/reference/cli/) for more details. Contributed by @ematipico + #### Enhancements - Biome now executes commands (lint, format, check and ci) on the working directory by default. [#2266](https://github.com/biomejs/biome/issues/2266) Contributed by @unvalley @@ -127,6 +141,11 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b Contributed by @Conaclos +- Add option `javascript.linter.enabled` to control the linter for JavaScript (and its super languages) files. Contributed by @ematipico +- Add option `json.linter.enabled` to control the linter for JSON (and its super languages) files. Contributed by @ematipico +- Add option `css.linter.enabled` to control the linter for CSS (and its super languages) files. Contributed by @ematipico +- Add option `css.formatter`, to control the formatter options for CSS (and its super languages) files. Contributed by @ematipico + #### Enhancements - The `javascript.formatter.trailingComma` option is deprecated and renamed to `javascript.formatter.trailingCommas`. The corresponding CLI option `--trailing-comma` is also deprecated and renamed to `--trailing-commas`. Details can be checked in [#2492](https://github.com/biomejs/biome/pull/2492). Contributed by @Sec-ant diff --git a/crates/biome_cli/Cargo.toml b/crates/biome_cli/Cargo.toml index 7607ad1a707..0037c430ea6 100644 --- a/crates/biome_cli/Cargo.toml +++ b/crates/biome_cli/Cargo.toml @@ -74,8 +74,7 @@ regex = { workspace = true } tokio = { workspace = true, features = ["io-util"] } [features] -docgen = ["bpaf/docgen"] -format_css = ["biome_css_formatter/format_css"] +docgen = ["bpaf/docgen"] [lints] workspace = true diff --git a/crates/biome_cli/src/commands/format.rs b/crates/biome_cli/src/commands/format.rs index 61577c7b412..093d1e7c221 100644 --- a/crates/biome_cli/src/commands/format.rs +++ b/crates/biome_cli/src/commands/format.rs @@ -51,7 +51,7 @@ pub(crate) fn format( files_configuration, write, mut json_formatter, - mut css_formatter, + css_formatter, since, staged, changed, @@ -130,27 +130,8 @@ pub(crate) fn format( } } } - // TODO: remove in biome 2.0 - if let Some(css_formatter) = css_formatter.as_mut() { - if let Some(indent_size) = css_formatter.indent_size { - let diagnostic = DeprecatedArgument::new(markup! { - "The argument ""--css-formatter-indent-size"" is deprecated, it will be removed in the next major release. Use ""--css-formatter-indent-width"" instead." - }); - console.error(markup! { - {PrintDiagnostic::simple(&diagnostic)} - }); - if css_formatter.indent_width.is_none() { - css_formatter.indent_width = Some(indent_size); - } - } - } - - if css_formatter.is_some() { - let css = configuration.css.get_or_insert_with(Default::default); - css.formatter.merge_with(css_formatter); - } - configuration.files.merge_with(files_configuration); + // merge formatter options if !configuration .formatter .as_ref() @@ -163,6 +144,10 @@ pub(crate) fn format( formatter.enabled = Some(true); } + if css_formatter.is_some() { + let css = configuration.css.get_or_insert_with(Default::default); + css.formatter.merge_with(css_formatter); + } if javascript_formatter.is_some() { let javascript = configuration .javascript @@ -173,6 +158,8 @@ pub(crate) fn format( let json = configuration.json.get_or_insert_with(Default::default); json.formatter.merge_with(json_formatter); } + + configuration.files.merge_with(files_configuration); configuration.vcs.merge_with(vcs_configuration); // check if support of git ignore files is enabled diff --git a/crates/biome_cli/src/commands/lint.rs b/crates/biome_cli/src/commands/lint.rs index 035eef8992a..63c01697841 100644 --- a/crates/biome_cli/src/commands/lint.rs +++ b/crates/biome_cli/src/commands/lint.rs @@ -5,6 +5,9 @@ use crate::commands::{ use crate::{ execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution, TraversalMode, }; +use biome_configuration::css::PartialCssLinter; +use biome_configuration::javascript::PartialJavascriptLinter; +use biome_configuration::json::PartialJsonLinter; use biome_configuration::linter::RuleSelector; use biome_configuration::vcs::PartialVcsConfiguration; use biome_configuration::{ @@ -30,6 +33,9 @@ pub(crate) struct LintCommandPayload { pub(crate) staged: bool, pub(crate) changed: bool, pub(crate) since: Option, + pub(crate) javascript_linter: Option, + pub(crate) json_linter: Option, + pub(crate) css_linter: Option, } /// Handler for the "lint" command of the Biome CLI @@ -47,6 +53,9 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<( staged, changed, since, + javascript_linter, + css_linter, + json_linter, } = payload; setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); @@ -96,6 +105,21 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<( ..Default::default() }); + if css_linter.is_some() { + let css = fs_configuration.css.get_or_insert_with(Default::default); + css.linter.merge_with(css_linter); + } + if javascript_linter.is_some() { + let javascript = fs_configuration + .javascript + .get_or_insert_with(Default::default); + javascript.linter.merge_with(javascript_linter); + } + if json_linter.is_some() { + let json = fs_configuration.json.get_or_insert_with(Default::default); + json.linter.merge_with(json_linter); + } + // check if support of git ignore files is enabled let vcs_base_path = configuration_path.or(session.app.fs.working_directory()); let (vcs_base_path, gitignore_matches) = diff --git a/crates/biome_cli/src/commands/mod.rs b/crates/biome_cli/src/commands/mod.rs index d0d9ad9b33f..87ef0a02e96 100644 --- a/crates/biome_cli/src/commands/mod.rs +++ b/crates/biome_cli/src/commands/mod.rs @@ -4,14 +4,17 @@ use crate::diagnostics::DeprecatedConfigurationFile; use crate::execute::Stdin; use crate::logging::LoggingKind; use crate::{CliDiagnostic, CliSession, LoggingLevel, VERSION}; +use biome_configuration::css::PartialCssLinter; +use biome_configuration::javascript::PartialJavascriptLinter; +use biome_configuration::json::PartialJsonLinter; use biome_configuration::linter::RuleSelector; use biome_configuration::{ - css::partial_css_formatter, javascript::partial_javascript_formatter, - json::partial_json_formatter, partial_configuration, partial_files_configuration, - partial_formatter_configuration, partial_linter_configuration, vcs::partial_vcs_configuration, - vcs::PartialVcsConfiguration, PartialCssFormatter, PartialFilesConfiguration, - PartialFormatterConfiguration, PartialJavascriptFormatter, PartialJsonFormatter, - PartialLinterConfiguration, + css::partial_css_formatter, css::partial_css_linter, javascript::partial_javascript_formatter, + javascript::partial_javascript_linter, json::partial_json_formatter, json::partial_json_linter, + partial_configuration, partial_files_configuration, partial_formatter_configuration, + partial_linter_configuration, vcs::partial_vcs_configuration, vcs::PartialVcsConfiguration, + PartialCssFormatter, PartialFilesConfiguration, PartialFormatterConfiguration, + PartialJavascriptFormatter, PartialJsonFormatter, PartialLinterConfiguration, }; use biome_configuration::{ConfigurationDiagnostic, PartialConfiguration}; use biome_console::{markup, Console, ConsoleExt}; @@ -150,6 +153,15 @@ pub enum BiomeCommand { #[bpaf(external(partial_files_configuration), optional, hide_usage)] files_configuration: Option, + #[bpaf(external(partial_javascript_linter), optional, hide_usage)] + javascript_linter: Option, + + #[bpaf(external(partial_json_linter), optional, hide_usage)] + json_linter: Option, + + #[bpaf(external(partial_css_linter), optional, hide_usage, hide)] + css_linter: Option, + #[bpaf(external, hide_usage)] cli_options: CliOptions, diff --git a/crates/biome_cli/src/commands/rage.rs b/crates/biome_cli/src/commands/rage.rs index 7d3edd44e9c..410c1704710 100644 --- a/crates/biome_cli/src/commands/rage.rs +++ b/crates/biome_cli/src/commands/rage.rs @@ -256,6 +256,18 @@ impl Display for RageConfiguration<'_, '_> { {KeyValuePair("Line width", markup!({DebugDisplayOption(json_formatter_configuration.line_width.map(|lw| lw.get()))}))} {KeyValuePair("Trailing Commas", markup!({DebugDisplayOption(json_formatter_configuration.trailing_commas)}))} ).fmt(fmt)?; + + let css_formatter_configuration = + configuration.get_css_formatter_configuration(); + markup! ( + {Section("CSS Formatter")} + {KeyValuePair("Enabled", markup!({DebugDisplay(css_formatter_configuration.enabled)}))} + {KeyValuePair("Indent style", markup!({DebugDisplay(css_formatter_configuration.indent_style)}))} + {KeyValuePair("Indent width", markup!({DebugDisplay(css_formatter_configuration.indent_width)}))} + {KeyValuePair("Line ending", markup!({DebugDisplay(css_formatter_configuration.line_ending)}))} + {KeyValuePair("Line width", markup!({DebugDisplay(css_formatter_configuration.line_width)}))} + {KeyValuePair("Quote style", markup!({DebugDisplay(css_formatter_configuration.quote_style)}))} + ).fmt(fmt)?; } // Print linter configuration if --linter option is true @@ -263,8 +275,8 @@ impl Display for RageConfiguration<'_, '_> { let linter_configuration = configuration.get_linter_rules(); markup! ( {Section("Linter")} - {KeyValuePair("Recommended", markup!({DebugDisplay(linter_configuration.recommended.unwrap_or(false))}))} - {KeyValuePair("All", markup!({DebugDisplay(linter_configuration.all.unwrap_or(false))}))} + {KeyValuePair("Recommended", markup!({DebugDisplay(linter_configuration.recommended.unwrap_or_default())}))} + {KeyValuePair("All", markup!({DebugDisplay(linter_configuration.all.unwrap_or_default())}))} {RageConfigurationLintRules("Rules",linter_configuration)} ).fmt(fmt)?; } diff --git a/crates/biome_cli/src/lib.rs b/crates/biome_cli/src/lib.rs index 384f93c3bcc..f17171e8b19 100644 --- a/crates/biome_cli/src/lib.rs +++ b/crates/biome_cli/src/lib.rs @@ -122,6 +122,9 @@ impl<'app> CliSession<'app> { staged, changed, since, + css_linter, + javascript_linter, + json_linter, } => commands::lint::lint( self, LintCommandPayload { @@ -137,6 +140,9 @@ impl<'app> CliSession<'app> { staged, changed, since, + css_linter, + javascript_linter, + json_linter, }, ), BiomeCommand::Ci { diff --git a/crates/biome_cli/tests/cases/handle_css_files.rs b/crates/biome_cli/tests/cases/handle_css_files.rs new file mode 100644 index 00000000000..ff0025fc8c5 --- /dev/null +++ b/crates/biome_cli/tests/cases/handle_css_files.rs @@ -0,0 +1,183 @@ +use crate::run_cli; +use crate::snap_test::{assert_cli_snapshot, SnapshotPayload}; +use biome_console::BufferConsole; +use biome_fs::MemoryFileSystem; +use biome_service::DynRef; +use bpaf::Args; +use std::path::Path; + +#[test] +fn should_not_format_files_by_default() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let css_file_content = r#"html {}"#; + let css_file = Path::new("input.css"); + fs.insert(css_file.into(), css_file_content.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), css_file.as_os_str().to_str().unwrap()].as_slice()), + ); + + // no files processed error + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_not_format_files_by_default", + fs, + console, + result, + )); +} + +#[test] +fn should_format_files_by_when_opt_in() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let css_file_content = r#"html {}"#; + let css_file = Path::new("input.css"); + fs.insert(css_file.into(), css_file_content.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--css-formatter-enabled=true", + css_file.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + // not formatted error + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_format_files_by_when_opt_in", + fs, + console, + result, + )); +} + +#[test] +fn should_format_write_files_by_when_opt_in() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let css_file_content = r#"html {}"#; + let css_file = Path::new("input.css"); + fs.insert(css_file.into(), css_file_content.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "format", + "--write", + "--css-formatter-enabled=true", + css_file.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_format_write_files_by_when_opt_in", + fs, + console, + result, + )); +} + +#[test] +fn should_not_lint_files_by_default() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("biome.json"); + fs.insert( + file_path.into(), + r#"{ + "linter": { "rules": { "all": true } } +} +"# + .as_bytes(), + ); + + let css_file_content = r#"html {}"#; + let css_file = Path::new("input.css"); + fs.insert(css_file.into(), css_file_content.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["lint", css_file.as_os_str().to_str().unwrap()].as_slice()), + ); + + // no files processed error + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_not_lint_files_by_default", + fs, + console, + result, + )); +} + +#[test] +fn should_lint_files_by_when_enabled() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("biome.json"); + fs.insert( + file_path.into(), + r#"{ + "linter": { "rules": { "all": true } } +} +"# + .as_bytes(), + ); + + let css_file_content = r#"html {}"#; + let css_file = Path::new("input.css"); + fs.insert(css_file.into(), css_file_content.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + "lint", + "--css-linter-enabled=true", + css_file.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + // diagnostic + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_lint_files_by_when_enabled", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/cases/mod.rs b/crates/biome_cli/tests/cases/mod.rs index 0c086ce1cc3..7469794861f 100644 --- a/crates/biome_cli/tests/cases/mod.rs +++ b/crates/biome_cli/tests/cases/mod.rs @@ -7,6 +7,7 @@ mod config_path; mod cts_files; mod diagnostics; mod handle_astro_files; +mod handle_css_files; mod handle_svelte_files; mod handle_vue_files; mod included_files; diff --git a/crates/biome_cli/tests/commands/format.rs b/crates/biome_cli/tests/commands/format.rs index f0f6b0f0aa7..a1278472aaf 100644 --- a/crates/biome_cli/tests/commands/format.rs +++ b/crates/biome_cli/tests/commands/format.rs @@ -2631,8 +2631,9 @@ fn should_apply_different_formatting() { }, "css": { "formatter": { + "enabled": true, "lineWidth": 40, - "indentSize": 6 + "indentWidth": 6 } } }"#, @@ -2730,7 +2731,8 @@ const a = { "--json-formatter-line-width=20", "--json-formatter-indent-size=2", "--css-formatter-line-width=40", - "--css-formatter-indent-size=6", + "--css-formatter-indent-width=6", + "--css-formatter-enabled=true", json_file.as_os_str().to_str().unwrap(), js_file.as_os_str().to_str().unwrap(), css_file.as_os_str().to_str().unwrap(), diff --git a/crates/biome_cli/tests/snapshots/main_cases_handle_css_files/should_format_files_by_when_opt_in.snap b/crates/biome_cli/tests/snapshots/main_cases_handle_css_files/should_format_files_by_when_opt_in.snap new file mode 100644 index 00000000000..169f83e7f52 --- /dev/null +++ b/crates/biome_cli/tests/snapshots/main_cases_handle_css_files/should_format_files_by_when_opt_in.snap @@ -0,0 +1,40 @@ +--- +source: crates/biome_cli/tests/snap_test.rs +expression: content +--- +## `input.css` + +```css +html {} +``` + +# Termination Message + +```block +format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Some errors were emitted while running checks. + + + +``` + +# Emitted Messages + +```block +input.css format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Formatter would have printed the following content: + + 1 │ - html·{} + 1 │ + html·{ + 2 │ + } + 3 │ + + + +``` + +```block +Checked 1 file in