diff --git a/crates/biome_html_formatter/src/context.rs b/crates/biome_html_formatter/src/context.rs index 3108c8e60668..656596018b82 100644 --- a/crates/biome_html_formatter/src/context.rs +++ b/crates/biome_html_formatter/src/context.rs @@ -4,7 +4,7 @@ use biome_formatter::{ printer::PrinterOptions, AttributePosition, BracketSpacing, CstFormatContext, FormatContext, FormatOptions, IndentStyle, IndentWidth, LineEnding, LineWidth, TransformSourceMap, }; -use biome_html_syntax::HtmlLanguage; +use biome_html_syntax::{HtmlFileSource, HtmlLanguage}; use crate::comments::{FormatHtmlLeadingComment, HtmlCommentStyle, HtmlComments}; @@ -27,7 +27,7 @@ pub struct HtmlFormatOptions { } impl HtmlFormatOptions { - pub fn new() -> Self { + pub fn new(_file_source: HtmlFileSource) -> Self { Self { ..Default::default() } diff --git a/crates/biome_html_formatter/tests/prettier_tests.rs b/crates/biome_html_formatter/tests/prettier_tests.rs index f42abd1fbd0e..8dca42c6a0d5 100644 --- a/crates/biome_html_formatter/tests/prettier_tests.rs +++ b/crates/biome_html_formatter/tests/prettier_tests.rs @@ -21,7 +21,7 @@ fn test_snapshot(input: &'static str, _: &str, _: &str, _: &str) { let test_file = PrettierTestFile::new(input, root_path); let source_type = HtmlFileSource::html(); - let options = HtmlFormatOptions::new() + let options = HtmlFormatOptions::new(HtmlFileSource::html()) .with_indent_style(IndentStyle::Space) .with_indent_width(IndentWidth::default()); diff --git a/crates/biome_html_formatter/tests/quick_test.rs b/crates/biome_html_formatter/tests/quick_test.rs index 123d0e055e85..c9d4a814083f 100644 --- a/crates/biome_html_formatter/tests/quick_test.rs +++ b/crates/biome_html_formatter/tests/quick_test.rs @@ -22,7 +22,7 @@ fn quick_test() { "#; let source_type = HtmlFileSource::html(); let tree = parse_html(src); - let options = HtmlFormatOptions::new() + let options = HtmlFormatOptions::new(HtmlFileSource::html()) .with_indent_style(IndentStyle::Space) .with_line_width(LineWidth::try_from(80).unwrap()) .with_attribute_position(AttributePosition::Multiline); diff --git a/crates/biome_html_formatter/tests/spec_test.rs b/crates/biome_html_formatter/tests/spec_test.rs index ecfd4a4a7bf5..365159512632 100644 --- a/crates/biome_html_formatter/tests/spec_test.rs +++ b/crates/biome_html_formatter/tests/spec_test.rs @@ -33,7 +33,7 @@ pub fn run(spec_input_file: &str, _expected_file: &str, test_directory: &str, _f let source_type: HtmlFileSource = test_file.input_file().as_path().try_into().unwrap(); - let options = HtmlFormatOptions::new(); + let options = HtmlFormatOptions::new(HtmlFileSource::html()); let language = language::HtmlTestFormatLanguage::new(source_type); let snapshot = SpecSnapshot::new( diff --git a/crates/biome_service/src/file_handlers/html.rs b/crates/biome_service/src/file_handlers/html.rs index 8925c36fc1db..c666d29392e9 100644 --- a/crates/biome_service/src/file_handlers/html.rs +++ b/crates/biome_service/src/file_handlers/html.rs @@ -1,5 +1,5 @@ use biome_analyze::{AnalyzerConfiguration, AnalyzerOptions}; -use biome_formatter::Printed; +use biome_formatter::{IndentStyle, IndentWidth, LineEnding, LineWidth, Printed}; use biome_fs::BiomePath; use biome_html_formatter::{format_node, HtmlFormatOptions}; use biome_html_parser::parse_html_with_cache; @@ -18,8 +18,30 @@ use super::{ FormatterCapabilities, ParseResult, ParserCapabilities, SearchCapabilities, }; +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +pub struct HtmlFormatterSettings { + pub line_ending: Option, + pub line_width: Option, + pub indent_width: Option, + pub indent_style: Option, + pub enabled: Option, +} + +impl Default for HtmlFormatterSettings { + fn default() -> Self { + Self { + enabled: Some(false), + indent_style: Default::default(), + indent_width: Default::default(), + line_ending: Default::default(), + line_width: Default::default(), + } + } +} + impl ServiceLanguage for HtmlLanguage { - type FormatterSettings = (); + type FormatterSettings = HtmlFormatterSettings; type LinterSettings = (); type OrganizeImportsSettings = (); type FormatOptions = HtmlFormatOptions; @@ -33,14 +55,40 @@ impl ServiceLanguage for HtmlLanguage { } fn resolve_format_options( - _global: Option<&crate::settings::FormatSettings>, - _overrides: Option<&crate::settings::OverrideSettings>, - _language: Option<&Self::FormatterSettings>, - _path: &biome_fs::BiomePath, - _file_source: &super::DocumentFileSource, + global: Option<&crate::settings::FormatSettings>, + overrides: Option<&crate::settings::OverrideSettings>, + language: Option<&Self::FormatterSettings>, + path: &biome_fs::BiomePath, + file_source: &super::DocumentFileSource, ) -> Self::FormatOptions { - // TODO: actually resolve options - HtmlFormatOptions::default() + let indent_style = language + .and_then(|l| l.indent_style) + .or(global.and_then(|g| g.indent_style)) + .unwrap_or_default(); + let line_width = language + .and_then(|l| l.line_width) + .or(global.and_then(|g| g.line_width)) + .unwrap_or_default(); + let indent_width = language + .and_then(|l| l.indent_width) + .or(global.and_then(|g| g.indent_width)) + .unwrap_or_default(); + + let line_ending = language + .and_then(|l| l.line_ending) + .or(global.and_then(|g| g.line_ending)) + .unwrap_or_default(); + + let options = HtmlFormatOptions::new(file_source.to_html_file_source().unwrap_or_default()) + .with_indent_style(indent_style) + .with_indent_width(indent_width) + .with_line_width(line_width) + .with_line_ending(line_ending); + if let Some(overrides) = overrides { + overrides.to_override_html_format_options(path, options) + } else { + options + } } fn resolve_analyzer_options( diff --git a/crates/biome_service/src/file_handlers/mod.rs b/crates/biome_service/src/file_handlers/mod.rs index 469793f8b2e6..77238dafce73 100644 --- a/crates/biome_service/src/file_handlers/mod.rs +++ b/crates/biome_service/src/file_handlers/mod.rs @@ -304,6 +304,13 @@ impl DocumentFileSource { } } + pub fn to_html_file_source(&self) -> Option { + match self { + DocumentFileSource::Html(html) => Some(*html), + _ => None, + } + } + pub fn can_parse(path: &Path, content: &str) -> bool { let file_source = DocumentFileSource::from(path); match file_source { diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index 8eaf70178351..11b13bb2d539 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -23,6 +23,7 @@ use biome_formatter::{ use biome_fs::BiomePath; use biome_graphql_formatter::context::GraphqlFormatOptions; use biome_graphql_syntax::GraphqlLanguage; +use biome_html_formatter::HtmlFormatOptions; use biome_html_syntax::HtmlLanguage; use biome_js_formatter::context::JsFormatOptions; use biome_js_parser::JsParserOptions; @@ -1001,6 +1002,19 @@ impl OverrideSettings { options } + pub fn to_override_html_format_options( + &self, + path: &Path, + mut options: HtmlFormatOptions, + ) -> HtmlFormatOptions { + for pattern in self.patterns.iter() { + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + pattern.apply_overrides_to_html_format_options(&mut options); + } + } + options + } + pub fn to_override_js_parser_options( &self, path: &Path, @@ -1152,6 +1166,7 @@ pub struct OverrideSettingPattern { pub(crate) cached_json_format_options: RwLock>, pub(crate) cached_css_format_options: RwLock>, pub(crate) cached_graphql_format_options: RwLock>, + pub(crate) cached_html_format_options: RwLock>, pub(crate) cached_js_parser_options: RwLock>, pub(crate) _cached_json_parser_options: RwLock>, pub(crate) cached_css_parser_options: RwLock>, @@ -1321,6 +1336,36 @@ impl OverrideSettingPattern { } } + fn apply_overrides_to_html_format_options(&self, options: &mut HtmlFormatOptions) { + if let Ok(readonly_cache) = self.cached_html_format_options.read() { + if let Some(cached_options) = readonly_cache.as_ref() { + *options = cached_options.clone(); + return; + } + } + + let html_formatter = &self.languages.html.formatter; + let formatter = &self.formatter; + + if let Some(indent_style) = html_formatter.indent_style.or(formatter.indent_style) { + options.set_indent_style(indent_style); + } + if let Some(indent_width) = html_formatter.indent_width.or(formatter.indent_width) { + options.set_indent_width(indent_width) + } + if let Some(line_ending) = html_formatter.line_ending.or(formatter.line_ending) { + options.set_line_ending(line_ending); + } + if let Some(line_width) = html_formatter.line_width.or(formatter.line_width) { + options.set_line_width(line_width); + } + + if let Ok(mut writeonly_cache) = self.cached_html_format_options.write() { + let options = options.clone(); + let _ = writeonly_cache.insert(options); + } + } + fn apply_overrides_to_js_parser_options(&self, options: &mut JsParserOptions) { if let Ok(readonly_cache) = self.cached_js_parser_options.read() { if let Some(cached_options) = readonly_cache.as_ref() {