diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 964af66..307fe2b 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -13,6 +13,7 @@ - [omitNumberLeadingZero](./config/omit-number-leading-zero.md) - [trailingComma](./config/trailing-comma.md) - [formatComments](./config/format-comments.md) + - [alignComments](./config/align-comments.md) - [linebreakInPseudoParens](./config/linebreak-in-pseudo-parens.md) - [declarationOrder](./config/declaration-order.md) - [singleLineBlockThreshold](./config/single-line-block-threshold.md) diff --git a/docs/src/config/align-comments.md b/docs/src/config/align-comments.md new file mode 100644 index 0000000..f76459c --- /dev/null +++ b/docs/src/config/align-comments.md @@ -0,0 +1,61 @@ +# `alignComments` + +Control whether to tweak multi-line comments indentation. + +Default option value is `true`. + +## Example for `false` + +[Playground](https://malva-play.vercel.app/?code=H4sIAAAAAAAAA0tUqOZSAAJ9LYXk%2FNzc1LwShZzMvFQFQ7AoEKCIGmEVNQaLaumDqZLUihLdlNTk%2FKLEksz8PCuFvPy8VGuuWgAzUTX%2BaQAAAA%3D%3D&config=H4sIAAAAAAAAA6vmUlBQSszJTM9zzs%2FNTc0rKVayUkhLzClO5aoFAIntfVEcAAAA&syntax=css) + +When formatting the 4-space indented CSS into 2-space indented CSS: + +```css +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} +``` + +will be formatted as: + +```css +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} +``` + +## Example for `true` + +[Playground](https://malva-play.vercel.app/?code=H4sIAAAAAAAAA0tUqOZSAAJ9LYXk%2FNzc1LwShZzMvFQFQ7AoEKCIGmEVNQaLaumDqZLUihLdlNTk%2FKLEksz8PCuFvPy8VGuuWgAzUTX%2BaQAAAA%3D%3D&config=H4sIAAAAAAAAA6vmUlBQSszJTM9zzs%2FNTc0rKVayUigpKk3lqgUAiNln3BsAAAA%3D&syntax=css) + +When formatting the 4-space indented CSS into 2-space indented CSS: + +```css +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} +``` + +will be formatted as: + +```css +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} +``` diff --git a/dprint_plugin/deployment/schema.json b/dprint_plugin/deployment/schema.json index 5ae5118..7eddfb5 100644 --- a/dprint_plugin/deployment/schema.json +++ b/dprint_plugin/deployment/schema.json @@ -138,6 +138,11 @@ "type": "boolean", "default": false }, + "alignComments": { + "description": "Control whether to tweak multi-line comments indentation.", + "type": "boolean", + "default": true + }, "linebreakInPseudoParens": { "description": "Control whether line break should be inserted in pseudo class/element parens or not if current line is too long.", "type": "boolean", diff --git a/dprint_plugin/src/config.rs b/dprint_plugin/src/config.rs index d1cce8a..bc72993 100644 --- a/dprint_plugin/src/config.rs +++ b/dprint_plugin/src/config.rs @@ -146,6 +146,7 @@ pub(crate) fn resolve_config( trailing_comma: get_value(&mut config, "trailingComma", false, &mut diagnostics), format_comments: get_nullable_value(&mut config, "formatComments", &mut diagnostics) .unwrap_or_else(|| get_value(&mut config, "padComments", false, &mut diagnostics)), + align_comments: get_value(&mut config, "alignComments", true, &mut diagnostics), linebreak_in_pseudo_parens: get_value( &mut config, "linebreakInPseudoParens", diff --git a/malva/src/config.rs b/malva/src/config.rs index da69df2..38a0e50 100644 --- a/malva/src/config.rs +++ b/malva/src/config.rs @@ -119,6 +119,9 @@ pub struct LanguageOptions { /// See [`formatComments`](https://malva.netlify.app/config/format-comments.html) pub format_comments: bool, + #[cfg_attr(feature = "config_serde", serde(alias = "alignComments"))] + pub align_comments: bool, + #[cfg_attr( feature = "config_serde", serde(alias = "linebreakInPseudoParens", alias = "lineBreakInPseudoParens") @@ -266,6 +269,7 @@ impl Default for LanguageOptions { omit_number_leading_zero: false, trailing_comma: false, format_comments: false, + align_comments: true, linebreak_in_pseudo_parens: false, declaration_order: None, single_line_block_threshold: None, diff --git a/malva/src/doc_gen/comment.rs b/malva/src/doc_gen/comment.rs index 0e1af3e..dc33343 100644 --- a/malva/src/doc_gen/comment.rs +++ b/malva/src/doc_gen/comment.rs @@ -35,6 +35,8 @@ pub(crate) fn format_comment<'s>(comment: &Comment<'s>, ctx: &Ctx<'_, 's>) -> Do docs.extend( lines.map(|line| Doc::hard_line().append(Doc::text(line.trim_start()))), ); + } else if ctx.options.align_comments { + docs.append(&mut reflow(comment, ctx)); } else { docs.extend(itertools::intersperse( lines.map(Doc::text), @@ -76,3 +78,30 @@ pub(crate) fn format_comment<'s>(comment: &Comment<'s>, ctx: &Ctx<'_, 's>) -> Do } } } + +pub(super) fn reflow<'s>(comment: &Comment<'s>, ctx: &Ctx<'_, 's>) -> Vec> { + let col = ctx + .line_bounds + .get_line_col(comment.span.start) + .1 + .saturating_sub(1); + let mut docs = Vec::with_capacity(2); + let mut lines = comment.content.split('\n').enumerate().peekable(); + while let Some((i, line)) = lines.next() { + let s = line.strip_suffix('\r').unwrap_or(line); + let s = if s.starts_with([' ', '\t']) && i > 0 { + s.get(col..).unwrap_or(s) + } else { + s + }; + if i > 0 { + if s.trim().is_empty() && lines.peek().is_some() { + docs.push(Doc::empty_line()); + } else { + docs.push(Doc::hard_line()); + } + } + docs.push(Doc::text(s)); + } + docs +} diff --git a/malva/src/line_bounds.rs b/malva/src/line_bounds.rs index 4d3acf1..75b0122 100644 --- a/malva/src/line_bounds.rs +++ b/malva/src/line_bounds.rs @@ -24,7 +24,7 @@ impl LineBounds { pub(crate) fn get_line_col(&self, pos: usize) -> (usize, usize) { let line = self.get_line_at(pos); - (line, pos - self.0[line - 1]) + (line, pos - self.0[line.saturating_sub(1)]) } fn get_line_at(&self, pos: usize) -> usize { diff --git a/malva/tests/fmt/css/align-comments/disabled.css b/malva/tests/fmt/css/align-comments/disabled.css new file mode 100644 index 0000000..2fc3720 --- /dev/null +++ b/malva/tests/fmt/css/align-comments/disabled.css @@ -0,0 +1,8 @@ +/*cfg alignComments = false */ +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} diff --git a/malva/tests/fmt/css/align-comments/disabled.snap b/malva/tests/fmt/css/align-comments/disabled.snap new file mode 100644 index 0000000..99d8549 --- /dev/null +++ b/malva/tests/fmt/css/align-comments/disabled.snap @@ -0,0 +1,11 @@ +--- +source: malva/tests/fmt.rs +--- +/*cfg alignComments = false */ +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} diff --git a/malva/tests/fmt/css/align-comments/enabled.css b/malva/tests/fmt/css/align-comments/enabled.css new file mode 100644 index 0000000..2ab64bb --- /dev/null +++ b/malva/tests/fmt/css/align-comments/enabled.css @@ -0,0 +1,7 @@ +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +} diff --git a/malva/tests/fmt/css/align-comments/enabled.snap b/malva/tests/fmt/css/align-comments/enabled.snap new file mode 100644 index 0000000..dda6dbc --- /dev/null +++ b/malva/tests/fmt/css/align-comments/enabled.snap @@ -0,0 +1,10 @@ +--- +source: malva/tests/fmt.rs +--- +a { + /* comment line 1 + comment line 2 + comment line 3 + */ + text-decoration: none; +}