From 05869d8c8688860b73df871f1b70b90a72502e7d Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Thu, 17 Nov 2022 15:23:53 +0100 Subject: [PATCH 1/3] postcss-custom-media: avoid complex generated CSS in more cases --- .../src/nodes/media-condition.ts | 2 +- plugins/postcss-custom-media/CHANGELOG.md | 4 ++ .../transform-at-media/transform-at-media.ts | 25 ++++++- .../test/basic-after-v9.css | 12 +++- .../test/basic-after-v9.expect.css | 34 ++++------ .../test/basic-after-v9.preserve.expect.css | 44 ++++++------- .../test/basic.expect.css | 38 +---------- .../test/complex.expect.css | 66 +------------------ .../postcss-custom-media/test/list.expect.css | 32 +-------- .../test/true-false.expect.css | 24 +------ rollup/presets/package-typescript.mjs | 14 ++-- 11 files changed, 81 insertions(+), 214 deletions(-) diff --git a/packages/media-query-list-parser/src/nodes/media-condition.ts b/packages/media-query-list-parser/src/nodes/media-condition.ts index 766c39eaf..187c9a70e 100644 --- a/packages/media-query-list-parser/src/nodes/media-condition.ts +++ b/packages/media-query-list-parser/src/nodes/media-condition.ts @@ -9,7 +9,7 @@ export class MediaCondition { media: MediaNot | MediaInParens | MediaConditionListWithAnd | MediaConditionListWithOr; - constructor(media: MediaNot | MediaInParens |MediaConditionListWithAnd | MediaConditionListWithOr) { + constructor(media: MediaNot | MediaInParens | MediaConditionListWithAnd | MediaConditionListWithOr) { this.media = media; } diff --git a/plugins/postcss-custom-media/CHANGELOG.md b/plugins/postcss-custom-media/CHANGELOG.md index a16d2d9c4..1c1582760 100644 --- a/plugins/postcss-custom-media/CHANGELOG.md +++ b/plugins/postcss-custom-media/CHANGELOG.md @@ -1,5 +1,9 @@ # Changes to PostCSS Custom Media +### Unreleased + +- Fixed: avoid complex generated CSS when `@custom-media` contains only a single simple media feature. + ### 9.0.0 (November 14, 2022) - Updated: Support for Node v14+ (major). diff --git a/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts b/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts index 65bea992a..dec3a00b5 100644 --- a/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts +++ b/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts @@ -1,5 +1,5 @@ import { alwaysTrue, neverTrue } from './always-true-or-false'; -import { isGeneralEnclosed, isMediaAnd, isMediaConditionList, isMediaFeature, isMediaFeatureBoolean, isMediaNot, isMediaOr, isMediaQueryInvalid, isMediaQueryWithType, MediaQuery, newMediaFeaturePlain, parse } from '@csstools/media-query-list-parser'; +import { isGeneralEnclosed, isMediaAnd, isMediaConditionList, isMediaFeature, isMediaFeatureBoolean, isMediaNot, isMediaOr, isMediaQueryInvalid, isMediaQueryWithType, MediaFeature, MediaQuery, newMediaFeaturePlain, parse } from '@csstools/media-query-list-parser'; export function transformAtMediaListTokens(params: string, replacements: Map, falsy: Array }>): Array<{ replaceWith: string, encapsulateWith?: string }> { const mediaQueries = parse(params, { @@ -104,6 +104,29 @@ export function transformComplexMediaQuery(mediaQuery: MediaQuery, replacements: const replacement = replacements.get(name); if (replacement) { + + if (replacement.truthy.length === 1 && mediaQueryIsSimple(replacement.truthy[0])) { + let mediaFeature: MediaFeature | null = null; + const replacementMediaQuery = replacement.truthy[0]; + replacementMediaQuery.walk((replacementEntry) => { + if (isMediaFeature(replacementEntry.node)) { + mediaFeature = replacementEntry.node; + return false; + } + }); + + if (mediaFeature && mediaFeature.feature) { + parent.feature = mediaFeature.feature; + candidate = [ + { + replaceWith: mediaQuery.toString(), + }, + ]; + + return false; + } + } + const replaceWithTrue = newMediaFeaturePlain( alwaysTrue[0][4].value as string, alwaysTrue[2], diff --git a/plugins/postcss-custom-media/test/basic-after-v9.css b/plugins/postcss-custom-media/test/basic-after-v9.css index 01fb549e9..cd54fd265 100644 --- a/plugins/postcss-custom-media/test/basic-after-v9.css +++ b/plugins/postcss-custom-media/test/basic-after-v9.css @@ -13,6 +13,12 @@ } } +@media (((--simple-feature-test))) { + .a { + order: 1.2; + } +} + /* Also a type condition */ @media screen and (--simple-feature-test) { .a { @@ -31,7 +37,7 @@ @custom-media --modern (color), (hover); @media (--modern) and (width > 1024px) { - .a { - color: green; - } + .a { + color: green; + } } diff --git a/plugins/postcss-custom-media/test/basic-after-v9.expect.css b/plugins/postcss-custom-media/test/basic-after-v9.expect.css index 6d01623fe..42fe24303 100644 --- a/plugins/postcss-custom-media/test/basic-after-v9.expect.css +++ b/plugins/postcss-custom-media/test/basic-after-v9.expect.css @@ -11,54 +11,42 @@ } } -/* Also a type condition */ @media (min-width: 300px) { -@media screen and (max-color:2147477350) { .a { - order: 2; + order: 1.2; } } -} -@media not all and (min-width: 300px) { -@media screen and (color:2147477350) { + +/* Also a type condition */ +@media screen and (min-width: 300px) { .a { order: 2; } } -} /* Negation */ -@media (min-width: 300px) { -@media not (max-color:2147477350) { +@media not (min-width: 300px) { .a { order: 3; } } -} -@media not all and (min-width: 300px) { -@media not (color:2147477350) { - .a { - order: 3; - } -} -} /* LightningCSS example */ @media (color),(hover) { @media (max-color:2147477350) and (width > 1024px) { - .a { - color: green; - } + .a { + color: green; + } } } @media not all and (color),not all and (hover) { @media (color:2147477350) and (width > 1024px) { - .a { - color: green; - } + .a { + color: green; + } } } diff --git a/plugins/postcss-custom-media/test/basic-after-v9.preserve.expect.css b/plugins/postcss-custom-media/test/basic-after-v9.preserve.expect.css index 5fa31e9fd..1e8981ca6 100644 --- a/plugins/postcss-custom-media/test/basic-after-v9.preserve.expect.css +++ b/plugins/postcss-custom-media/test/basic-after-v9.preserve.expect.css @@ -24,21 +24,24 @@ } } -/* Also a type condition */ @media (min-width: 300px) { -@media screen and (max-color:2147477350) { .a { - order: 2; + order: 1.2; } } + +@media (((--simple-feature-test))) { + .a { + order: 1.2; + } } -@media not all and (min-width: 300px) { -@media screen and (color:2147477350) { + +/* Also a type condition */ +@media screen and (min-width: 300px) { .a { order: 2; } } -} @media screen and (--simple-feature-test) { .a { order: 2; @@ -46,20 +49,11 @@ } /* Negation */ -@media (min-width: 300px) { -@media not (max-color:2147477350) { +@media not (min-width: 300px) { .a { order: 3; } } -} -@media not all and (min-width: 300px) { -@media not (color:2147477350) { - .a { - order: 3; - } -} -} @media not (--simple-feature-test) { .a { order: 3; @@ -72,23 +66,23 @@ @media (color),(hover) { @media (max-color:2147477350) and (width > 1024px) { - .a { - color: green; - } + .a { + color: green; + } } } @media not all and (color),not all and (hover) { @media (color:2147477350) and (width > 1024px) { - .a { - color: green; - } + .a { + color: green; + } } } @media (--modern) and (width > 1024px) { - .a { - color: green; - } + .a { + color: green; + } } diff --git a/plugins/postcss-custom-media/test/basic.expect.css b/plugins/postcss-custom-media/test/basic.expect.css index 97d82e390..572710522 100644 --- a/plugins/postcss-custom-media/test/basic.expect.css +++ b/plugins/postcss-custom-media/test/basic.expect.css @@ -118,47 +118,11 @@ } } -@media (min-width: 320px) { - -@media (max-width: 640px) { - -@media (max-color:2147477350) and (max-color:2147477350) { - body { - order: 10; - } -} -} - -@media not all and (max-width: 640px) { - -@media (max-color:2147477350) and (color:2147477350) { - body { - order: 10; - } -} -} -} - -@media not all and (min-width: 320px) { - -@media (max-width: 640px) { - -@media (color:2147477350) and (max-color:2147477350) { - body { - order: 10; - } -} -} - -@media not all and (max-width: 640px) { - -@media (color:2147477350) and (color:2147477350) { +@media (min-width: 320px) and (max-width: 640px) { body { order: 10; } } -} -} @media (min-width: 320px) and (max-width: 640px) { body { diff --git a/plugins/postcss-custom-media/test/complex.expect.css b/plugins/postcss-custom-media/test/complex.expect.css index 792e80338..89246f1d3 100644 --- a/plugins/postcss-custom-media/test/complex.expect.css +++ b/plugins/postcss-custom-media/test/complex.expect.css @@ -58,85 +58,25 @@ @media only screen { -@media (width >= 570px) { - -@media (max-color:2147477350) and (max-color:2147477350) { - body { - background-color: green; - } -} -} - -@media not all and (width >= 570px) { - -@media (max-color:2147477350) and (color:2147477350) { +@media (max-color:2147477350) and (width >= 570px) { body { background-color: green; } } } -} @media not screen { -@media (width >= 570px) { - -@media (color:2147477350) and (max-color:2147477350) { - body { - background-color: green; - } -} -} - -@media not all and (width >= 570px) { - -@media (color:2147477350) and (color:2147477350) { - body { - background-color: green; - } -} -} -} - -@media (width >= 570px) { - -@media (width < 1000px) { - -@media (max-color:2147477350) and (max-color:2147477350) { - body { - background-color: green; - } -} -} - -@media not all and (width < 1000px) { - -@media (max-color:2147477350) and (color:2147477350) { - body { - background-color: green; - } -} -} -} - -@media not all and (width >= 570px) { - -@media (width < 1000px) { - -@media (color:2147477350) and (max-color:2147477350) { +@media (color:2147477350) and (width >= 570px) { body { background-color: green; } } } -@media not all and (width < 1000px) { - -@media (color:2147477350) and (color:2147477350) { +@media (width >= 570px) and (width < 1000px) { body { background-color: green; } } -} -} /* #endregion https://github.com/csstools/postcss-custom-media/issues/51 */ diff --git a/plugins/postcss-custom-media/test/list.expect.css b/plugins/postcss-custom-media/test/list.expect.css index 3bf1138d3..a4f7ea7a2 100644 --- a/plugins/postcss-custom-media/test/list.expect.css +++ b/plugins/postcss-custom-media/test/list.expect.css @@ -44,38 +44,8 @@ } } -@media (min-width: 201px) { - -@media screen and (max-color:2147477350) { +@media screen and (min-width: 201px), not (min-width: 202px) { .b { order: 4; } } -} - -@media not all and (min-width: 201px) { - -@media screen and (color:2147477350) { - .b { - order: 4; - } -} -} - -@media (min-width: 202px) { - -@media not (max-color:2147477350) { - .b { - order: 4; - } -} -} - -@media not all and (min-width: 202px) { - -@media not (color:2147477350) { - .b { - order: 4; - } -} -} diff --git a/plugins/postcss-custom-media/test/true-false.expect.css b/plugins/postcss-custom-media/test/true-false.expect.css index 789755def..520b1b1f5 100644 --- a/plugins/postcss-custom-media/test/true-false.expect.css +++ b/plugins/postcss-custom-media/test/true-false.expect.css @@ -1,36 +1,14 @@ -@media (max-color:2147477350) {@media screen and (max-color:2147477350) { +@media screen and (max-color:2147477350) { .true { order: 1; } } -} - -@media not all and (max-color:2147477350) { - -@media screen and (color:2147477350) { - .true { - order: 1; - } -} -} - -@media (color:2147477350) { - -@media screen and (max-color:2147477350) { - .false { - order: 2; - } -} -} - -@media not all and (color:2147477350) { @media screen and (color:2147477350) { .false { order: 2; } } -} @media (max-color:2147477350) { .true { diff --git a/rollup/presets/package-typescript.mjs b/rollup/presets/package-typescript.mjs index 8477a020c..0c71ae90f 100644 --- a/rollup/presets/package-typescript.mjs +++ b/rollup/presets/package-typescript.mjs @@ -21,13 +21,13 @@ export function packageTypescript() { extensions: ['.js', '.ts'], presets: packageBabelPreset, }), - terser({ - compress: { - reduce_funcs: false, // https://github.com/terser/terser/issues/1305 - }, - keep_classnames: true, - keep_fnames: true, - }), + // terser({ + // compress: { + // reduce_funcs: false, // https://github.com/terser/terser/issues/1305 + // }, + // keep_classnames: true, + // keep_fnames: true, + // }), ], }, ]; From 0f46f3cc26e44d47d730925f477fdd8a40ade34e Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Thu, 17 Nov 2022 15:39:03 +0100 Subject: [PATCH 2/3] undo --- rollup/presets/package-typescript.mjs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rollup/presets/package-typescript.mjs b/rollup/presets/package-typescript.mjs index 0c71ae90f..8477a020c 100644 --- a/rollup/presets/package-typescript.mjs +++ b/rollup/presets/package-typescript.mjs @@ -21,13 +21,13 @@ export function packageTypescript() { extensions: ['.js', '.ts'], presets: packageBabelPreset, }), - // terser({ - // compress: { - // reduce_funcs: false, // https://github.com/terser/terser/issues/1305 - // }, - // keep_classnames: true, - // keep_fnames: true, - // }), + terser({ + compress: { + reduce_funcs: false, // https://github.com/terser/terser/issues/1305 + }, + keep_classnames: true, + keep_fnames: true, + }), ], }, ]; From ef81a46b58925b1d39e79437e98850c2af55bcdd Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Fri, 18 Nov 2022 19:58:54 +0100 Subject: [PATCH 3/3] fmt --- .../src/transform-at-media/transform-at-media.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts b/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts index dec3a00b5..7c9e23816 100644 --- a/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts +++ b/plugins/postcss-custom-media/src/transform-at-media/transform-at-media.ts @@ -1,5 +1,19 @@ import { alwaysTrue, neverTrue } from './always-true-or-false'; -import { isGeneralEnclosed, isMediaAnd, isMediaConditionList, isMediaFeature, isMediaFeatureBoolean, isMediaNot, isMediaOr, isMediaQueryInvalid, isMediaQueryWithType, MediaFeature, MediaQuery, newMediaFeaturePlain, parse } from '@csstools/media-query-list-parser'; +import { + MediaFeature, + MediaQuery, + isGeneralEnclosed, + isMediaAnd, + isMediaConditionList, + isMediaFeature, + isMediaFeatureBoolean, + isMediaNot, + isMediaOr, + isMediaQueryInvalid, + isMediaQueryWithType, + newMediaFeaturePlain, + parse, +} from '@csstools/media-query-list-parser'; export function transformAtMediaListTokens(params: string, replacements: Map, falsy: Array }>): Array<{ replaceWith: string, encapsulateWith?: string }> { const mediaQueries = parse(params, {