diff --git a/changelog_unreleased/css/19960.md b/changelog_unreleased/css/19960.md new file mode 100644 index 000000000..475c3618b --- /dev/null +++ b/changelog_unreleased/css/19960.md @@ -0,0 +1,33 @@ +#### Preserve empty lines after function calls in parenthesized values (#19960 by @kovsu) + + +```css +/* Input */ +a { + background: linear-gradient( + to right, + rgba(0, 0, 0, 0.5) calc(50% - 1px), + + transparent calc(50% + 1px) + ); +} + +/* Prettier stable */ +a { + background: linear-gradient( + to right, + rgba(0, 0, 0, 0.5) calc(50% - 1px), + transparent calc(50% + 1px) + ); +} + +/* Prettier main */ +a { + background: linear-gradient( + to right, + rgba(0, 0, 0, 0.5) calc(50% - 1px), + + transparent calc(50% + 1px) + ); +} +``` diff --git a/src/language-css/loc.js b/src/language-css/loc.js index 2264391ad..5c4707c09 100644 --- a/src/language-css/loc.js +++ b/src/language-css/loc.js @@ -33,6 +33,10 @@ function calculateLocStart(node, text) { } function calculateLocEnd(node, text) { + if (node.type === "value-func" && node.group?.close) { + return calculateLocEnd(node.group.close, text); + } + if (node.type === "css-comment" && node.inline) { return skipEverythingButNewLine(text, node.source.startOffset); } diff --git a/tests/format/css/parens/__snapshots__/format.test.js.snap b/tests/format/css/parens/__snapshots__/format.test.js.snap index 32d80c3f6..b2d1ecc7a 100644 --- a/tests/format/css/parens/__snapshots__/format.test.js.snap +++ b/tests/format/css/parens/__snapshots__/format.test.js.snap @@ -1,5 +1,46 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +exports[`empty-line-after-function.css format 1`] = ` +====================================options===================================== +parsers: ["css"] + printWidth: 80 (default) | +=====================================input====================================== +a { + clip-path: polygon( + 0 calc(100% - 1px), + + 100% 100% + ); + background: linear-gradient( + to right, + + rgba(0, 0, 0, 0.5) calc(50% - 1px), + + + + transparent + ); +} + +=====================================output===================================== +a { + clip-path: polygon( + 0 calc(100% - 1px), + + 100% 100% + ); + background: linear-gradient( + to right, + + rgba(0, 0, 0, 0.5) calc(50% - 1px), + + transparent + ); +} + +================================================================================ +`; + exports[`empty-lines.css format 1`] = ` ====================================options===================================== parsers: ["css"] diff --git a/tests/format/css/parens/empty-line-after-function.css b/tests/format/css/parens/empty-line-after-function.css new file mode 100644 index 000000000..50730f2a0 --- /dev/null +++ b/tests/format/css/parens/empty-line-after-function.css @@ -0,0 +1,16 @@ +a { + clip-path: polygon( + 0 calc(100% - 1px), + + 100% 100% + ); + background: linear-gradient( + to right, + + rgba(0, 0, 0, 0.5) calc(50% - 1px), + + + + transparent + ); +} diff --git a/tests/format/less/parens/__snapshots__/format.test.js.snap b/tests/format/less/parens/__snapshots__/format.test.js.snap index 9fb714b35..352116906 100644 --- a/tests/format/less/parens/__snapshots__/format.test.js.snap +++ b/tests/format/less/parens/__snapshots__/format.test.js.snap @@ -33,6 +33,43 @@ parsers: ["less"] ================================================================================ `; +exports[`empty-line-after-function.less format 1`] = ` +====================================options===================================== +parsers: ["less"] + printWidth: 80 (default) | +=====================================input====================================== +a { + clip-path: polygon( + 0 calc(100% - 1px), + + 100% 100% + ); + width: fn( + 1px calc(1px + 2px), + + + + 2px 3px + ); +} + +=====================================output===================================== +a { + clip-path: polygon( + 0 calc(100% - 1px), + + 100% 100% + ); + width: fn( + 1px calc(1px + 2px), + + 2px 3px + ); +} + +================================================================================ +`; + exports[`parens.less format 1`] = ` ====================================options===================================== parsers: ["less"] diff --git a/tests/format/less/parens/empty-line-after-function.less b/tests/format/less/parens/empty-line-after-function.less new file mode 100644 index 000000000..7cc9b6816 --- /dev/null +++ b/tests/format/less/parens/empty-line-after-function.less @@ -0,0 +1,14 @@ +a { + clip-path: polygon( + 0 calc(100% - 1px), + + 100% 100% + ); + width: fn( + 1px calc(1px + 2px), + + + + 2px 3px + ); +} diff --git a/tests/format/scss/map/__snapshots__/format.test.js.snap b/tests/format/scss/map/__snapshots__/format.test.js.snap index 4ea8b1c6b..1d02a019b 100644 --- a/tests/format/scss/map/__snapshots__/format.test.js.snap +++ b/tests/format/scss/map/__snapshots__/format.test.js.snap @@ -1114,6 +1114,134 @@ $map: ( ================================================================================ `; +exports[`empty-line-after-function.scss - {"trailingComma":"es5"} format 1`] = ` +====================================options===================================== +parsers: ["scss"] +trailingComma: "es5" + printWidth: 80 (default) | +=====================================input====================================== +$map: ( + a: calc(1px + 2px), + + b: rgba(0, 0, 0, 0.5), + + c: 1px, + + d: fn(fn(1)), + + e: 2px +); + +$map: ( + a: calc(1px + 2px), // comment + + b: 2px, +); + +$map: ( + a: calc(1px + 2px), // comment + + + + + b: 2px, +); + + +=====================================output===================================== +$map: ( + a: calc(1px + 2px), + + b: rgba(0, 0, 0, 0.5), + + c: 1px, + + d: fn(fn(1)), + + e: 2px, +); + +$map: ( + a: calc(1px + 2px), + + // comment + b: 2px, +); + +$map: ( + a: calc(1px + 2px), + + // comment + b: 2px, +); + +================================================================================ +`; + +exports[`empty-line-after-function.scss - {"trailingComma":"none"} format 1`] = ` +====================================options===================================== +parsers: ["scss"] +trailingComma: "none" + printWidth: 80 (default) | +=====================================input====================================== +$map: ( + a: calc(1px + 2px), + + b: rgba(0, 0, 0, 0.5), + + c: 1px, + + d: fn(fn(1)), + + e: 2px +); + +$map: ( + a: calc(1px + 2px), // comment + + b: 2px, +); + +$map: ( + a: calc(1px + 2px), // comment + + + + + b: 2px, +); + + +=====================================output===================================== +$map: ( + a: calc(1px + 2px), + + b: rgba(0, 0, 0, 0.5), + + c: 1px, + + d: fn(fn(1)), + + e: 2px +); + +$map: ( + a: calc(1px + 2px), + + // comment + b: 2px +); + +$map: ( + a: calc(1px + 2px), + + // comment + b: 2px +); + +================================================================================ +`; + exports[`key-values.scss - {"trailingComma":"es5"} format 1`] = ` ====================================options===================================== parsers: ["scss"] diff --git a/tests/format/scss/map/empty-line-after-function.scss b/tests/format/scss/map/empty-line-after-function.scss new file mode 100644 index 000000000..e84fe7a73 --- /dev/null +++ b/tests/format/scss/map/empty-line-after-function.scss @@ -0,0 +1,27 @@ +$map: ( + a: calc(1px + 2px), + + b: rgba(0, 0, 0, 0.5), + + c: 1px, + + d: fn(fn(1)), + + e: 2px +); + +$map: ( + a: calc(1px + 2px), // comment + + b: 2px, +); + +$map: ( + a: calc(1px + 2px), // comment + + + + + b: 2px, +); +