From 4b12f838fea40a4ced437352db2d6627a9429723 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 25 Oct 2023 15:20:49 +0200 Subject: [PATCH] Fix incorrect spaces around `-` in `calc()` expression (#12283) * sync package-lock.json * prevent formatting inside `env()` when formatting `calc` function * prevent formatting keywords in `calc` * add dedicated normalization tests * `calc()` in `env()` should be formatted * update changelog --- CHANGELOG.md | 4 +++- src/util/dataTypes.js | 30 ++++++++++++++++++++++++++++++ tests/arbitrary-values.test.js | 28 ++++++++++++++++++++++++++++ tests/normalize-data-types.test.js | 15 +++++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02f2b973b572..40ecf4c97283 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Fixed + +- Fix incorrect spaces around `-` in `calc()` expression ([#12283](https://github.com/tailwindlabs/tailwindcss/pull/12283)) ## [3.3.4] - 2023-10-24 diff --git a/src/util/dataTypes.js b/src/util/dataTypes.js index b427a1631ae9..005c37ad1501 100644 --- a/src/util/dataTypes.js +++ b/src/util/dataTypes.js @@ -84,6 +84,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 = '' @@ -126,6 +149,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 774b4db406b9..ff7abcd84fdc 100644 --- a/tests/arbitrary-values.test.js +++ b/tests/arbitrary-values.test.js @@ -653,3 +653,31 @@ crosscheck(({ stable, oxide }) => { }) }) }) + +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 d3b52cfe726e..f11e38b790e3 100644 --- a/tests/normalize-data-types.test.js +++ b/tests/normalize-data-types.test.js @@ -69,6 +69,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)'],