From fd5e670d31c2349b8e0e73c7d643459cce6c3769 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Tue, 9 Apr 2024 08:58:43 +0800 Subject: [PATCH 1/4] optimize formatting grid properties --- malva/src/doc_gen/stmt.rs | 41 ++++++++++++++++--- .../tests/fmt/less/comments/between-decl.snap | 3 +- .../tests/fmt/scss/comments/between-decl.snap | 3 +- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/malva/src/doc_gen/stmt.rs b/malva/src/doc_gen/stmt.rs index cdf92ce..ca15ce3 100644 --- a/malva/src/doc_gen/stmt.rs +++ b/malva/src/doc_gen/stmt.rs @@ -33,21 +33,23 @@ impl<'s> DocGen<'s> for Declaration<'s> { }) ) }); - if can_break_before_value { - docs.push(Doc::line_or_space().nest(ctx.indent_width)); + let space_after_colon = if can_break_before_value { + Doc::line_or_space().nest(ctx.indent_width) } else { - docs.push(Doc::space()); - } + Doc::space() + }; docs.reserve(self.value.len() * 2); let mut pos = self.colon_span.end; - let mut iter = self.value.iter().peekable(); match &self.name { InterpolableIdent::Literal(Ident { name, .. }) if name.starts_with("--") || name.eq_ignore_ascii_case("filter") => { use raffia::token::Token; + docs.push(space_after_colon); + + let mut iter = self.value.iter().peekable(); while let Some(value) = iter.next() { let span = value.span(); docs.push( @@ -70,7 +72,36 @@ impl<'s> DocGen<'s> for Declaration<'s> { pos = span.end; } } + InterpolableIdent::Literal(Ident { name, .. }) + if name.eq_ignore_ascii_case("grid") + || name.eq_ignore_ascii_case("grid-template") + || name.eq_ignore_ascii_case("grid-template-areas") => + { + for (index, value) in self.value.iter().enumerate() { + let span = value.span(); + let comments = ctx.end_spaced_comments(pos, span.start).collect::>(); + + if !comments.is_empty() { + docs.push(Doc::space()); + } else if ctx.line_bounds.line_distance(pos, span.start) == 0 { + if index == 0 { + docs.push(Doc::line_or_space().nest(ctx.indent_width)); + } else { + docs.push(Doc::space()); + } + } else { + docs.push(Doc::hard_line().nest(ctx.indent_width)); + } + docs.push(Doc::list(comments).nest(ctx.indent_width)); + docs.push(value.doc(ctx)); + + pos = span.end; + } + } _ => { + docs.push(space_after_colon); + + let mut iter = self.value.iter().peekable(); while let Some(value) = iter.next() { let span = value.span(); docs.push( diff --git a/malva/tests/fmt/less/comments/between-decl.snap b/malva/tests/fmt/less/comments/between-decl.snap index 6036a41..b1fb96c 100644 --- a/malva/tests/fmt/less/comments/between-decl.snap +++ b/malva/tests/fmt/less/comments/between-decl.snap @@ -17,7 +17,8 @@ selector { "sidebar content content" // "footer footer footer"; - grid-template-areas: "header header header" // + grid-template-areas: + "header header header" // "sidebar content content" // "footer footer footer"; } diff --git a/malva/tests/fmt/scss/comments/between-decl.snap b/malva/tests/fmt/scss/comments/between-decl.snap index e3b756e..f3222ce 100644 --- a/malva/tests/fmt/scss/comments/between-decl.snap +++ b/malva/tests/fmt/scss/comments/between-decl.snap @@ -17,7 +17,8 @@ selector { "sidebar content content" // "footer footer footer"; - grid-template-areas: "header header header" // + grid-template-areas: + "header header header" // "sidebar content content" // "footer footer footer"; } From 624bcfe5a6624615265f03837acd4efd4561aadf Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Wed, 10 Apr 2024 08:10:40 +0800 Subject: [PATCH 2/4] optimize formatting grid properties --- malva/src/doc_gen/stmt.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/malva/src/doc_gen/stmt.rs b/malva/src/doc_gen/stmt.rs index ca15ce3..6adc7af 100644 --- a/malva/src/doc_gen/stmt.rs +++ b/malva/src/doc_gen/stmt.rs @@ -74,8 +74,9 @@ impl<'s> DocGen<'s> for Declaration<'s> { } InterpolableIdent::Literal(Ident { name, .. }) if name.eq_ignore_ascii_case("grid") - || name.eq_ignore_ascii_case("grid-template") - || name.eq_ignore_ascii_case("grid-template-areas") => + || name + .get(0..13) + .is_some_and(|s| s.eq_ignore_ascii_case("grid-template")) => { for (index, value) in self.value.iter().enumerate() { let span = value.span(); @@ -83,12 +84,10 @@ impl<'s> DocGen<'s> for Declaration<'s> { if !comments.is_empty() { docs.push(Doc::space()); + } else if index == 0 { + docs.push(Doc::line_or_space().nest(ctx.indent_width)); } else if ctx.line_bounds.line_distance(pos, span.start) == 0 { - if index == 0 { - docs.push(Doc::line_or_space().nest(ctx.indent_width)); - } else { - docs.push(Doc::space()); - } + docs.push(Doc::space()); } else { docs.push(Doc::hard_line().nest(ctx.indent_width)); } From d8c0afb776a0829a8cb51dc791e85f9f144f30c6 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Wed, 10 Apr 2024 08:11:06 +0800 Subject: [PATCH 3/4] add tests for grid properties --- malva/tests/fmt/css/grid/grid.css | 114 ++++++++++++++++++++++++++++ malva/tests/fmt/css/grid/grid.snap | 118 +++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 malva/tests/fmt/css/grid/grid.css create mode 100644 malva/tests/fmt/css/grid/grid.snap diff --git a/malva/tests/fmt/css/grid/grid.css b/malva/tests/fmt/css/grid/grid.css new file mode 100644 index 0000000..b8cdb7b --- /dev/null +++ b/malva/tests/fmt/css/grid/grid.css @@ -0,0 +1,114 @@ +/* quotes */ +div { + grid-template-areas: + 'header header' + 'main sidebar' + 'footer footer'; +} + +/* numbers */ +div { + grid-template-columns: + [full-start] minmax(1.50em, 1fr) + [main-start] minmax(.40ch, 75ch) + [main-end] minmax(1em, 1.000fr) + [full-end]; +} + +/* casing */ +div { + GRID: + [top] 1fr + [middle] 1fr + bottom; + + grid-TEMPLATE: + "a a a" 200px + "b b b" 200px + / 200px 200px auto; +} + +/* break before first line if there are any breaks */ +div { + grid-template-columns: + 1fr 100px 3em; + grid: [wide-start] "header header header" 200px [wide-end] + "footer footer footer" 25px + / auto 50px auto; +} + +/** + * https://github.com/prettier/prettier/issues/2703#issuecomment-341188126 + */ +.container { + display: grid; + + /* basic template rows/columns */ + grid-template-columns: 1fr 100px 3em; + grid-template-rows: 1fr 100px 3em; + /* template rows/columns with named grid lines */ + grid-template-columns: + [wide-start] 1fr + [main-start] 500px + [main-end] 1fr + [wide-end]; + grid-template-rows: + [top] 1fr + [middle] 1fr + [bottom]; + /* template rows/columns with functions */ + grid-template-columns: minmax(1em, 1fr) minmax(1em, 80ch) minmax(1em, 1fr); + /* getting really busy with named lines + functions */ + grid-template-columns: + [full-start] minmax(1em, 1fr) + [main-start] minmax(1em, 80ch) + [main-end] minmax(1em, 1fr) + [full-end]; + + grid-template-areas: + "header header header" + "main main sidebar" + "main main sidebar2" + "footer footer footer"; + + /* Shorthand for grid-template-rows, grid-template-columns, and grid-template + areas. In one. This can get really crazy. */ + grid-template: + [row1-start] "header header header" 25px [row1-end] + [row2-start] "footer footer footer" 25px [row2-end] + / auto 50px auto; + + /* The. Worst. This one is shorthand for like everything here smashed into one. But rarely will you actually specify EVERYTHING. */ + grid: + [row1-start] "header header header" 25px [row1-end] + [row2-start] "footer footer footer" 25px [row2-end] + / auto 50px auto; + /* simpler use case: */ + grid: 200px auto / 1fr auto 1fr; + + /* Okay, the the worst of it. The simpler syntaxes: */ + + grid-row-gap: 2em; + grid-column-gap: 1em; + /* shorthand for grid-row-gap + grid-column-gap: */ + grid-gap: 2em 1em; + + grid-auto-columns: 1fr; + grid-auto-rows: 1fr; +} + +.container > .item { + grid-column-start: 1; + grid-column-end: 2; + grid-row-start: -2; + grid-row-end: -1; + + /* shorthands for the above: */ + grid-column: 1 / 2; + grid-column: main; + grid-row: -2 / span 1; + grid-row: footer; + + grid-area: main; + grid-area: 1 / main-start / 3 / main-end; +} diff --git a/malva/tests/fmt/css/grid/grid.snap b/malva/tests/fmt/css/grid/grid.snap new file mode 100644 index 0000000..4f63257 --- /dev/null +++ b/malva/tests/fmt/css/grid/grid.snap @@ -0,0 +1,118 @@ +--- +source: malva/tests/fmt.rs +--- +/* quotes */ +div { + grid-template-areas: + "header header" + "main sidebar" + "footer footer"; +} + +/* numbers */ +div { + grid-template-columns: + [full-start] minmax(1.50em, 1fr) + [main-start] minmax(0.40ch, 75ch) + [main-end] minmax(1em, 1.000fr) + [full-end]; +} + +/* casing */ +div { + grid: + [top] 1fr + [middle] 1fr + bottom; + + grid-template: + "a a a" 200px + "b b b" 200px + / 200px 200px auto; +} + +/* break before first line if there are any breaks */ +div { + grid-template-columns: 1fr 100px 3em; + grid: + [wide-start] "header header header" 200px [wide-end] + "footer footer footer" 25px + / auto 50px auto; +} + +/** + * https://github.com/prettier/prettier/issues/2703#issuecomment-341188126 + */ +.container { + display: grid; + + /* basic template rows/columns */ + grid-template-columns: 1fr 100px 3em; + grid-template-rows: 1fr 100px 3em; + /* template rows/columns with named grid lines */ + grid-template-columns: + [wide-start] 1fr + [main-start] 500px + [main-end] 1fr + [wide-end]; + grid-template-rows: + [top] 1fr + [middle] 1fr + [bottom]; + /* template rows/columns with functions */ + grid-template-columns: minmax(1em, 1fr) minmax(1em, 80ch) minmax(1em, 1fr); + /* getting really busy with named lines + functions */ + grid-template-columns: + [full-start] minmax(1em, 1fr) + [main-start] minmax(1em, 80ch) + [main-end] minmax(1em, 1fr) + [full-end]; + + grid-template-areas: + "header header header" + "main main sidebar" + "main main sidebar2" + "footer footer footer"; + + /* Shorthand for grid-template-rows, grid-template-columns, and grid-template + areas. In one. This can get really crazy. */ + grid-template: + [row1-start] "header header header" 25px [row1-end] + [row2-start] "footer footer footer" 25px [row2-end] + / auto 50px auto; + + /* The. Worst. This one is shorthand for like everything here smashed into one. But rarely will you actually specify EVERYTHING. */ + grid: + [row1-start] "header header header" 25px [row1-end] + [row2-start] "footer footer footer" 25px [row2-end] + / auto 50px auto; + /* simpler use case: */ + grid: 200px auto / 1fr auto 1fr; + + /* Okay, the the worst of it. The simpler syntaxes: */ + + grid-row-gap: 2em; + grid-column-gap: 1em; + /* shorthand for grid-row-gap + grid-column-gap: */ + grid-gap: 2em 1em; + + grid-auto-columns: 1fr; + grid-auto-rows: 1fr; +} + +.container > .item { + grid-column-start: 1; + grid-column-end: 2; + grid-row-start: -2; + grid-row-end: -1; + + /* shorthands for the above: */ + grid-column: 1 / 2; + grid-column: main; + grid-row: -2 / span 1; + grid-row: footer; + + grid-area: main; + grid-area: 1 / main-start / 3 / main-end; +} + From 7295d672e26d3207d1eb1d3529af723a60b38894 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Thu, 11 Apr 2024 07:42:04 +0800 Subject: [PATCH 4/4] refactor --- malva/src/doc_gen/stmt.rs | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/malva/src/doc_gen/stmt.rs b/malva/src/doc_gen/stmt.rs index 6adc7af..d073c18 100644 --- a/malva/src/doc_gen/stmt.rs +++ b/malva/src/doc_gen/stmt.rs @@ -78,24 +78,28 @@ impl<'s> DocGen<'s> for Declaration<'s> { .get(0..13) .is_some_and(|s| s.eq_ignore_ascii_case("grid-template")) => { - for (index, value) in self.value.iter().enumerate() { - let span = value.span(); - let comments = ctx.end_spaced_comments(pos, span.start).collect::>(); - - if !comments.is_empty() { - docs.push(Doc::space()); - } else if index == 0 { - docs.push(Doc::line_or_space().nest(ctx.indent_width)); - } else if ctx.line_bounds.line_distance(pos, span.start) == 0 { - docs.push(Doc::space()); - } else { - docs.push(Doc::hard_line().nest(ctx.indent_width)); - } - docs.push(Doc::list(comments).nest(ctx.indent_width)); - docs.push(value.doc(ctx)); + pos = self + .value + .iter() + .enumerate() + .fold(pos, |pos, (index, value)| { + let span = value.span(); + let comments = ctx.end_spaced_comments(pos, span.start).collect::>(); + + if !comments.is_empty() { + docs.push(Doc::space()); + } else if index == 0 { + docs.push(Doc::line_or_space().nest(ctx.indent_width)); + } else if ctx.line_bounds.line_distance(pos, span.start) == 0 { + docs.push(Doc::space()); + } else { + docs.push(Doc::hard_line().nest(ctx.indent_width)); + } + docs.push(Doc::list(comments).nest(ctx.indent_width)); + docs.push(value.doc(ctx)); - pos = span.end; - } + span.end + }); } _ => { docs.push(space_after_colon);