diff --git a/changelog_unreleased/css/18114.md b/changelog_unreleased/css/18114.md new file mode 100644 index 000000000..8645d2adc --- /dev/null +++ b/changelog_unreleased/css/18114.md @@ -0,0 +1,19 @@ +#### Remove unexpected space between font size and line height (#18114 by @kovsu) + + +```css +/* Input */ +a { + font: var(--size)/1; +} + +/* Prettier stable */ +a { + font: var(--size) / 1; +} + +/* Prettier main */ +a { + font: var(--size)/1; +} +``` diff --git a/src/language-css/print/comma-separated-value-group.js b/src/language-css/print/comma-separated-value-group.js index 973380c86..339f2b11e 100644 --- a/src/language-css/print/comma-separated-value-group.js +++ b/src/language-css/print/comma-separated-value-group.js @@ -337,17 +337,6 @@ function printCommaSeparatedValueGroup(path, options, print) { isColorAdjusterFuncNode(parentParentNode) && !hasEmptyRawBefore(iNextNode); - const requireSpaceBeforeOperator = - iNextNextNode?.type === "value-func" || - (iNextNextNode && isWordNode(iNextNextNode)) || - iNode.type === "value-func" || - isWordNode(iNode); - const requireSpaceAfterOperator = - iNextNode.type === "value-func" || - isWordNode(iNextNode) || - iPrevNode?.type === "value-func" || - (iPrevNode && isWordNode(iPrevNode)); - // Space before unary minus followed by a function call. if ( options.parser === "scss" && @@ -360,6 +349,17 @@ function printCommaSeparatedValueGroup(path, options, print) { continue; } + const requireSpaceBeforeOperator = + iNextNextNode?.type === "value-func" || + (iNextNextNode && isWordNode(iNextNextNode)) || + iNode.type === "value-func" || + isWordNode(iNode); + const requireSpaceAfterOperator = + iNextNode.type === "value-func" || + isWordNode(iNextNode) || + iPrevNode?.type === "value-func" || + (iPrevNode && isWordNode(iPrevNode)); + // Formatting `/`, `+`, `-` sign if ( !(isMultiplicationNode(iNextNode) || isMultiplicationNode(iNode)) && @@ -441,6 +441,28 @@ function printCommaSeparatedValueGroup(path, options, print) { continue; } + // Formatting `font` property + if ( + declAncestorProp && + (declAncestorProp === "font" || declAncestorProp.startsWith("--")) + ) { + if ( + isDivisionNode(iNextNode) && + hasEmptyRawBefore(iNextNode) && + isPossibleFontSize(iNode) + ) { + continue; + } + + if ( + isDivisionNode(iNode) && + hasEmptyRawBefore(iNode) && + isPossibleFontSize(iPrevNode) + ) { + continue; + } + } + // Add `space` before next math operation // Note: `grip` property have `/` delimiter and it is not math operation, so // `grid` property handles above @@ -517,4 +539,24 @@ function printCommaSeparatedValueGroup(path, options, print) { return group(indent(fill(parts))); } +function isPossibleFontSize(node) { + if (node?.type === "value-number") { + return true; + } + + if (node?.type !== "value-func") { + return false; + } + + const value = node.value.toLowerCase(); + return ( + value === "var" || + value === "calc" || + value === "min" || + value === "max" || + value === "clamp" || + value.startsWith("--") + ); +} + export default printCommaSeparatedValueGroup; diff --git a/src/language-css/utils/index.js b/src/language-css/utils/index.js index 04b7816be..b2354bdca 100644 --- a/src/language-css/utils/index.js +++ b/src/language-css/utils/index.js @@ -150,7 +150,7 @@ function isMultiplicationNode(node) { } function isDivisionNode(node) { - return node.type === "value-operator" && node.value === "/"; + return node?.type === "value-operator" && node.value === "/"; } function isAdditionNode(node) { @@ -231,7 +231,7 @@ function hasParensAroundNode(node) { } function hasEmptyRawBefore(node) { - return node.raws?.before === ""; + return node?.raws?.before === ""; } function isKeyValuePairNode(node) { diff --git a/tests/format/css/font/__snapshots__/format.test.js.snap b/tests/format/css/font/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..0ca4760b9 --- /dev/null +++ b/tests/format/css/font/__snapshots__/format.test.js.snap @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`font.css format 1`] = ` +====================================options===================================== +parsers: ["css", "scss", "less"] +printWidth: 80 + | printWidth +=====================================input====================================== +.font { + /* No space */ + font: 1rem/1; + --custom-font: 1rem/1; + font: var(--size)/2; + --custom-font: var(--size)/2; + font: calc(var(--size)/2)/2; + font: min(1px, 2px)/2; + font: max(1px, 2px)/2; + font: clamp(1px, 2px, 3px)/2; + + /* Space around */ + font: 1rem / 1; + --font: 1rem / 1; + font: --custom(1px) / 2; + --font: --custom(1px) / 2; + font: calc(var(--size) / 2) / 2; + font: min(1px, 2px) / 2; + font: max(1px, 2px) / 2; + font: clamp(1px, 2px, 3px) / 2; + font: --custom(1px) / 2; + + /* Space before */ + font: 1rem /1; + --font: 1rem /1; + font: --custom(1px) /2; /* Bug*/ + --font: --custom(1px) /2; /* Bug*/ + + /* Space after */ + font: 1rem/ 1; /* Bug*/ + --font: 1rem/ 1; /* Bug*/ + font: --custom(1px)/ 2; /* Bug*/ + --font: --custom(1px)/ 2; /* Bug*/ +} + +=====================================output===================================== +.font { + /* No space */ + font: 1rem/1; + --custom-font: 1rem/1; + font: var(--size)/2; + --custom-font: var(--size)/2; + font: calc(var(--size)/2)/2; + font: min(1px, 2px)/2; + font: max(1px, 2px)/2; + font: clamp(1px, 2px, 3px)/2; + + /* Space around */ + font: 1rem / 1; + --font: 1rem / 1; + font: --custom(1px) / 2; + --font: --custom(1px) / 2; + font: calc(var(--size) / 2) / 2; + font: min(1px, 2px) / 2; + font: max(1px, 2px) / 2; + font: clamp(1px, 2px, 3px) / 2; + font: --custom(1px) / 2; + + /* Space before */ + font: 1rem /1; + --font: 1rem /1; + font: --custom(1px) / 2; /* Bug*/ + --font: --custom(1px) / 2; /* Bug*/ + + /* Space after */ + font: 1rem/1; /* Bug*/ + --font: 1rem/1; /* Bug*/ + font: --custom(1px)/2; /* Bug*/ + --font: --custom(1px)/2; /* Bug*/ +} + +================================================================================ +`; diff --git a/tests/format/css/font/font.css b/tests/format/css/font/font.css new file mode 100644 index 000000000..6ea5b3f45 --- /dev/null +++ b/tests/format/css/font/font.css @@ -0,0 +1,34 @@ +.font { + /* No space */ + font: 1rem/1; + --custom-font: 1rem/1; + font: var(--size)/2; + --custom-font: var(--size)/2; + font: calc(var(--size)/2)/2; + font: min(1px, 2px)/2; + font: max(1px, 2px)/2; + font: clamp(1px, 2px, 3px)/2; + + /* Space around */ + font: 1rem / 1; + --font: 1rem / 1; + font: --custom(1px) / 2; + --font: --custom(1px) / 2; + font: calc(var(--size) / 2) / 2; + font: min(1px, 2px) / 2; + font: max(1px, 2px) / 2; + font: clamp(1px, 2px, 3px) / 2; + font: --custom(1px) / 2; + + /* Space before */ + font: 1rem /1; + --font: 1rem /1; + font: --custom(1px) /2; /* Bug*/ + --font: --custom(1px) /2; /* Bug*/ + + /* Space after */ + font: 1rem/ 1; /* Bug*/ + --font: 1rem/ 1; /* Bug*/ + font: --custom(1px)/ 2; /* Bug*/ + --font: --custom(1px)/ 2; /* Bug*/ +} diff --git a/tests/format/css/font/format.test.js b/tests/format/css/font/format.test.js new file mode 100644 index 000000000..19d2938f3 --- /dev/null +++ b/tests/format/css/font/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ["css", "scss", "less"]);