diff --git a/CHANGELOG.md b/CHANGELOG.md index 7166a196164d..86b92a4b1df4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix source maps issue resulting in a crash ([#11319](https://github.com/tailwindlabs/tailwindcss/pull/11319)) - Fallback to RegEx based parser when using custom transformers or extractors ([#11335](https://github.com/tailwindlabs/tailwindcss/pull/11335)) - Bump `lightningcss` and reflect related improvements in tests ([#11550](https://github.com/tailwindlabs/tailwindcss/pull/11550)) +- Fix incorrect spaces around `-` in `calc()` expression ([#12283](https://github.com/tailwindlabs/tailwindcss/pull/12283)) ### Added diff --git a/package-lock.json b/package-lock.json index a753f4c9f065..83a5521deab2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,7 +101,7 @@ "devDependencies": { "rollup": "^3.29.4", "rollup-plugin-postcss": "^4.0.2", - "sass": "1.69.4" + "sass": "^1.69.4" } }, "integrations/tailwindcss-cli": { @@ -19178,7 +19178,7 @@ "requires": { "rollup": "^3.29.4", "rollup-plugin-postcss": "^4.0.2", - "sass": "1.69.4" + "sass": "^1.69.4" } }, "@tailwindcss/integrations-tailwindcss-cli": { @@ -29825,7 +29825,7 @@ "requires": { "rollup": "^3.29.4", "rollup-plugin-postcss": "^4.0.2", - "sass": "1.69.4" + "sass": "^1.69.4" } }, "@tailwindcss/integrations-tailwindcss-cli": { diff --git a/src/util/dataTypes.js b/src/util/dataTypes.js index 9a98f2d3d094..d4fef2e4a05f 100644 --- a/src/util/dataTypes.js +++ b/src/util/dataTypes.js @@ -85,6 +85,29 @@ export function normalize(value, context = null, isRoot = true) { */ function normalizeMathOperatorSpacing(value) { let preventFormattingInFunctions = ['theme'] + let preventFormattingKeywords = [ + 'min-content', + 'max-content', + 'fit-content', + + // Env + 'safe-area-inset-top', + 'safe-area-inset-right', + 'safe-area-inset-bottom', + 'safe-area-inset-left', + + 'titlebar-area-x', + 'titlebar-area-y', + 'titlebar-area-width', + 'titlebar-area-height', + + 'keyboard-inset-top', + 'keyboard-inset-right', + 'keyboard-inset-bottom', + 'keyboard-inset-left', + 'keyboard-inset-width', + 'keyboard-inset-height', + ] return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => { let result = '' @@ -127,6 +150,13 @@ function normalizeMathOperatorSpacing(value) { result += consumeUntil([')', ',']) } + // Skip formatting of known keywords + else if (preventFormattingKeywords.some((keyword) => peek(keyword))) { + let keyword = preventFormattingKeywords.find((keyword) => peek(keyword)) + result += keyword + i += keyword.length - 1 + } + // Skip formatting inside known functions else if (preventFormattingInFunctions.some((fn) => peek(fn))) { result += consumeUntil([')']) diff --git a/tests/arbitrary-values.test.js b/tests/arbitrary-values.test.js index 76d2d0eca10b..fe85f431f82a 100644 --- a/tests/arbitrary-values.test.js +++ b/tests/arbitrary-values.test.js @@ -638,3 +638,31 @@ it('should support underscores in arbitrary modifiers', () => { `) }) }) + +it('should not insert spaces around operators inside `env()`', () => { + let config = { + content: [{ raw: html`
` }], + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + .grid-cols-\[calc\(env\(safe-area-inset-bottom\)\+1px\)\] { + grid-template-columns: calc(env(safe-area-inset-bottom) + 1px); + } + `) + }) +}) + +it('should not insert spaces around `-` in arbitrary values that use `max-content`', () => { + let config = { + content: [{ raw: html`
` }], + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + .grid-cols-\[repeat\(3\,_minmax\(0\,_max-content\)\)\] { + grid-template-columns: repeat(3, minmax(0, max-content)); + } + `) + }) +}) diff --git a/tests/normalize-data-types.test.js b/tests/normalize-data-types.test.js index 166cc4828f31..1dbc91473231 100644 --- a/tests/normalize-data-types.test.js +++ b/tests/normalize-data-types.test.js @@ -68,6 +68,21 @@ let table = [ ['calc(theme(spacing.foo-2))', 'calc(theme(spacing.foo-2))'], ['calc(theme(spacing.foo-bar))', 'calc(theme(spacing.foo-bar))'], + // Prevent formatting inside `var()` functions + ['calc(var(--foo-bar-bar)*2)', 'calc(var(--foo-bar-bar) * 2)'], + + // Prevent formatting inside `env()` functions + ['calc(env(safe-area-inset-bottom)*2)', 'calc(env(safe-area-inset-bottom) * 2)'], + // Should format inside `calc()` nested in `env()` + ['env(safe-area-inset-bottom,calc(10px+20px))', 'env(safe-area-inset-bottom,calc(10px + 20px))'], + [ + 'calc(env(safe-area-inset-bottom,calc(10px+20px))+5px)', + 'calc(env(safe-area-inset-bottom,calc(10px + 20px)) + 5px)', + ], + + // Prevent formatting keywords + ['minmax(min-content,25%)', 'minmax(min-content,25%)'], + // Misc ['color(0_0_0/1.0)', 'color(0 0 0/1.0)'], ['color(0_0_0_/_1.0)', 'color(0 0 0 / 1.0)'],