From 1f965da75876dcf4ac4f34d011b162f905e448e1 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Fri, 8 Jul 2022 18:18:21 +0200 Subject: [PATCH 01/11] remove-plugins-with-side-effects-and-remove-side-effects-from-plugins--frank-asian-elephant-3b36cfb366 --- cli/csstools-cli/package.json | 1 - cli/csstools-cli/src/cli.ts | 4 - .../src/plugins/postcss-env-function.ts | 18 - package-lock.json | 4 - plugin-packs/postcss-preset-env/.tape.mjs | 123 ------ plugin-packs/postcss-preset-env/package.json | 1 - .../scripts/plugins-data.json | 5 - plugin-packs/postcss-preset-env/src/index.js | 5 - .../src/lib/list-features.mjs | 5 - .../src/lib/shared-options.mjs | 14 +- .../src/plugins/plugins-by-id.mjs | 2 - .../src/plugins/plugins-data.mjs | 5 - .../src/side-effects/plugins.mjs | 92 ----- .../src/side-effects/write-to-exports.mjs | 196 --------- .../test/basic.ch88-ff78-saf10.expect.css | 26 +- .../test/basic.ch88-ff78.expect.css | 8 +- .../basic.ch88-ff78.no-is-pseudo.expect.css | 8 +- .../test/basic.nesting.false.expect.css | 26 +- .../test/basic.op_mini.expect.css | 26 +- .../test/basic.preserve.true.expect.css | 54 ++- .../test/basic.stage0-ff49.expect.css | 26 +- .../test/basic.stage0-ff66.expect.css | 26 +- .../test/basic.stage0.expect.css | 26 +- .../test/generated-custom-exports.css | 9 - .../test/generated-custom-exports.js | 13 - .../test/generated-custom-exports.json | 13 - .../test/generated-custom-exports.mjs | 13 - .../test/import.ch87.array.expect.css | 15 - .../test/import.ch87.expect.css | 15 - .../import.ch87.incorrect-options.expect.css | 14 - .../postcss-preset-env/test/import.css | 16 - .../postcss-preset-env/test/import.expect.css | 15 - .../test/layers-basic.expect.css | 44 +- .../layers-basic.preserve.true.expect.css | 50 ++- plugins/postcss-custom-media/.tape.cjs | 255 ------------ plugins/postcss-custom-media/.tape.mjs | 26 ++ plugins/postcss-custom-media/package.json | 4 +- .../src/get-custom-media-from-imports.js | 110 ----- plugins/postcss-custom-media/src/index.js | 19 +- .../src/write-custom-media-to-exports.js | 129 ------ .../test/basic.import.expect.css | 0 .../test/export-media.css | 8 - .../postcss-custom-media/test/export-media.js | 12 - .../test/export-media.json | 12 - .../test/export-media.mjs | 10 - .../postcss-custom-media/test/import-css.css | 0 .../test/import-media.css | 2 - .../postcss-custom-media/test/import-media.js | 6 - .../test/import-media.json | 6 - plugins/postcss-custom-media/test/import.css | 29 -- .../test/import.empty.expect.css | 29 -- .../test/import.expect.css | 29 -- .../test/import.plugin.expect.css | 29 -- plugins/postcss-custom-properties/.tape.cjs | 29 -- plugins/postcss-custom-properties/.tape.mjs | 381 ------------------ .../postcss-custom-properties/package.json | 2 +- .../postcss-custom-properties/src/index.ts | 92 +---- .../lib/get-custom-properties-from-imports.ts | 158 -------- .../lib/get-custom-properties-from-root.ts | 64 +-- .../src/lib/options.ts | 14 - .../lib/write-custom-properties-to-exports.ts | 159 -------- .../postcss-custom-properties/test/basic.css | 4 + .../test/basic.expect.css | 5 + .../test/basic.import-is-empty.expect.css | 161 -------- .../test/basic.import-override.expect.css | 111 ----- .../basic.import-override.inverse.expect.css | 111 ----- .../test/basic.import.expect.css | 162 -------- .../test/basic.preserve.expect.css | 30 ++ .../test/export-properties.css | 20 - .../test/export-properties.js | 22 - .../test/export-properties.json | 22 - .../test/export-properties.mjs | 20 - .../test/export-properties.scss | 18 - .../test/import-properties-2.cjs | 6 - .../test/import-properties-2.css | 4 - .../test/import-properties-2.js | 6 - .../test/import-properties-2.mjs | 6 - .../test/import-properties.cjs | 6 - .../test/import-properties.css | 4 - .../test/import-properties.js | 6 - .../test/import-properties.json | 8 - .../test/import-properties.mjs | 6 - .../test/import-properties.pcss | 4 - plugins/postcss-custom-selectors/.tape.cjs | 244 ----------- plugins/postcss-custom-selectors/.tape.mjs | 217 ---------- plugins/postcss-custom-selectors/package.json | 5 +- ...-root.js => custom-selectors-from-root.ts} | 15 +- .../postcss-custom-selectors/src/export-to.js | 129 ------ .../src/import-from.js | 121 ------ plugins/postcss-custom-selectors/src/index.js | 45 --- plugins/postcss-custom-selectors/src/index.ts | 37 ++ .../src/transform-rule.js | 19 - .../src/transform-rule.ts | 38 ++ ...transform-selectors-by-custom-selectors.js | 99 ----- .../test/basic-import.css | 3 - .../test/basic-import.empty.expect.css | 3 - .../test/basic-import.expect.css | 3 - .../test/basic.expect.css | 103 +++-- .../test/basic.export.expect.css | 85 ---- .../test/basic.preserve.expect.css | 58 +-- .../test/complex.expect.css | 12 +- .../postcss-custom-selectors/test/empty.css | 0 .../test/examples/example.expect.css | 4 +- .../test/examples/example.preserve.expect.css | 2 +- .../test/export-selectors.css | 22 - .../test/export-selectors.js | 20 - .../test/export-selectors.json | 20 - .../test/export-selectors.mjs | 18 - .../test/import-selectors.css | 1 - .../test/import-selectors.js | 5 - .../test/import-selectors.json | 5 - .../test/safety.expect.css | 8 +- .../postcss-custom-selectors/tsconfig.json | 10 + 113 files changed, 643 insertions(+), 3982 deletions(-) delete mode 100644 cli/csstools-cli/src/plugins/postcss-env-function.ts delete mode 100644 plugin-packs/postcss-preset-env/src/side-effects/plugins.mjs delete mode 100644 plugin-packs/postcss-preset-env/src/side-effects/write-to-exports.mjs delete mode 100644 plugin-packs/postcss-preset-env/test/generated-custom-exports.css delete mode 100644 plugin-packs/postcss-preset-env/test/generated-custom-exports.js delete mode 100644 plugin-packs/postcss-preset-env/test/generated-custom-exports.json delete mode 100644 plugin-packs/postcss-preset-env/test/generated-custom-exports.mjs delete mode 100644 plugin-packs/postcss-preset-env/test/import.ch87.array.expect.css delete mode 100644 plugin-packs/postcss-preset-env/test/import.ch87.expect.css delete mode 100644 plugin-packs/postcss-preset-env/test/import.ch87.incorrect-options.expect.css delete mode 100644 plugin-packs/postcss-preset-env/test/import.css delete mode 100644 plugin-packs/postcss-preset-env/test/import.expect.css delete mode 100644 plugins/postcss-custom-media/.tape.cjs create mode 100644 plugins/postcss-custom-media/.tape.mjs delete mode 100644 plugins/postcss-custom-media/src/get-custom-media-from-imports.js delete mode 100644 plugins/postcss-custom-media/src/write-custom-media-to-exports.js delete mode 100644 plugins/postcss-custom-media/test/basic.import.expect.css delete mode 100644 plugins/postcss-custom-media/test/export-media.css delete mode 100644 plugins/postcss-custom-media/test/export-media.js delete mode 100644 plugins/postcss-custom-media/test/export-media.json delete mode 100644 plugins/postcss-custom-media/test/export-media.mjs delete mode 100644 plugins/postcss-custom-media/test/import-css.css delete mode 100644 plugins/postcss-custom-media/test/import-media.css delete mode 100644 plugins/postcss-custom-media/test/import-media.js delete mode 100644 plugins/postcss-custom-media/test/import-media.json delete mode 100644 plugins/postcss-custom-media/test/import.css delete mode 100644 plugins/postcss-custom-media/test/import.empty.expect.css delete mode 100644 plugins/postcss-custom-media/test/import.expect.css delete mode 100644 plugins/postcss-custom-media/test/import.plugin.expect.css delete mode 100644 plugins/postcss-custom-properties/.tape.cjs delete mode 100644 plugins/postcss-custom-properties/src/lib/get-custom-properties-from-imports.ts delete mode 100644 plugins/postcss-custom-properties/src/lib/options.ts delete mode 100644 plugins/postcss-custom-properties/src/lib/write-custom-properties-to-exports.ts delete mode 100644 plugins/postcss-custom-properties/test/basic.import-is-empty.expect.css delete mode 100644 plugins/postcss-custom-properties/test/basic.import-override.expect.css delete mode 100644 plugins/postcss-custom-properties/test/basic.import-override.inverse.expect.css delete mode 100644 plugins/postcss-custom-properties/test/basic.import.expect.css delete mode 100644 plugins/postcss-custom-properties/test/export-properties.css delete mode 100644 plugins/postcss-custom-properties/test/export-properties.js delete mode 100644 plugins/postcss-custom-properties/test/export-properties.json delete mode 100644 plugins/postcss-custom-properties/test/export-properties.mjs delete mode 100644 plugins/postcss-custom-properties/test/export-properties.scss delete mode 100644 plugins/postcss-custom-properties/test/import-properties-2.cjs delete mode 100644 plugins/postcss-custom-properties/test/import-properties-2.css delete mode 100644 plugins/postcss-custom-properties/test/import-properties-2.js delete mode 100644 plugins/postcss-custom-properties/test/import-properties-2.mjs delete mode 100644 plugins/postcss-custom-properties/test/import-properties.cjs delete mode 100644 plugins/postcss-custom-properties/test/import-properties.css delete mode 100644 plugins/postcss-custom-properties/test/import-properties.js delete mode 100644 plugins/postcss-custom-properties/test/import-properties.json delete mode 100644 plugins/postcss-custom-properties/test/import-properties.mjs delete mode 100644 plugins/postcss-custom-properties/test/import-properties.pcss delete mode 100644 plugins/postcss-custom-selectors/.tape.cjs rename plugins/postcss-custom-selectors/src/{custom-selectors-from-root.js => custom-selectors-from-root.ts} (69%) delete mode 100644 plugins/postcss-custom-selectors/src/export-to.js delete mode 100644 plugins/postcss-custom-selectors/src/import-from.js delete mode 100644 plugins/postcss-custom-selectors/src/index.js create mode 100644 plugins/postcss-custom-selectors/src/index.ts delete mode 100644 plugins/postcss-custom-selectors/src/transform-rule.js create mode 100644 plugins/postcss-custom-selectors/src/transform-rule.ts delete mode 100644 plugins/postcss-custom-selectors/src/transform-selectors-by-custom-selectors.js delete mode 100644 plugins/postcss-custom-selectors/test/basic-import.css delete mode 100644 plugins/postcss-custom-selectors/test/basic-import.empty.expect.css delete mode 100644 plugins/postcss-custom-selectors/test/basic-import.expect.css delete mode 100644 plugins/postcss-custom-selectors/test/basic.export.expect.css delete mode 100644 plugins/postcss-custom-selectors/test/empty.css delete mode 100644 plugins/postcss-custom-selectors/test/export-selectors.css delete mode 100644 plugins/postcss-custom-selectors/test/export-selectors.js delete mode 100644 plugins/postcss-custom-selectors/test/export-selectors.json delete mode 100644 plugins/postcss-custom-selectors/test/export-selectors.mjs delete mode 100644 plugins/postcss-custom-selectors/test/import-selectors.css delete mode 100644 plugins/postcss-custom-selectors/test/import-selectors.js delete mode 100644 plugins/postcss-custom-selectors/test/import-selectors.json create mode 100644 plugins/postcss-custom-selectors/tsconfig.json diff --git a/cli/csstools-cli/package.json b/cli/csstools-cli/package.json index 7c9884838c..fc0ed313b8 100644 --- a/cli/csstools-cli/package.json +++ b/cli/csstools-cli/package.json @@ -55,7 +55,6 @@ "postcss-custom-selectors": "^6.0.2", "postcss-dir-pseudo-class": "^6.0.4", "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-gap-properties": "^3.0.3", diff --git a/cli/csstools-cli/src/cli.ts b/cli/csstools-cli/src/cli.ts index 0f0b2e0ed9..0a485dd8ea 100644 --- a/cli/csstools-cli/src/cli.ts +++ b/cli/csstools-cli/src/cli.ts @@ -12,7 +12,6 @@ import postcssCustomProperties from './plugins/postcss-custom-properties'; import postcssCustomSelectors from './plugins/postcss-custom-selectors'; import postcssDirPseudoClass from './plugins/postcss-dir-pseudo-class'; import postcssDoublePositionGradients from './plugins/postcss-double-position-gradients'; -import postcssEnvFunction from './plugins/postcss-env-function'; import postcssFocusVisible from './plugins/postcss-focus-visible'; import postcssFocusWithin from './plugins/postcss-focus-within'; import postcssFontFormatKeywords from './plugins/postcss-font-format-keywords'; @@ -80,9 +79,6 @@ function main() { case 'postcss-double-position-gradients': postcssDoublePositionGradients(); return; - case 'postcss-env-function': - postcssEnvFunction(); - return; case 'postcss-focus-visible': postcssFocusVisible(); return; diff --git a/cli/csstools-cli/src/plugins/postcss-env-function.ts b/cli/csstools-cli/src/plugins/postcss-env-function.ts deleted file mode 100644 index 0cb86326c1..0000000000 --- a/cli/csstools-cli/src/plugins/postcss-env-function.ts +++ /dev/null @@ -1,18 +0,0 @@ -import plugin from 'postcss-env-function'; -import { cli, helpTextLogger } from '@csstools/base-cli'; - -export default function postcssEnvFunction() { - cli( - plugin, - ['importFrom'], - helpTextLogger( - '@csstools/cli postcss-env-function', - 'PostCSS Environment Variables', - 'Lets you use `env()` variables in CSS, following the CSS Environment Variables specification.', - { - importFrom: ['import-variables.js'], - }, - ), - false, - ); -} diff --git a/package-lock.json b/package-lock.json index bb0f639391..4ccefcc879 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,6 @@ "postcss-custom-selectors": "^6.0.2", "postcss-dir-pseudo-class": "^6.0.4", "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-gap-properties": "^3.0.3", @@ -6909,7 +6908,6 @@ "postcss-custom-selectors": "^6.0.3", "postcss-dir-pseudo-class": "^6.0.4", "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-font-variant": "^5.0.0", @@ -8847,7 +8845,6 @@ "postcss-custom-selectors": "^6.0.2", "postcss-dir-pseudo-class": "^6.0.4", "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-gap-properties": "^3.0.3", @@ -11683,7 +11680,6 @@ "postcss-custom-selectors": "^6.0.3", "postcss-dir-pseudo-class": "^6.0.4", "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-font-variant": "^5.0.0", diff --git a/plugin-packs/postcss-preset-env/.tape.mjs b/plugin-packs/postcss-preset-env/.tape.mjs index 2794cefa80..c89f756200 100644 --- a/plugin-packs/postcss-preset-env/.tape.mjs +++ b/plugin-packs/postcss-preset-env/.tape.mjs @@ -1,6 +1,5 @@ import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; import plugin from 'postcss-preset-env'; -import fs from 'fs'; const orderDetectionPlugin = (prop, changeWhenMatches) => { return { @@ -383,128 +382,6 @@ postcssTape(plugin)({ } } }, - 'import': { - message: 'supports { importFrom: { customMedia, customProperties, customSelectors, environmentVariables } } usage', - warnings: 2, - options: { - importFrom: { - customMedia: { - '--narrow-window': '(max-width: env(--sm))' - }, - customProperties: { - '--order': '1' - }, - customSelectors: { - ':--heading': 'h1, h2, h3, h4, h5, h6' - }, - environmentVariables: { - '--sm': '40rem' - } - }, - stage: 0 - } - }, - 'import:ch87': { - message: 'supports { browsers: "chrome >= 87", importFrom: { customMedia, customProperties, customSelectors, environmentVariables } } usage', - warnings: 2, - options: { - browsers: 'chrome >= 87', - importFrom: { - customMedia: { - '--narrow-window': '(max-width: env(--sm))' - }, - customProperties: { - '--order': '1' - }, - customSelectors: { - ':--heading': 'h1, h2, h3, h4, h5, h6' - }, - environmentVariables: { - '--sm': '40rem' - } - }, - stage: 0 - } - }, - 'import:ch87:array': { - message: 'supports { browsers: "chrome >= 87", importFrom: [{ customMedia, customProperties, customSelectors, environmentVariables }] } usage', - warnings: 2, - options: { - browsers: 'chrome >= 87', - importFrom: [{ - customMedia: { - '--narrow-window': '(max-width: env(--sm))' - }, - customProperties: { - '--order': '1' - }, - customSelectors: { - ':--heading': 'h1, h2, h3, h4, h5, h6' - }, - environmentVariables: { - '--sm': '40rem' - } - }], - stage: 0 - } - }, - 'import:ch87:incorrect-options': { - message: 'supports { browsers: "chrome >= 87", importFrom: false } usage', - options: { - browsers: 'chrome >= 87', - importFrom: false, - stage: 0 - } - }, - 'basic:export': { - message: 'supports { stage: 0 } usage', - warnings: 1, - options: { - stage: 0, - exportTo: [ - 'test/generated-custom-exports.css', - 'test/generated-custom-exports.js', - 'test/generated-custom-exports.json', - 'test/generated-custom-exports.mjs' - ] - }, - expect: 'basic.stage0.expect.css', - result: 'basic.stage0.result.css', - before() { - try { - global.__exportTo = { - css: fs.readFileSync('test/generated-custom-exports.css', 'utf8'), - js: fs.readFileSync('test/generated-custom-exports.js', 'utf8'), - json: fs.readFileSync('test/generated-custom-exports.json', 'utf8'), - mjs: fs.readFileSync('test/generated-custom-exports.mjs', 'utf8') - }; - - fs.rmSync('test/generated-custom-exports.css'); - fs.rmSync('test/generated-custom-exports.js'); - fs.rmSync('test/generated-custom-exports.json'); - fs.rmSync('test/generated-custom-exports.mjs'); - } catch (_) { - // ignore errors here. - // If the files are removed manually test run will regenerate these. - // The after step will still fail. - // The real test is in the after step. - } - }, - after() { - global.__exportAs = { - css: fs.readFileSync('test/generated-custom-exports.css', 'utf8'), - js: fs.readFileSync('test/generated-custom-exports.js', 'utf8'), - json: fs.readFileSync('test/generated-custom-exports.json', 'utf8'), - mjs: fs.readFileSync('test/generated-custom-exports.mjs', 'utf8') - }; - - Object.keys(global.__exportTo).forEach(key => { - if (global.__exportTo[key] !== global.__exportAs[key]) { - throw new Error(`The original ${key} file did not match the freshly exported copy`); - } - }); - } - }, 'progressive-custom-properties': { message: 'supports progressive custom properties plugin', options: { diff --git a/plugin-packs/postcss-preset-env/package.json b/plugin-packs/postcss-preset-env/package.json index ee4ef64095..2ed75ee1d6 100644 --- a/plugin-packs/postcss-preset-env/package.json +++ b/plugin-packs/postcss-preset-env/package.json @@ -55,7 +55,6 @@ "postcss-custom-selectors": "^6.0.3", "postcss-dir-pseudo-class": "^6.0.4", "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", "postcss-focus-visible": "^6.0.4", "postcss-focus-within": "^5.0.4", "postcss-font-variant": "^5.0.0", diff --git a/plugin-packs/postcss-preset-env/scripts/plugins-data.json b/plugin-packs/postcss-preset-env/scripts/plugins-data.json index f306912eea..a3bd1ce051 100644 --- a/plugin-packs/postcss-preset-env/scripts/plugins-data.json +++ b/plugin-packs/postcss-preset-env/scripts/plugins-data.json @@ -69,11 +69,6 @@ "id": "double-position-gradients", "importName": "postcssDoublePositionGradients" }, - { - "packageName": "postcss-env-function", - "id": "environment-variables", - "importName": "postcssEnvFunction" - }, { "packageName": "postcss-focus-visible", "id": "focus-visible-pseudo-class", diff --git a/plugin-packs/postcss-preset-env/src/index.js b/plugin-packs/postcss-preset-env/src/index.js index c68ecd325d..80700b0b60 100644 --- a/plugin-packs/postcss-preset-env/src/index.js +++ b/plugin-packs/postcss-preset-env/src/index.js @@ -2,7 +2,6 @@ import autoprefixer from 'autoprefixer'; import cssdb from 'cssdb'; import logFeaturesList from './log/features-list.mjs'; import postcssProgressiveCustomProperties from '@csstools/postcss-progressive-custom-properties'; -import writeToExports from './side-effects/write-to-exports.mjs'; import { initializeSharedOptions } from './lib/shared-options.mjs'; import { listFeatures } from './lib/list-features.mjs'; import { newLogger } from './log/helper.mjs'; @@ -47,10 +46,6 @@ const plugin = (opts) => { // Always reset the logger, if when debug is false logger.resetLogger(); - - if (options.exportTo) { - writeToExports(sharedOptions.exportTo, opts.exportTo); - } }, }; }; diff --git a/plugin-packs/postcss-preset-env/src/lib/list-features.mjs b/plugin-packs/postcss-preset-env/src/lib/list-features.mjs index 813fe62971..b992e6b69e 100644 --- a/plugin-packs/postcss-preset-env/src/lib/list-features.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/list-features.mjs @@ -1,5 +1,4 @@ import browserslist from 'browserslist'; -import { pluginHasSideEffects } from '../side-effects/plugins.mjs'; import { featuresWithClientSide } from '../client-side-polyfills/plugins.mjs'; import { stageFromOptions } from './stage.mjs'; import { prepareFeaturesList } from './prepare-features-list.mjs'; @@ -109,10 +108,6 @@ export function listFeatures(cssdbList, options, sharedOptions, logger) { return features[feature.id]; } - if (pluginHasSideEffects(feature)) { - return true; - } - const unsupportedBrowsers = browserslist(feature.browsers, { ignoreUnknownVersions: true, }); diff --git a/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs b/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs index 44bcd91117..617e318ad6 100644 --- a/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs @@ -1,20 +1,8 @@ export function initializeSharedOptions(opts) { - if ('importFrom' in opts || 'exportTo' in opts || 'preserve' in opts) { + if ('preserve' in opts) { const sharedOptions = {}; - if ('importFrom' in opts) { - sharedOptions.importFrom = opts.importFrom; - } - - if ('exportTo' in opts) { - sharedOptions.exportTo = { - customMedia: {}, - customProperties: {}, - customSelectors: {}, - }; - } - if ('preserve' in opts) { sharedOptions.preserve = opts.preserve; } diff --git a/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs b/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs index 24894fe892..33816c6bbf 100644 --- a/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs +++ b/plugin-packs/postcss-preset-env/src/plugins/plugins-by-id.mjs @@ -13,7 +13,6 @@ import postcssCustomSelectors from 'postcss-custom-selectors'; import postcssDirPseudoClass from 'postcss-dir-pseudo-class'; import postcssNormalizeDisplayValues from '@csstools/postcss-normalize-display-values'; import postcssDoublePositionGradients from 'postcss-double-position-gradients'; -import postcssEnvFunction from 'postcss-env-function'; import postcssFocusVisible from 'postcss-focus-visible'; import postcssFocusWithin from 'postcss-focus-within'; import postcssFontFormatKeywords from '@csstools/postcss-font-format-keywords'; @@ -60,7 +59,6 @@ export const pluginsById = new Map( ['dir-pseudo-class', postcssDirPseudoClass], ['display-two-values', postcssNormalizeDisplayValues], ['double-position-gradients', postcssDoublePositionGradients], - ['environment-variables', postcssEnvFunction], ['focus-visible-pseudo-class', postcssFocusVisible], ['focus-within-pseudo-class', postcssFocusWithin], ['font-format-keywords', postcssFontFormatKeywords], diff --git a/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs b/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs index e41440f15a..f0e5c0e86d 100644 --- a/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs +++ b/plugin-packs/postcss-preset-env/src/plugins/plugins-data.mjs @@ -69,11 +69,6 @@ export default [ 'id': 'double-position-gradients', 'importName': 'postcssDoublePositionGradients', }, - { - 'packageName': 'postcss-env-function', - 'id': 'environment-variables', - 'importName': 'postcssEnvFunction', - }, { 'packageName': 'postcss-focus-visible', 'id': 'focus-visible-pseudo-class', diff --git a/plugin-packs/postcss-preset-env/src/side-effects/plugins.mjs b/plugin-packs/postcss-preset-env/src/side-effects/plugins.mjs deleted file mode 100644 index e788390dc8..0000000000 --- a/plugin-packs/postcss-preset-env/src/side-effects/plugins.mjs +++ /dev/null @@ -1,92 +0,0 @@ -// Some plugins have side effects that go beyond the scope of preset-env. -// These plugins always need to run. -// IMPORTANT: this should be removed and cleaned up in a next major version. -export function pluginHasSideEffects(feature) { - if ('importFrom' in Object(feature.pluginOptions)) { - switch (feature.id) { - case 'custom-media-queries': - if (anyOptionFor(feature.pluginOptions.importFrom, 'customMedia')) { - return true; - } - break; - case 'custom-properties': - if (anyOptionFor(feature.pluginOptions.importFrom, 'customProperties')) { - return true; - } - break; - case 'environment-variables': - if (anyOptionFor(feature.pluginOptions.importFrom, 'environmentVariables')) { - return true; - } - break; - case 'custom-selectors': - if (anyOptionFor(feature.pluginOptions.importFrom, 'customSelectors')) { - return true; - } - break; - - default: - break; - } - } - - if ('exportTo' in Object(feature.pluginOptions)) { - switch (feature.id) { - case 'custom-media-queries': - if (anyOptionFor(feature.pluginOptions.exportTo, 'customMedia')) { - return true; - } - break; - case 'custom-properties': - if (anyOptionFor(feature.pluginOptions.exportTo, 'customProperties')) { - return true; - } - break; - case 'environment-variables': - if (anyOptionFor(feature.pluginOptions.exportTo, 'environmentVariables')) { - return true; - } - break; - case 'custom-selectors': - if (anyOptionFor(feature.pluginOptions.exportTo, 'customSelectors')) { - return true; - } - break; - - default: - break; - } - } - - return false; -} - -function anyOptionFor(opts, feature) { - if (!opts) { - return false; - } - - if (typeof opts === 'string') { - return true; - } - - if (Array.isArray(opts)) { - for (let i = 0; i < opts.length; i++) { - if (typeof opts[i] === 'string') { - return true; - } - - if (opts[i] && (feature in Object(opts[i]))) { - return true; - } - } - - return false; - } - - if (feature in Object(opts)) { - return true; - } - - return false; -} diff --git a/plugin-packs/postcss-preset-env/src/side-effects/write-to-exports.mjs b/plugin-packs/postcss-preset-env/src/side-effects/write-to-exports.mjs deleted file mode 100644 index 40af0165cc..0000000000 --- a/plugin-packs/postcss-preset-env/src/side-effects/write-to-exports.mjs +++ /dev/null @@ -1,196 +0,0 @@ -/* eslint max-params: ["error", 4] */ - -import fs from 'fs'; -import path from 'path'; - -/* Write Exports to CSS File -/* ========================================================================== */ - -function getCustomMediaAsCss(customMedia) { - const cssContent = Object.keys(customMedia).reduce((cssLines, name) => { - cssLines.push(`@custom-media ${name} ${customMedia[name]};`); - - return cssLines; - }, []).join('\n'); - const css = `${cssContent}\n`; - - return css; -} - -function getCustomPropertiesAsCss(customProperties) { - const cssContent = Object.keys(customProperties).reduce((cssLines, name) => { - cssLines.push(`\t${name}: ${customProperties[name]};`); - - return cssLines; - }, []).join('\n'); - const css = `:root {\n${cssContent}\n}\n`; - - return css; -} - -function getCustomSelectorsAsCss(customSelectors) { - const cssContent = Object.keys(customSelectors).reduce((cssLines, name) => { - cssLines.push(`@custom-selector ${name} ${customSelectors[name]};`); - - return cssLines; - }, []).join('\n'); - const css = `${cssContent}\n`; - - return css; -} - -async function writeExportsToCssFile(to, customMedia, customProperties, customSelectors) { - const customPropertiesAsCss = getCustomPropertiesAsCss(customProperties); - const customMediaAsCss = getCustomMediaAsCss(customMedia); - const customSelectorsAsCss = getCustomSelectorsAsCss(customSelectors); - const css = `${customMediaAsCss}\n${customSelectorsAsCss}\n${customPropertiesAsCss}`; - - await writeFile(to, css); -} - -/* Write Exports to JSON file -/* ========================================================================== */ - -async function writeExportsToJsonFile(to, customMedia, customProperties, customSelectors) { - const jsonContent = JSON.stringify({ - 'custom-media': customMedia, - 'custom-properties': customProperties, - 'custom-selectors': customSelectors, - }, null, ' '); - const json = `${jsonContent}\n`; - - await writeFile(to, json); -} - -/* Write Exports to Common JS file -/* ========================================================================== */ - -function getObjectWithKeyAsCjs(key, object) { - const jsContents = Object.keys(object).reduce((jsLines, name) => { - jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(object[name])}'`); - - return jsLines; - }, []).join(',\n'); - const cjs = `\n\t${key}: {\n${jsContents}\n\t}`; - - return cjs; -} - -async function writeExportsToCjsFile(to, customMedia, customProperties, customSelectors) { - const customMediaAsCjs = getObjectWithKeyAsCjs('customMedia', customMedia); - const customPropertiesAsCjs = getObjectWithKeyAsCjs('customProperties', customProperties); - const customSelectorsAsCjs = getObjectWithKeyAsCjs('customSelectors', customSelectors); - const cjs = `module.exports = {${customMediaAsCjs},${customPropertiesAsCjs},${customSelectorsAsCjs}\n};\n`; - - await writeFile(to, cjs); -} - -/* Write Exports to Module JS file -/* ========================================================================== */ - -function getObjectWithKeyAsMjs(key, object) { - const mjsContents = Object.keys(object).reduce((mjsLines, name) => { - mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(object[name])}'`); - - return mjsLines; - }, []).join(',\n'); - const mjs = `export const ${key} = {\n${mjsContents}\n};\n`; - - return mjs; -} - -async function writeExportsToMjsFile(to, customMedia, customProperties, customSelectors) { - const customMediaAsMjs = getObjectWithKeyAsMjs('customMedia', customMedia); - const customPropertiesAsMjs = getObjectWithKeyAsMjs('customProperties', customProperties); - const customSelectorsAsMjs = getObjectWithKeyAsMjs('customSelectors', customSelectors); - const mjs = `${customMediaAsMjs}\n${customPropertiesAsMjs}\n${customSelectorsAsMjs}`; - - await writeFile(to, mjs); -} - -/* Write Exports to Exports -/* ========================================================================== */ - -export default function writeToExports(customExports, destinations) { - return Promise.all([].concat(destinations).map(async destination => { - if (destination instanceof Function) { - await destination({ - customMedia: getObjectWithStringifiedKeys(customExports.customMedia), - customProperties: getObjectWithStringifiedKeys(customExports.customProperties), - customSelectors: getObjectWithStringifiedKeys(customExports.customSelectors), - }); - } else { - // read the destination as an object - const opts = destination === Object(destination) ? destination : { to: String(destination) }; - - // transformer for Exports into a JSON-compatible object - const toJSON = opts.toJSON || getObjectWithStringifiedKeys; - - if ('customMedia' in opts || 'customProperties' in opts || 'customSelectors' in opts) { - // write directly to an object as customProperties - opts.customMedia = toJSON(customExports.customMedia); - opts.customProperties = toJSON(customExports.customProperties); - opts.customSelectors = toJSON(customExports.customSelectors); - } else if ('custom-media' in opts || 'custom-properties' in opts || 'custom-selectors' in opts) { - // write directly to an object as custom-properties - opts['custom-media'] = toJSON(customExports.customMedia); - opts['custom-properties'] = toJSON(customExports.customProperties); - opts['custom-selectors'] = toJSON(customExports.customSelectors); - } else { - // destination pathname - const to = String(opts.to || ''); - - // type of file being written to - const type = (opts.type || path.extname(opts.to).slice(1)).toLowerCase(); - - // transformed Exports - const customMediaJSON = toJSON(customExports.customMedia); - const customPropertiesJSON = toJSON(customExports.customProperties); - const customSelectorsJSON = toJSON(customExports.customSelectors); - - if (type === 'css') { - await writeExportsToCssFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON); - } - - if (type === 'js') { - await writeExportsToCjsFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON); - } - - if (type === 'json') { - await writeExportsToJsonFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON); - } - - if (type === 'mjs') { - await writeExportsToMjsFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON); - } - } - } - })); -} - -/* Helper utilities -/* ========================================================================== */ - -function getObjectWithStringifiedKeys(object) { - return Object.keys(object).reduce((objectJSON, key) => { - objectJSON[key] = String(object[key]); - - return objectJSON; - }, {}); -} - -function writeFile(to, text) { - return new Promise((resolve, reject) => { - fs.writeFile(to, text, error => { - if (error) { - reject(error); - } else { - resolve(); - } - }); - }); -} - -function escapeForJS(string) { - return string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); -} diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css index 0ecb2c36d2..e0b521e674 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css @@ -98,7 +98,29 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -495,6 +517,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } +@custom-selector :--view-m [data-view-size=m]; + [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css index c7d13158db..236ed757b1 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css @@ -91,7 +91,9 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +.test-custom-selectors:is(h1, h2, h3, h4, h5, h6) { order:12; } @@ -476,6 +478,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } -[data-view-size=m] .view { +@custom-selector :--view-m [data-view-size=m]; + +:is([data-view-size=m]) .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css index 1424e71ece..cd6e34d4a1 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css @@ -91,7 +91,9 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +.test-custom-selectors:is(h1, h2, h3, h4, h5, h6) { order:12; } @@ -476,6 +478,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } -[data-view-size=m] .view { +@custom-selector :--view-m [data-view-size=m]; + +:is([data-view-size=m]) .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css index c27bc71342..c785524945 100644 --- a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css @@ -92,7 +92,29 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -599,6 +621,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } +@custom-selector :--view-m [data-view-size=m]; + .view { @nest :--view-m & { background: red; diff --git a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css index b1f0430fba..b07e61dc1e 100644 --- a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css @@ -98,7 +98,29 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -585,6 +607,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } +@custom-selector :--view-m [data-view-size=m]; + [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css index dd791edeaf..17ae206b88 100644 --- a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css @@ -194,7 +194,55 @@ @custom-selector :--heading h1, h2, h3, h4, h5, h6; -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +h1.test-custom-selectors { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h2.test-custom-selectors { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h3.test-custom-selectors { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h4.test-custom-selectors { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h5.test-custom-selectors { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h6.test-custom-selectors { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +.test-custom-selectors:is(h1, h2, h3, h4, h5, h6) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -1018,6 +1066,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background: red; } +:is([data-view-size=m]) .view { + background: red; +} + :--view-m .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css index 40145efe76..cf3298bf75 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css @@ -97,7 +97,29 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -497,6 +519,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } +@custom-selector :--view-m [data-view-size=m]; + [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css index 1923dd4125..17fb07a0c3 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css @@ -89,7 +89,29 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -482,6 +504,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } +@custom-selector :--view-m [data-view-size=m]; + [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css index 765bc00551..34c012f1ef 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css @@ -99,7 +99,29 @@ } } -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -606,6 +628,8 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te left: atan2(); } +@custom-selector :--view-m [data-view-size=m]; + [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/generated-custom-exports.css b/plugin-packs/postcss-preset-env/test/generated-custom-exports.css deleted file mode 100644 index 126ccd8a75..0000000000 --- a/plugin-packs/postcss-preset-env/test/generated-custom-exports.css +++ /dev/null @@ -1,9 +0,0 @@ -@custom-media --narrow-window (max-width: 30em); -@custom-media --dark-mode (prefers-color-scheme: dark); - -@custom-selector :--heading h1, h2, h3, h4, h5, h6; -@custom-selector :--view-m [data-view-size=m]; - -:root { - --order: 1; -} diff --git a/plugin-packs/postcss-preset-env/test/generated-custom-exports.js b/plugin-packs/postcss-preset-env/test/generated-custom-exports.js deleted file mode 100644 index 6237413bf5..0000000000 --- a/plugin-packs/postcss-preset-env/test/generated-custom-exports.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - customMedia: { - '--narrow-window': '(max-width: 30em)', - '--dark-mode': '(prefers-color-scheme: dark)' - }, - customProperties: { - '--order': '1' - }, - customSelectors: { - ':--heading': 'h1, h2, h3, h4, h5, h6', - ':--view-m': '[data-view-size=m]' - } -}; diff --git a/plugin-packs/postcss-preset-env/test/generated-custom-exports.json b/plugin-packs/postcss-preset-env/test/generated-custom-exports.json deleted file mode 100644 index 500c8bff68..0000000000 --- a/plugin-packs/postcss-preset-env/test/generated-custom-exports.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "custom-media": { - "--narrow-window": "(max-width: 30em)", - "--dark-mode": "(prefers-color-scheme: dark)" - }, - "custom-properties": { - "--order": "1" - }, - "custom-selectors": { - ":--heading": "h1, h2, h3, h4, h5, h6", - ":--view-m": "[data-view-size=m]" - } -} diff --git a/plugin-packs/postcss-preset-env/test/generated-custom-exports.mjs b/plugin-packs/postcss-preset-env/test/generated-custom-exports.mjs deleted file mode 100644 index 54030e2487..0000000000 --- a/plugin-packs/postcss-preset-env/test/generated-custom-exports.mjs +++ /dev/null @@ -1,13 +0,0 @@ -export const customMedia = { - '--narrow-window': '(max-width: 30em)', - '--dark-mode': '(prefers-color-scheme: dark)' -}; - -export const customProperties = { - '--order': '1' -}; - -export const customSelectors = { - ':--heading': 'h1, h2, h3, h4, h5, h6', - ':--view-m': '[data-view-size=m]' -}; diff --git a/plugin-packs/postcss-preset-env/test/import.ch87.array.expect.css b/plugin-packs/postcss-preset-env/test/import.ch87.array.expect.css deleted file mode 100644 index ded9c5eb87..0000000000 --- a/plugin-packs/postcss-preset-env/test/import.ch87.array.expect.css +++ /dev/null @@ -1,15 +0,0 @@ -.test-custom-properties { - order: 1; - order: var(--order); -} - -@media (max-width: 40rem) { - .test-custom-media-queries { - order: 2; - } -} - -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { - order: 3; - } - diff --git a/plugin-packs/postcss-preset-env/test/import.ch87.expect.css b/plugin-packs/postcss-preset-env/test/import.ch87.expect.css deleted file mode 100644 index ded9c5eb87..0000000000 --- a/plugin-packs/postcss-preset-env/test/import.ch87.expect.css +++ /dev/null @@ -1,15 +0,0 @@ -.test-custom-properties { - order: 1; - order: var(--order); -} - -@media (max-width: 40rem) { - .test-custom-media-queries { - order: 2; - } -} - -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { - order: 3; - } - diff --git a/plugin-packs/postcss-preset-env/test/import.ch87.incorrect-options.expect.css b/plugin-packs/postcss-preset-env/test/import.ch87.incorrect-options.expect.css deleted file mode 100644 index 855fbe258f..0000000000 --- a/plugin-packs/postcss-preset-env/test/import.ch87.incorrect-options.expect.css +++ /dev/null @@ -1,14 +0,0 @@ -.test-custom-properties { - order: var(--order); -} - -@media (--narrow-window) { - .test-custom-media-queries { - order: 2; - } -} - -.test-custom-selectors:--heading { - order: 3; - } - diff --git a/plugin-packs/postcss-preset-env/test/import.css b/plugin-packs/postcss-preset-env/test/import.css deleted file mode 100644 index e562695476..0000000000 --- a/plugin-packs/postcss-preset-env/test/import.css +++ /dev/null @@ -1,16 +0,0 @@ -.test-custom-properties { - order: var(--order); -} - -@media (--narrow-window) { - .test-custom-media-queries { - order: 2; - } -} - -.test-custom-selectors { - &:--heading { - order: 3; - } -} - diff --git a/plugin-packs/postcss-preset-env/test/import.expect.css b/plugin-packs/postcss-preset-env/test/import.expect.css deleted file mode 100644 index ded9c5eb87..0000000000 --- a/plugin-packs/postcss-preset-env/test/import.expect.css +++ /dev/null @@ -1,15 +0,0 @@ -.test-custom-properties { - order: 1; - order: var(--order); -} - -@media (max-width: 40rem) { - .test-custom-media-queries { - order: 2; - } -} - -h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.test-custom-selectors,h5.test-custom-selectors,h6.test-custom-selectors { - order: 3; - } - diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css index 4f49da5536..0b95438852 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -166,7 +166,49 @@ } } -h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css index 66fa374542..6342cc853e 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css @@ -205,7 +205,55 @@ @custom-selector :--heading h1, h2, h3, h4, h5, h6; -h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group:13; + -webkit-order:12; + -moz-box-ordinal-group:13; + -ms-flex-order:12; + order:12; +} + +.test-custom-selectors:is(h1, h2, h3, h4, h5, h6):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; diff --git a/plugins/postcss-custom-media/.tape.cjs b/plugins/postcss-custom-media/.tape.cjs deleted file mode 100644 index 60fff7ba9b..0000000000 --- a/plugins/postcss-custom-media/.tape.cjs +++ /dev/null @@ -1,255 +0,0 @@ -const postcssTape = require('../../packages/postcss-tape/dist/index.cjs'); -const plugin = require('postcss-custom-media'); -const fs = require('fs'); - -postcssTape(plugin)({ - 'basic': { - message: 'supports basic usage' - }, - 'basic:preserve': { - message: 'supports { preserve: true } usage', - options: { - preserve: true - } - }, - 'examples/example': { - message: 'minimal example', - }, - 'examples/example:preserve': { - message: 'minimal example', - options: { - preserve: true - } - }, - 'complex': { - message: 'supports complex usage' - }, - 'import': { - message: 'supports { importFrom: { customMedia: { ... } } } usage', - options: { - importFrom: { - customMedia: { - '--mq-a': '(max-width: 30em), (max-height: 30em)', - '--not-mq-a': 'not all and (--mq-a)' - } - } - } - }, - 'import:import-fn': { - message: 'supports { importFrom() } usage', - options: { - importFrom() { - return { - customMedia: { - '--mq-a': '(max-width: 30em), (max-height: 30em)', - '--not-mq-a': 'not all and (--mq-a)' - } - }; - } - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:import-fn-promise': { - message: 'supports { async importFrom() } usage', - options: { - importFrom() { - return new Promise(resolve => { - resolve({ - customMedia: { - '--mq-a': '(max-width: 30em), (max-height: 30em)', - '--not-mq-a': 'not all and (--mq-a)' - } - }) - }); - } - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:json': { - message: 'supports { importFrom: "test/import-media.json" } usage', - options: { - importFrom: 'test/import-media.json' - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:js': { - message: 'supports { importFrom: "test/import-media.js" } usage', - options: { - importFrom: 'test/import-media.js' - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:css': { - message: 'supports { importFrom: "test/import-media.css" } usage', - options: { - importFrom: 'test/import-media.css' - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:css-from': { - message: 'supports { importFrom: { from: "test/import-media.css" } } usage', - options: { - importFrom: { from: 'test/import-media.css' } - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:css-from-type': { - message: 'supports { importFrom: [ { from: "test/import-media.css", type: "css" } ] } usage', - options: { - importFrom: [{ from: 'test/import-media.css', type: 'css' }] - }, - expect: 'import.expect.css', - result: 'import.result.css' - }, - 'import:empty': { - message: 'supports { importFrom: {} } usage', - options: { - importFrom: {} - } - }, - 'basic:export': { - message: 'supports { exportTo: { customMedia: { ... } } } usage', - options: { - exportTo: (global.__exportMediaObject = global.__exportMediaObject || { - customMedia: null - }) - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - after() { - if (__exportMediaObject.customMedia['--mq-a'] !== '(max-width: 30em), (max-height: 30em)') { - throw new Error('The exportTo function failed'); - } - } - }, - 'basic:export-fn': { - message: 'supports { exportTo() } usage', - options: { - exportTo(customMedia) { - if (customMedia['--mq-a'] !== '(max-width: 30em), (max-height: 30em)') { - throw new Error('The exportTo function failed'); - } - } - }, - expect: 'basic.expect.css', - result: 'basic.result.css' - }, - 'basic:export-fn-promise': { - message: 'supports { async exportTo() } usage', - options: { - exportTo(customMedia) { - return new Promise((resolve, reject) => { - if (customMedia['--mq-a'] !== '(max-width: 30em), (max-height: 30em)') { - reject('The exportTo function failed'); - } else { - resolve(); - } - }); - } - }, - expect: 'basic.expect.css', - result: 'basic.result.css' - }, - 'basic:export-json': { - message: 'supports { exportTo: "test/export-media.json" } usage', - options: { - exportTo: 'test/export-media.json' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - global.__exportMediaString = fs.readFileSync('test/export-media.json', 'utf8'); - }, - after() { - if (global.__exportMediaString !== fs.readFileSync('test/export-media.json', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - } - }, - 'basic:export-js': { - message: 'supports { exportTo: "test/export-media.js" } usage', - options: { - exportTo: 'test/export-media.js' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - global.__exportMediaString = fs.readFileSync('test/export-media.js', 'utf8'); - }, - after() { - if (global.__exportMediaString !== fs.readFileSync('test/export-media.js', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - } - }, - 'basic:export-mjs': { - message: 'supports { exportTo: "test/export-media.mjs" } usage', - options: { - exportTo: 'test/export-media.mjs' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - global.__exportMediaString = fs.readFileSync('test/export-media.mjs', 'utf8'); - }, - after() { - if (global.__exportMediaString !== fs.readFileSync('test/export-media.mjs', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - } - }, - 'basic:export-css': { - message: 'supports { exportTo: "test/export-media.css" } usage', - options: { - exportTo: 'test/export-media.css' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - global.__exportMediaString = fs.readFileSync('test/export-media.css', 'utf8'); - }, - after() { - if (global.__exportMediaString !== fs.readFileSync('test/export-media.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - } - }, - 'basic:export-css-to': { - message: 'supports { exportTo: { to: "test/export-media.css" } } usage', - options: { - exportTo: { to: 'test/export-media.css' } - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - global.__exportMediaString = fs.readFileSync('test/export-media.css', 'utf8'); - }, - after() { - if (global.__exportMediaString !== fs.readFileSync('test/export-media.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - } - }, - 'basic:export-css-to-type': { - message: 'supports { exportTo: { to: "test/export-media.css", type: "css" } } usage', - options: { - exportTo: { to: 'test/export-media.css', type: 'css' } - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - global.__exportMediaString = fs.readFileSync('test/export-media.css', 'utf8'); - }, - after() { - if (global.__exportMediaString !== fs.readFileSync('test/export-media.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - } - } -}); diff --git a/plugins/postcss-custom-media/.tape.mjs b/plugins/postcss-custom-media/.tape.mjs new file mode 100644 index 0000000000..f13d9db694 --- /dev/null +++ b/plugins/postcss-custom-media/.tape.mjs @@ -0,0 +1,26 @@ +import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; +import plugin from 'postcss-custom-media'; + +postcssTape(plugin)({ + 'basic': { + message: 'supports basic usage' + }, + 'basic:preserve': { + message: 'supports { preserve: true } usage', + options: { + preserve: true + } + }, + 'examples/example': { + message: 'minimal example', + }, + 'examples/example:preserve': { + message: 'minimal example', + options: { + preserve: true + } + }, + 'complex': { + message: 'supports complex usage' + }, +}); diff --git a/plugins/postcss-custom-media/package.json b/plugins/postcss-custom-media/package.json index d12f4aec88..8716e7409f 100644 --- a/plugins/postcss-custom-media/package.json +++ b/plugins/postcss-custom-media/package.json @@ -58,9 +58,9 @@ "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", "lint:package-json": "node ../../.github/bin/format-package-json.mjs", "prepublishOnly": "npm run clean && npm run build && npm run test", - "test": "node .tape.cjs && npm run test:exports", + "test": "node .tape.mjs && npm run test:exports", "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs", - "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.cjs" + "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs" }, "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media#readme", "repository": { diff --git a/plugins/postcss-custom-media/src/get-custom-media-from-imports.js b/plugins/postcss-custom-media/src/get-custom-media-from-imports.js deleted file mode 100644 index 944795ac5a..0000000000 --- a/plugins/postcss-custom-media/src/get-custom-media-from-imports.js +++ /dev/null @@ -1,110 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { parse } from 'postcss'; -import getMediaAstFromMediaString from './media-ast-from-string'; -import getCustomMedia from './custom-media-from-root'; - -/* Get Custom Media from CSS File -/* ========================================================================== */ - -async function getCustomMediaFromCSSFile(from) { - const css = await readFile(from); - const root = parse(css, { from }); - - return getCustomMedia(root, { preserve: true }); -} - -/* Get Custom Media from Object -/* ========================================================================== */ - -function getCustomMediaFromObject(object) { - const customMedia = Object.assign( - {}, - Object(object).customMedia, - Object(object)['custom-media'], - ); - - for (const key in customMedia) { - customMedia[key] = getMediaAstFromMediaString(customMedia[key]); - } - - return customMedia; -} - -/* Get Custom Media from JSON file -/* ========================================================================== */ - -async function getCustomMediaFromJSONFile(from) { - const object = await readJSON(from); - - return getCustomMediaFromObject(object); -} - -/* Get Custom Media from JS file -/* ========================================================================== */ - -async function getCustomMediaFromJSFile(from) { - const object = await import(from); - - return getCustomMediaFromObject(object); -} - -/* Get Custom Media from Sources -/* ========================================================================== */ - -export default function getCustomMediaFromSources(sources) { - return sources.map(source => { - if (source instanceof Promise) { - return source; - } else if (source instanceof Function) { - return source(); - } - - // read the source as an object - const opts = source === Object(source) ? source : { from: String(source) }; - - // skip objects with custom media - if (Object(opts).customMedia || Object(opts)['custom-media']) { - return opts; - } - - // source pathname - const from = path.resolve(String(opts.from || '')); - - // type of file being read from - const type = (opts.type || path.extname(from).slice(1)).toLowerCase(); - - return { type, from }; - }).reduce(async (customMedia, source) => { - const { type, from } = await source; - - if (type === 'css' || type === 'pcss') { - return Object.assign(await customMedia, await getCustomMediaFromCSSFile(from)); - } - - if (type === 'js') { - return Object.assign(await customMedia, await getCustomMediaFromJSFile(from)); - } - - if (type === 'json') { - return Object.assign(await customMedia, await getCustomMediaFromJSONFile(from)); - } - - return Object.assign(await customMedia, getCustomMediaFromObject(await source)); - }, {}); -} - -/* Helper utilities -/* ========================================================================== */ - -const readFile = from => new Promise((resolve, reject) => { - fs.readFile(from, 'utf8', (error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); -}); - -const readJSON = async from => JSON.parse(await readFile(from)); diff --git a/plugins/postcss-custom-media/src/index.js b/plugins/postcss-custom-media/src/index.js index 17d08a2edd..78d2136796 100644 --- a/plugins/postcss-custom-media/src/index.js +++ b/plugins/postcss-custom-media/src/index.js @@ -1,22 +1,10 @@ import getCustomMediaFromRoot from './custom-media-from-root'; -import getCustomMediaFromImports from './get-custom-media-from-imports'; import transformAtrules from './transform-atrules'; -import writeCustomMediaToExports from './write-custom-media-to-exports'; const creator = opts => { // whether to preserve custom media and at-rules using them const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : false; - // sources to import custom media from - const importFrom = [].concat(Object(opts).importFrom || []); - - - // destinations to export custom media to - const exportTo = [].concat(Object(opts).exportTo || []); - - // promise any custom media are imported - const customMediaImportsPromise = getCustomMediaFromImports(importFrom); - const customMediaHelperKey = Symbol('customMediaHelper'); return { @@ -24,12 +12,7 @@ const creator = opts => { Once: async (root, helpers) => { // combine rules from root and from imports - helpers[customMediaHelperKey] = Object.assign( - await customMediaImportsPromise, - getCustomMediaFromRoot(root, { preserve }), - ); - - await writeCustomMediaToExports(helpers[customMediaHelperKey], exportTo); + helpers[customMediaHelperKey] = getCustomMediaFromRoot(root, { preserve }); }, AtRule: (atrule, helpers) => { if (atrule.name !== 'media') { diff --git a/plugins/postcss-custom-media/src/write-custom-media-to-exports.js b/plugins/postcss-custom-media/src/write-custom-media-to-exports.js deleted file mode 100644 index 52754f3f53..0000000000 --- a/plugins/postcss-custom-media/src/write-custom-media-to-exports.js +++ /dev/null @@ -1,129 +0,0 @@ -import fs from 'fs'; -import path from 'path'; - -/* Write Custom Media from CSS File -/* ========================================================================== */ - -async function writeCustomMediaToCssFile(to, customMedia) { - const cssContent = Object.keys(customMedia).reduce((cssLines, name) => { - cssLines.push(`@custom-media ${name} ${customMedia[name]};`); - - return cssLines; - }, []).join('\n'); - const css = `${cssContent}\n`; - - await writeFile(to, css); -} - -/* Write Custom Media from JSON file -/* ========================================================================== */ - -async function writeCustomMediaToJsonFile(to, customMedia) { - const jsonContent = JSON.stringify({ - 'custom-media': customMedia, - }, null, '\t'); - const json = `${jsonContent}\n`; - - await writeFile(to, json); -} - -/* Write Custom Media from Common JS file -/* ========================================================================== */ - -async function writeCustomMediaToCjsFile(to, customMedia) { - const jsContents = Object.keys(customMedia).reduce((jsLines, name) => { - jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(customMedia[name])}'`); - - return jsLines; - }, []).join(',\n'); - const js = `module.exports = {\n\tcustomMedia: {\n${jsContents}\n\t}\n};\n`; - - await writeFile(to, js); -} - -/* Write Custom Media from Module JS file -/* ========================================================================== */ - -async function writeCustomMediaToMjsFile(to, customMedia) { - const mjsContents = Object.keys(customMedia).reduce((mjsLines, name) => { - mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(customMedia[name])}'`); - - return mjsLines; - }, []).join(',\n'); - const mjs = `export const customMedia = {\n${mjsContents}\n};\n`; - - await writeFile(to, mjs); -} - -/* Write Custom Media to Exports -/* ========================================================================== */ - -export default function writeCustomMediaToExports(customMedia, destinations) { - return Promise.all(destinations.map(async destination => { - if (destination instanceof Function) { - await destination(defaultCustomMediaToJSON(customMedia)); - } else { - // read the destination as an object - const opts = destination === Object(destination) ? destination : { to: String(destination) }; - - // transformer for custom media into a JSON-compatible object - const toJSON = opts.toJSON || defaultCustomMediaToJSON; - - if ('customMedia' in opts) { - // write directly to an object as customMedia - opts.customMedia = toJSON(customMedia); - } else if ('custom-media' in opts) { - // write directly to an object as custom-media - opts['custom-media'] = toJSON(customMedia); - } else { - // destination pathname - const to = String(opts.to || ''); - - // type of file being written to - const type = (opts.type || path.extname(to).slice(1)).toLowerCase(); - - // transformed custom media - const customMediaJSON = toJSON(customMedia); - - if (type === 'css') { - await writeCustomMediaToCssFile(to, customMediaJSON); - } - - if (type === 'js') { - await writeCustomMediaToCjsFile(to, customMediaJSON); - } - - if (type === 'json') { - await writeCustomMediaToJsonFile(to, customMediaJSON); - } - - if (type === 'mjs') { - await writeCustomMediaToMjsFile(to, customMediaJSON); - } - } - } - })); -} - -/* Helper utilities -/* ========================================================================== */ - -const defaultCustomMediaToJSON = customMedia => { - return Object.keys(customMedia).reduce((customMediaJSON, key) => { - customMediaJSON[key] = String(customMedia[key]); - - return customMediaJSON; - }, {}); -}; - -const writeFile = (to, text) => new Promise((resolve, reject) => { - fs.writeFile(to, text, error => { - if (error) { - reject(error); - } else { - resolve(); - } - }); -}); - -const escapeForJS = string => string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); diff --git a/plugins/postcss-custom-media/test/basic.import.expect.css b/plugins/postcss-custom-media/test/basic.import.expect.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/postcss-custom-media/test/export-media.css b/plugins/postcss-custom-media/test/export-media.css deleted file mode 100644 index f51e88c82e..0000000000 --- a/plugins/postcss-custom-media/test/export-media.css +++ /dev/null @@ -1,8 +0,0 @@ -@custom-media --mq-a (max-width: 30em), (max-height: 30em); -@custom-media --mq-b screen and (max-width: 30em); -@custom-media --not-mq-a not all and (--mq-a); -@custom-media --circular-mq-a (--circular-mq-b); -@custom-media --circular-mq-b (--circular-mq-a); -@custom-media --min (min-width: 320px); -@custom-media --max (max-width: 640px); -@custom-media --concat (min-width: 320px) and (max-width: 640px); diff --git a/plugins/postcss-custom-media/test/export-media.js b/plugins/postcss-custom-media/test/export-media.js deleted file mode 100644 index acccd84089..0000000000 --- a/plugins/postcss-custom-media/test/export-media.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - customMedia: { - '--mq-a': '(max-width: 30em), (max-height: 30em)', - '--mq-b': 'screen and (max-width: 30em)', - '--not-mq-a': 'not all and (--mq-a)', - '--circular-mq-a': '(--circular-mq-b)', - '--circular-mq-b': '(--circular-mq-a)', - '--min': '(min-width: 320px)', - '--max': '(max-width: 640px)', - '--concat': '(min-width: 320px) and (max-width: 640px)' - } -}; diff --git a/plugins/postcss-custom-media/test/export-media.json b/plugins/postcss-custom-media/test/export-media.json deleted file mode 100644 index 729bde28ee..0000000000 --- a/plugins/postcss-custom-media/test/export-media.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "custom-media": { - "--mq-a": "(max-width: 30em), (max-height: 30em)", - "--mq-b": "screen and (max-width: 30em)", - "--not-mq-a": "not all and (--mq-a)", - "--circular-mq-a": "(--circular-mq-b)", - "--circular-mq-b": "(--circular-mq-a)", - "--min": "(min-width: 320px)", - "--max": "(max-width: 640px)", - "--concat": "(min-width: 320px) and (max-width: 640px)" - } -} diff --git a/plugins/postcss-custom-media/test/export-media.mjs b/plugins/postcss-custom-media/test/export-media.mjs deleted file mode 100644 index ea36519d86..0000000000 --- a/plugins/postcss-custom-media/test/export-media.mjs +++ /dev/null @@ -1,10 +0,0 @@ -export const customMedia = { - '--mq-a': '(max-width: 30em), (max-height: 30em)', - '--mq-b': 'screen and (max-width: 30em)', - '--not-mq-a': 'not all and (--mq-a)', - '--circular-mq-a': '(--circular-mq-b)', - '--circular-mq-b': '(--circular-mq-a)', - '--min': '(min-width: 320px)', - '--max': '(max-width: 640px)', - '--concat': '(min-width: 320px) and (max-width: 640px)' -}; diff --git a/plugins/postcss-custom-media/test/import-css.css b/plugins/postcss-custom-media/test/import-css.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/postcss-custom-media/test/import-media.css b/plugins/postcss-custom-media/test/import-media.css deleted file mode 100644 index e788f32ae5..0000000000 --- a/plugins/postcss-custom-media/test/import-media.css +++ /dev/null @@ -1,2 +0,0 @@ -@custom-media --mq-a (max-width: 30em), (max-height: 30em); -@custom-media --not-mq-a not all and (--mq-a); diff --git a/plugins/postcss-custom-media/test/import-media.js b/plugins/postcss-custom-media/test/import-media.js deleted file mode 100644 index 3f2e0401ab..0000000000 --- a/plugins/postcss-custom-media/test/import-media.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - customMedia: { - '--mq-a': '(max-width: 30em), (max-height: 30em)', - '--not-mq-a': 'not all and (--mq-a)' - } -} diff --git a/plugins/postcss-custom-media/test/import-media.json b/plugins/postcss-custom-media/test/import-media.json deleted file mode 100644 index 807d8dfdd5..0000000000 --- a/plugins/postcss-custom-media/test/import-media.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "customMedia": { - "--mq-a": "(max-width: 30em), (max-height: 30em)", - "--not-mq-a": "not all and (--mq-a)" - } -} diff --git a/plugins/postcss-custom-media/test/import.css b/plugins/postcss-custom-media/test/import.css deleted file mode 100644 index f37220e74e..0000000000 --- a/plugins/postcss-custom-media/test/import.css +++ /dev/null @@ -1,29 +0,0 @@ -@media (--mq-a) { - body { - order: 1; - } -} - -@media (--mq-a), (--mq-a) { - body { - order: 1; - } -} - -@media not all and (--mq-a) { - body { - order: 2; - } -} - -@media (--not-mq-a) { - body { - order: 1; - } -} - -@media not all and (--not-mq-a) { - body { - order: 2; - } -} diff --git a/plugins/postcss-custom-media/test/import.empty.expect.css b/plugins/postcss-custom-media/test/import.empty.expect.css deleted file mode 100644 index f37220e74e..0000000000 --- a/plugins/postcss-custom-media/test/import.empty.expect.css +++ /dev/null @@ -1,29 +0,0 @@ -@media (--mq-a) { - body { - order: 1; - } -} - -@media (--mq-a), (--mq-a) { - body { - order: 1; - } -} - -@media not all and (--mq-a) { - body { - order: 2; - } -} - -@media (--not-mq-a) { - body { - order: 1; - } -} - -@media not all and (--not-mq-a) { - body { - order: 2; - } -} diff --git a/plugins/postcss-custom-media/test/import.expect.css b/plugins/postcss-custom-media/test/import.expect.css deleted file mode 100644 index 0bc2bbf3bf..0000000000 --- a/plugins/postcss-custom-media/test/import.expect.css +++ /dev/null @@ -1,29 +0,0 @@ -@media (max-width: 30em),(max-height: 30em) { - body { - order: 1; - } -} - -@media (max-width: 30em),(max-height: 30em), (max-width: 30em), (max-height: 30em) { - body { - order: 1; - } -} - -@media not all and (max-width: 30em),not all and (max-height: 30em) { - body { - order: 2; - } -} - -@media not all and (max-width: 30em),not all and (max-height: 30em) { - body { - order: 1; - } -} - -@media all and (max-width: 30em),all and (max-height: 30em) { - body { - order: 2; - } -} diff --git a/plugins/postcss-custom-media/test/import.plugin.expect.css b/plugins/postcss-custom-media/test/import.plugin.expect.css deleted file mode 100644 index 0bc2bbf3bf..0000000000 --- a/plugins/postcss-custom-media/test/import.plugin.expect.css +++ /dev/null @@ -1,29 +0,0 @@ -@media (max-width: 30em),(max-height: 30em) { - body { - order: 1; - } -} - -@media (max-width: 30em),(max-height: 30em), (max-width: 30em), (max-height: 30em) { - body { - order: 1; - } -} - -@media not all and (max-width: 30em),not all and (max-height: 30em) { - body { - order: 2; - } -} - -@media not all and (max-width: 30em),not all and (max-height: 30em) { - body { - order: 1; - } -} - -@media all and (max-width: 30em),all and (max-height: 30em) { - body { - order: 2; - } -} diff --git a/plugins/postcss-custom-properties/.tape.cjs b/plugins/postcss-custom-properties/.tape.cjs deleted file mode 100644 index 3c717ab096..0000000000 --- a/plugins/postcss-custom-properties/.tape.cjs +++ /dev/null @@ -1,29 +0,0 @@ -const postcssTape = require('../../packages/postcss-tape/dist/index.cjs'); -const plugin = require('postcss-custom-properties'); - -postcssTape(plugin)({ - 'basic:import-cjs': { - message: 'supports { importFrom: "test/import-properties{-2}?.cjs" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.cjs', - 'test/import-properties-2.cjs' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-css-js': { - message: 'supports { importFrom: "test/import-properties{-2}?.{css|js}" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.js', - 'test/import-properties-2.css' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - } -}); diff --git a/plugins/postcss-custom-properties/.tape.mjs b/plugins/postcss-custom-properties/.tape.mjs index 43fa4ae487..ffa02a7958 100644 --- a/plugins/postcss-custom-properties/.tape.mjs +++ b/plugins/postcss-custom-properties/.tape.mjs @@ -1,8 +1,6 @@ import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; import plugin from 'postcss-custom-properties'; -import { strict as assert } from 'assert'; import postcssImport from 'postcss-import'; -import fs from 'fs'; postcssTape(plugin)({ 'basic': { @@ -14,385 +12,6 @@ postcssTape(plugin)({ preserve: false } }, - 'basic:import': { - message: 'supports { importFrom: { customProperties: { ... } } } usage', - warnings: 1, - options: { - importFrom: { - customProperties: { - '--color': 'rgb(255, 0, 0)', - '--color-2': 'yellow', - '--ref-color': 'var(--color)', - '--margin': '0 10px 20px 30px', - '--z-index': 10 - } - } - } - }, - 'basic:import-fn': { - message: 'supports { importFrom() } usage', - warnings: 1, - options: { - importFrom() { - return { - customProperties: { - '--color': 'rgb(255, 0, 0)', - '--color-2': 'yellow', - '--ref-color': 'var(--color)', - '--margin': '0 10px 20px 30px', - '--z-index': 10 - } - }; - } - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-fn-promise': { - message: 'supports { async importFrom() } usage', - warnings: 1, - options: { - importFrom() { - return new Promise(resolve => { - resolve({ - customProperties: { - '--color': 'rgb(255, 0, 0)', - '--color-2': 'yellow', - '--ref-color': 'var(--color)', - '--z-index': 10 - } - }) - }); - } - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-json': { - message: 'supports { importFrom: "test/import-properties.json" } usage', - warnings: 1, - options: { - importFrom: 'test/import-properties.json' - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-cjs': { - message: 'supports { importFrom: "test/import-properties{-2}?.cjs" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.cjs', - 'test/import-properties-2.cjs' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-mjs': { - message: 'supports { importFrom: "test/import-properties{-2}?.mjs" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.mjs', - 'test/import-properties-2.mjs' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-css': { - message: 'supports { importFrom: "test/import-properties{-2}?.css" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.css', - 'test/import-properties-2.css' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-css-js': { - message: 'supports { importFrom: "test/import-properties{-2}?.{css|js}" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.js', - 'test/import-properties-2.css' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-css-pcss': { - message: 'supports { importFrom: "test/import-properties.{p}?css" } usage', - warnings: 1, - options: { - importFrom: [ - 'test/import-properties.pcss', - 'test/import-properties-2.css' - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-css-from': { - message: 'supports { importFrom: { from: "test/import-properties.css" } } usage', - warnings: 1, - options: { - importFrom: [ - { from: 'test/import-properties.css' }, - { from: 'test/import-properties-2.css' } - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-css-from-type': { - message: 'supports { importFrom: [ { from: "test/import-properties.css", type: "css" } ] } usage', - warnings: 1, - options: { - importFrom: [ - { from: 'test/import-properties.css', type: 'css' }, - { from: 'test/import-properties-2.css', type: 'css' } - ] - }, - expect: 'basic.import.expect.css', - result: 'basic.import.result.css' - }, - 'basic:import-override': { - message: 'importFrom with { preserve: false } should override root properties', - warnings: 1, - options: { - preserve: false, - importFrom: { - customProperties: { - '--color': 'rgb(0, 0, 0)', - '--color-2': 'yellow', - '--ref-color': 'var(--color)', - '--margin': '0 10px 20px 30px', - '--shadow-color': 'rgb(0,0,0)', - '--z-index': 10 - } - } - }, - expect: 'basic.import-override.expect.css', - result: 'basic.import-override.result.css' - }, - 'basic:import-override:inverse': { - message: 'importFrom with { preserve: false, overrideImportFromWithRoot: true } should override importFrom properties', - warnings: 1, - options: { - preserve: false, - overrideImportFromWithRoot: true, - importFrom: { - customProperties: { - '--color': 'rgb(0, 0, 0)', - '--color-2': 'yellow', - '--ref-color': 'var(--color)', - '--margin': '0 10px 20px 30px', - '--shadow-color': 'rgb(0,0,0)', - '--z-index': 10 - } - } - }, - expect: 'basic.import-override.inverse.expect.css', - result: 'basic.import-override.inverse.result.css' - }, - 'basic:export': { - message: 'supports { exportTo: { customProperties: { ... } } } usage', - warnings: 1, - options: { - exportTo: (global.__exportPropertiesObject = global.__exportPropertiesObject || { - customProperties: null - }) - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - after() { - if (__exportPropertiesObject.customProperties['--color'] !== 'rgb(255, 0, 0)') { - throw new Error('The exportTo function failed'); - } - } - }, - 'basic:export-fn': { - message: 'supports { exportTo() } usage', - warnings: 1, - options: { - exportTo(customProperties) { - if (customProperties['--color'] !== 'rgb(255, 0, 0)') { - throw new Error('The exportTo function failed'); - } - } - }, - expect: 'basic.expect.css', - result: 'basic.result.css' - }, - 'basic:export-fn-promise': { - message: 'supports { async exportTo() } usage', - warnings: 1, - options: { - exportTo(customProperties) { - return new Promise((resolve, reject) => { - if (customProperties['--color'] !== 'rgb(255, 0, 0)') { - reject('The exportTo function failed'); - } else { - resolve(); - } - }); - } - }, - expect: 'basic.expect.css', - result: 'basic.result.css' - }, - 'basic:export-scss': { - message: 'supports { exportTo: "test/export-properties.scss" } usage', - warnings: 1, - options: { - exportTo: 'test/export-properties.scss' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.scss', 'utf8'); - fs.rmSync('test/export-properties.scss'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.scss', 'utf8')); - } - }, - 'basic:export-json': { - message: 'supports { exportTo: "test/export-properties.json" } usage', - warnings: 1, - options: { - exportTo: 'test/export-properties.json' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.json', 'utf8'); - fs.rmSync('test/export-properties.json'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.json', 'utf8')); - } - }, - 'basic:export-js': { - message: 'supports { exportTo: "test/export-properties.js" } usage', - warnings: 1, - options: { - exportTo: 'test/export-properties.js' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.js', 'utf8'); - fs.rmSync('test/export-properties.js'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.js', 'utf8')); - } - }, - 'basic:export-mjs': { - message: 'supports { exportTo: "test/export-properties.mjs" } usage', - warnings: 1, - options: { - exportTo: 'test/export-properties.mjs' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.mjs', 'utf8'); - fs.rmSync('test/export-properties.mjs'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.mjs', 'utf8')); - } - }, - 'basic:export-css': { - message: 'supports { exportTo: "test/export-properties.css" } usage', - warnings: 1, - options: { - exportTo: 'test/export-properties.css' - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.css', 'utf8'); - fs.rmSync('test/export-properties.css'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.css', 'utf8')); - } - }, - 'basic:export-css-to': { - message: 'supports { exportTo: { to: "test/export-properties.css" } } usage', - warnings: 1, - options: { - exportTo: { to: 'test/export-properties.css' } - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.css', 'utf8'); - fs.rmSync('test/export-properties.css'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.css', 'utf8')); - } - }, - 'basic:export-css-to-type': { - message: 'supports { exportTo: { to: "test/export-properties.css", type: "css" } } usage', - warnings: 1, - options: { - exportTo: { to: 'test/export-properties.css', type: 'css' } - }, - expect: 'basic.expect.css', - result: 'basic.result.css', - before() { - try { - global.__exportPropertiesString = fs.readFileSync('test/export-properties.css', 'utf8'); - fs.rmSync('test/export-properties.css'); - } catch (_) { - // ignore - } - }, - after() { - assert.strictEqual(global.__exportPropertiesString, fs.readFileSync('test/export-properties.css', 'utf8')); - } - }, - 'basic:import-is-empty': { - message: 'supports { importFrom: {} } usage', - options: { - importFrom: {}, - disableDeprecationNotice: true - } - }, 'import': { message: 'supports "postcss-import"', plugins: [postcssImport(), plugin()] diff --git a/plugins/postcss-custom-properties/package.json b/plugins/postcss-custom-properties/package.json index 0bc556f3c2..4affc3d0e4 100644 --- a/plugins/postcss-custom-properties/package.json +++ b/plugins/postcss-custom-properties/package.json @@ -48,7 +48,7 @@ "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", "lint:package-json": "node ../../.github/bin/format-package-json.mjs", "prepublishOnly": "npm run clean && npm run build && npm run test", - "test": "node .tape.mjs && node .tape.cjs && npm run test:exports", + "test": "node .tape.mjs && npm run test:exports", "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs", "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs" }, diff --git a/plugins/postcss-custom-properties/src/index.ts b/plugins/postcss-custom-properties/src/index.ts index 22b2f1187c..9e54f98317 100644 --- a/plugins/postcss-custom-properties/src/index.ts +++ b/plugins/postcss-custom-properties/src/index.ts @@ -2,102 +2,28 @@ import type { PluginCreator } from 'postcss'; import type valuesParser from 'postcss-value-parser'; import getCustomPropertiesFromRoot from './lib/get-custom-properties-from-root'; -import getCustomPropertiesFromImports from './lib/get-custom-properties-from-imports'; import transformProperties from './lib/transform-properties'; -import writeCustomPropertiesToExports from './lib/write-custom-properties-to-exports'; -import type { ImportOptions, ExportOptions } from './lib/options'; export interface PluginOptions { - /** Do not emit warnings about "importFrom" and "exportTo" deprecations */ - disableDeprecationNotice?: boolean; /** Determines whether Custom Properties and properties using custom properties should be preserved in their original form. */ preserve?: boolean - - /** Specifies sources where Custom Properties can be imported from, which might be CSS, JS, and JSON files, functions, and directly passed objects. */ - importFrom?: ImportOptions | Array - - /** Specifies destinations where Custom Properties can be exported to, which might be CSS, JS, and JSON files, functions, and directly passed objects. */ - exportTo?: ExportOptions | Array - - /** Specifies if `importFrom` properties or `:root` properties have priority. */ - overrideImportFromWithRoot?: boolean } const creator: PluginCreator = (opts?: PluginOptions) => { // whether to preserve custom selectors and rules using them const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true; - const overrideImportFromWithRoot = 'overrideImportFromWithRoot' in Object(opts) ? Boolean(opts.overrideImportFromWithRoot) : false; - const disableDeprecationNotice = 'disableDeprecationNotice' in Object(opts) ? Boolean(opts.disableDeprecationNotice) : false; - - // sources to import custom selectors from - let importFrom: Array = []; - if (Array.isArray(opts?.importFrom)) { - importFrom = opts.importFrom; - } else if (opts?.importFrom) { - importFrom = [opts.importFrom]; - } - - // destinations to export custom selectors to - let exportTo: Array = []; - if (Array.isArray(opts?.exportTo)) { - exportTo = opts.exportTo; - } else if (opts?.exportTo) { - exportTo = [opts.exportTo]; - } - - // promise any custom selectors are imported - const customPropertiesPromise = getCustomPropertiesFromImports(importFrom); - - // whether to return synchronous function if no asynchronous operations are requested - const canReturnSyncFunction = importFrom.length === 0 && exportTo.length === 0; + let customProperties : Map = new Map(); return { postcssPlugin: 'postcss-custom-properties', - prepare () { - let customProperties: Map = new Map(); - - if (canReturnSyncFunction) { - return { - Once: (root) => { - customProperties = getCustomPropertiesFromRoot(root, { preserve }); - }, - Declaration: (decl) => { - transformProperties(decl, customProperties, { preserve }); - }, - OnceExit: () => { - customProperties.clear(); - }, - }; - } else { - return { - Once: async root => { - const importedCustomerProperties = (await customPropertiesPromise).entries(); - const rootCustomProperties = getCustomPropertiesFromRoot(root, { preserve: preserve }).entries(); - - if (overrideImportFromWithRoot) { - for (const [name, value] of [...importedCustomerProperties, ...rootCustomProperties]) { - customProperties.set(name, value); - } - } else { - for (const [name, value] of [...rootCustomProperties, ...importedCustomerProperties]) { - customProperties.set(name, value); - } - } - - await writeCustomPropertiesToExports(customProperties, exportTo); - }, - Declaration: (decl) => { - transformProperties(decl, customProperties, { preserve }); - }, - OnceExit: (root, { result }) => { - if (!disableDeprecationNotice && (importFrom.length > 0 || exportTo.length > 0)) { - root.warn(result, '"importFrom" and "exportTo" will be removed in a future version of postcss-custom-properties.\nWe are looking for insights and anecdotes on how these features are used so that we can design the best alternative.\nPlease let us know if our proposal will work for you.\nVisit the discussion on github for more details. https://github.com/csstools/postcss-plugins/discussions/192'); - } - - customProperties.clear(); - }, - }; - } + Once: (root) => { + customProperties = getCustomPropertiesFromRoot(root); + }, + Declaration: (decl) => { + transformProperties(decl, customProperties, { preserve: preserve }); + }, + OnceExit: () => { + customProperties.clear(); }, }; }; diff --git a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-imports.ts b/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-imports.ts deleted file mode 100644 index 1296201a07..0000000000 --- a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-imports.ts +++ /dev/null @@ -1,158 +0,0 @@ -import getCustomPropertiesFromRoot from './get-custom-properties-from-root'; -import path from 'path'; -import { pathToFileURL } from 'url'; -import type { ImportCustomProperties, ImportOptions } from './options'; -import valuesParser from 'postcss-value-parser'; -import { parse } from 'postcss'; -import { promises as fsp } from 'fs'; - -/* Get Custom Properties from CSS File -/* ========================================================================== */ - -async function getCustomPropertiesFromCSSFile(from) { - const css = await fsp.readFile(from); - const root = parse(css, { from : from.toString() }); - - return getCustomPropertiesFromRoot(root, { preserve: true }); -} - -/* Get Custom Properties from Object -/* ========================================================================== */ - -function getCustomPropertiesFromObject(object: ImportCustomProperties): Map { - const out: Map = new Map(); - - if ('customProperties' in object) { - for (const [name, value] of Object.entries(object.customProperties)) { - out.set(name, valuesParser(value.toString())); - } - } - - if ('custom-properties' in object) { - for (const [name, value] of Object.entries(object['custom-properties'])) { - out.set(name, valuesParser(value.toString())); - } - } - - return out; -} - -/* Get Custom Properties from JSON file -/* ========================================================================== */ - -async function getCustomPropertiesFromJSONFile(from): Promise> { - const object = await readJSON(from); - - return getCustomPropertiesFromObject(object); -} - -/* Get Custom Properties from JS file -/* ========================================================================== */ - -async function getCustomPropertiesFromJSFile(from): Promise> { - let object; - - try { - object = await import(from); - } catch (_) { - // windows support - object = await import(pathToFileURL(from).href); - } - - if ('default' in object) { - return getCustomPropertiesFromObject(object.default); - } - - return getCustomPropertiesFromObject(object); -} - -/* Get Custom Properties from Imports -/* ========================================================================== */ - -export default async function getCustomPropertiesFromImports(sources: Array): Promise> { - const sourceData = (await Promise.all(sources.map(async (source) => { - if (source instanceof Promise) { - source = await source; - } else if (source instanceof Function) { - source = await source(); - } - - if (typeof source === 'string') { - const fromPath = path.resolve(source); - const type = path.extname(fromPath).slice(1).toLowerCase(); - - return { - type: type, - from: fromPath, - }; - } - - if ('customProperties' in source && Object(source.customProperties) === source.customProperties) { - return source; - } - - if ('custom-properties' in source && Object(source['custom-properties']) === source['custom-properties']) { - return source; - } - - if ('from' in source) { - const fromPath = path.resolve(source.from); - let type = source.type; - if (!type) { - type = path.extname(fromPath).slice(1).toLowerCase(); - } - return { - type: type, - from: fromPath, - }; - } - - if (Object.keys(source).length === 0) { - // Empty `importFrom` object. - return null; - } - - return null; - }))).filter((x) => { - return !!x; - }); - - const data: Array> = await Promise.all(sourceData.map(async (partialData) => { - if (('type' in partialData) && ('from' in partialData)) { - if (partialData.type === 'css' || partialData.type === 'pcss') { - return await getCustomPropertiesFromCSSFile(partialData.from); - } - - if (partialData.type === 'js' || partialData.type === 'cjs') { - return await getCustomPropertiesFromJSFile(partialData.from); - } - - if (partialData.type === 'mjs') { - // Only works when running as a module. - return await getCustomPropertiesFromJSFile(partialData.from); - } - - if (partialData.type === 'json') { - return await getCustomPropertiesFromJSONFile(partialData.from); - } - - throw new Error('Invalid source type: ' + partialData.type); - } - - return getCustomPropertiesFromObject(partialData); - })); - - const out: Map = new Map(); - data.forEach((partialData) => { - for (const [name, value] of partialData.entries()) { - out.set(name, value); - } - }); - - return out; -} - -/* Helper utilities -/* ========================================================================== */ - -const readJSON = async from => JSON.parse((await fsp.readFile(from)).toString()); diff --git a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts b/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts index e177478fa1..acdd53c943 100644 --- a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts +++ b/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts @@ -1,41 +1,44 @@ +import { Root, Rule } from 'postcss'; import valuesParser from 'postcss-value-parser'; import { isBlockIgnored } from './is-ignored'; // return custom selectors from the css root, conditionally removing them -export default function getCustomPropertiesFromRoot(root, opts): Map { +export default function getCustomPropertiesFromRoot(root: Root): Map { // initialize custom selectors const customPropertiesFromHtmlElement: Map = new Map(); const customPropertiesFromRootPseudo: Map = new Map(); const out: Map = new Map(); // for each html or :root rule - root.nodes.slice().forEach(rule => { - const customPropertiesObject = isHtmlRule(rule) - ? customPropertiesFromHtmlElement - : isRootRule(rule) - ? customPropertiesFromRootPseudo - : null; - - // for each custom property - if (customPropertiesObject) { - rule.nodes.slice().forEach(decl => { - if (decl.variable && !isBlockIgnored(decl)) { - const { prop } = decl; - - // write the parsed value to the custom property - customPropertiesObject.set(prop, valuesParser(decl.value)); - - // conditionally remove the custom property declaration - if (!opts.preserve) { - decl.remove(); - } + root.each((rule) => { + if (rule.type !== 'rule') { + return; + } + + if (isHtmlRule(rule)) { + rule.each((decl) => { + if (decl.type !== 'decl') { + return; + } + + if (!decl.variable || isBlockIgnored(decl)) { + return; } + + customPropertiesFromHtmlElement.set(decl.prop, valuesParser(decl.value)); }); + } else if (isRootRule(rule)) { + rule.each((decl) => { + if (decl.type !== 'decl') { + return; + } - // conditionally remove the empty html or :root rule - if (!opts.preserve && isEmptyParent(rule) && !isBlockIgnored(rule)) { - rule.remove(); - } + if (!decl.variable || isBlockIgnored(decl)) { + return; + } + + customPropertiesFromRootPseudo.set(decl.prop, valuesParser(decl.value)); + }); } }); @@ -55,9 +58,10 @@ export default function getCustomPropertiesFromRoot(root, opts): Map node.type === 'rule' && node.selector.split(',').some(item => htmlSelectorRegExp.test(item)) && Object(node.nodes).length; -const isRootRule = node => node.type === 'rule' && node.selector.split(',').some(item => rootSelectorRegExp.test(item)) && Object(node.nodes).length; +function isHtmlRule(rule: Rule) { + return rule.selector.split(',').some(item => htmlSelectorRegExp.test(item)) && rule.nodes && rule.nodes.length; +} -// whether the node is a parent without children -const isEmptyParent = node => Object(node.nodes).length === 0; +function isRootRule(rule: Rule) { + return rule.selector.split(',').some(item => rootSelectorRegExp.test(item)) && rule.nodes && rule.nodes.length; +} diff --git a/plugins/postcss-custom-properties/src/lib/options.ts b/plugins/postcss-custom-properties/src/lib/options.ts deleted file mode 100644 index 6db403f7ff..0000000000 --- a/plugins/postcss-custom-properties/src/lib/options.ts +++ /dev/null @@ -1,14 +0,0 @@ - -export type ImportFromSource = { from: string, type?: string } | string; -export type ImportCustomProperties = { customProperties?: Record, 'custom-properties'?: Record }; -export type ImportAsFunction = () => ImportFromSource | ImportCustomProperties -export type ImportAsPromise = Promise -export type ImportAsFunctionPromise = () => Promise -export type ImportOptions = ImportFromSource | ImportCustomProperties | ImportAsFunction | ImportAsPromise | ImportAsFunctionPromise; - -export type ExportJSONFunction = (customProperties?: Record) => Record; -export type ExportToSource = { to: string, type?: string, toJSON: ExportJSONFunction } | string; -export type ExportCustomProperties = { customProperties?: Record, 'custom-properties'?: Record, toJSON: ExportJSONFunction }; -export type ExportAsFunction = (ExportCustomProperties) => void -export type ExportAsFunctionPromise = (ExportCustomProperties) => Promise -export type ExportOptions = ExportToSource | ExportCustomProperties | ExportAsFunction | ExportAsFunctionPromise; diff --git a/plugins/postcss-custom-properties/src/lib/write-custom-properties-to-exports.ts b/plugins/postcss-custom-properties/src/lib/write-custom-properties-to-exports.ts deleted file mode 100644 index bbd0b1cb65..0000000000 --- a/plugins/postcss-custom-properties/src/lib/write-custom-properties-to-exports.ts +++ /dev/null @@ -1,159 +0,0 @@ -import type valuesParser from 'postcss-value-parser'; - -import { promises as fsp } from 'fs'; -import path from 'path'; -import type { ExportOptions } from './options'; - -/* Write Custom Properties to CSS File -/* ========================================================================== */ - -async function writeCustomPropertiesToCssFile(to, customProperties) { - const cssContent = Object.keys(customProperties).reduce((cssLines, name) => { - cssLines.push(`\t${name}: ${customProperties[name]};`); - - return cssLines; - }, []).join('\n'); - const css = `:root {\n${cssContent}\n}\n`; - - await fsp.writeFile(to, css); -} - -/* Write Custom Properties to SCSS File -/* ========================================================================== */ - -async function writeCustomPropertiesToScssFile(to, customProperties) { - const scssContent = Object.keys(customProperties).reduce((scssLines, name) => { - const scssName = name.replace('--', '$'); - scssLines.push(`${scssName}: ${customProperties[name]};`); - - return scssLines; - }, []).join('\n'); - const scss = `${scssContent}\n`; - - await fsp.writeFile(to, scss); -} - -/* Write Custom Properties to JSON file -/* ========================================================================== */ - -async function writeCustomPropertiesToJsonFile(to, customProperties) { - const jsonContent = JSON.stringify({ - 'custom-properties': customProperties, - }, null, ' '); - const json = `${jsonContent}\n`; - - await fsp.writeFile(to, json); -} - -/* Write Custom Properties to Common JS file -/* ========================================================================== */ - -async function writeCustomPropertiesToCjsFile(to, customProperties) { - const jsContents = Object.keys(customProperties).reduce((jsLines, name) => { - jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(customProperties[name])}'`); - - return jsLines; - }, []).join(',\n'); - const js = `module.exports = {\n\tcustomProperties: {\n${jsContents}\n\t}\n};\n`; - - await fsp.writeFile(to, js); -} - -/* Write Custom Properties to Module JS file -/* ========================================================================== */ - -async function writeCustomPropertiesToMjsFile(to, customProperties) { - const mjsContents = Object.keys(customProperties).reduce((mjsLines, name) => { - mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(customProperties[name])}'`); - - return mjsLines; - }, []).join(',\n'); - const mjs = `export const customProperties = {\n${mjsContents}\n};\n`; - - await fsp.writeFile(to, mjs); -} - -/* Write Custom Properties to Exports -/* ========================================================================== */ - -export default function writeCustomPropertiesToExports(customProperties, destinations: Array) { - return Promise.all(destinations.map(async destination => { - if (destination instanceof Function) { - await destination(defaultCustomPropertiesToJSONObject(customProperties)); - return; - } - - if (typeof destination === 'string') { - const toPath = path.resolve(destination); - const type = path.extname(toPath).slice(1).toLowerCase(); - - await writePropertiesToFile(toPath, type, defaultCustomPropertiesToJSONObject(customProperties)); - return; - } - - // transformer for Custom Properties into a JSON-compatible object - let customPropertiesAsJSONObject = {}; - if ('toJSON' in destination) { - customPropertiesAsJSONObject = destination.toJSON(defaultCustomPropertiesToJSONObject(customProperties)); - } else { - customPropertiesAsJSONObject = defaultCustomPropertiesToJSONObject(customProperties); - } - - if ('to' in destination) { - const toPath = path.resolve(destination.to); - let type = destination.type; - if (!type) { - type = path.extname(toPath).slice(1).toLowerCase(); - } - - await writePropertiesToFile(toPath, type, customPropertiesAsJSONObject); - return; - } - - if ('customProperties' in destination) { - // write directly to an object as customProperties - destination.customProperties = customPropertiesAsJSONObject; - } else if ('custom-properties' in destination) { - // write directly to an object as custom-properties - destination['custom-properties'] = customPropertiesAsJSONObject; - } - })); -} - -async function writePropertiesToFile(to: string, type: string, customProperties: Record) { - if (type === 'css') { - await writeCustomPropertiesToCssFile(to, customProperties); - } - - if (type === 'scss') { - await writeCustomPropertiesToScssFile(to, customProperties); - } - - if (type === 'js') { - await writeCustomPropertiesToCjsFile(to, customProperties); - } - - if (type === 'json') { - await writeCustomPropertiesToJsonFile(to, customProperties); - } - - if (type === 'mjs') { - await writeCustomPropertiesToMjsFile(to, customProperties); - } -} - -/* Helper utilities -/* ========================================================================== */ - -function defaultCustomPropertiesToJSONObject(customProperties: Map): Record { - const out = {}; - for (const [name, value] of customProperties.entries()) { - out[name] = value.toString(); - } - - return out; -} - -const escapeForJS = (string) => { - return string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); -}; diff --git a/plugins/postcss-custom-properties/test/basic.css b/plugins/postcss-custom-properties/test/basic.css index 92d7a27be4..a30659889a 100644 --- a/plugins/postcss-custom-properties/test/basic.css +++ b/plugins/postcss-custom-properties/test/basic.css @@ -138,3 +138,7 @@ html { .test { font-family: var(--font, "Helvetica Neue", Arial, sans-serif); } + +.fallbacks-with-main-values-that-dont-exist { + color: var(--does-not-exist, var(--color)) +} diff --git a/plugins/postcss-custom-properties/test/basic.expect.css b/plugins/postcss-custom-properties/test/basic.expect.css index adbdb21f59..f5ec73cbc1 100644 --- a/plugins/postcss-custom-properties/test/basic.expect.css +++ b/plugins/postcss-custom-properties/test/basic.expect.css @@ -159,3 +159,8 @@ html { font-family: "Helvetica Neue", Arial, sans-serif; font-family: var(--font, "Helvetica Neue", Arial, sans-serif); } + +.fallbacks-with-main-values-that-dont-exist { + color: rgb(255, 0, 0); + color: var(--does-not-exist, var(--color)) +} diff --git a/plugins/postcss-custom-properties/test/basic.import-is-empty.expect.css b/plugins/postcss-custom-properties/test/basic.import-is-empty.expect.css deleted file mode 100644 index adbdb21f59..0000000000 --- a/plugins/postcss-custom-properties/test/basic.import-is-empty.expect.css +++ /dev/null @@ -1,161 +0,0 @@ -html { - --ref-color: skip; -} - -:root { - --color: rgb(255, 0, 0); - --color-h: 0; - --color-s: 100%; - --color-l: 50%; - --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); - --ref-color: var(--color); - --circular: var(--circular-2); - --circular-2: var(--circular); - --margin: 0 10px 20px 30px; - --shadow-color: rgb(255,0,0); - --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); - --font-family: "Open Sans", sans-serif; - --url-1: url("/my/path"); - --url-2: url('/my/path'); - --url-3: url(/my/path); - --url-4: url(data:image/png;bm90LWFuZC1pbWFnZQ==); - --✅-size: 2em; - color: rgb(255, 0, 0); - color: var(--color); -} - -:root, -[data-theme=light] { - --theme-color: #053; -} - -.ignore-line { - /* postcss-custom-properties: ignore next */ - color: var(--color); - background-color: blue; - background-color: var(--color-2, blue); -} - -.ignore-block { - /* postcss-custom-properties: off */ - color: var(--color-2, blue); - box-shadow: inset 0 -3px 0 var(--color); - background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); -} - -.test { - --skip: gray; - color: rgb(255, 0, 0); - color: var(--override, var(--color)); -} - -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); - box-shadow: inset 0 -3px 0 var(--color); -} - -.test--preserve_whitespaces { - margin: 0 10px 20px 30px; - margin: var(--margin); -} - -.test--complex_values { - box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); - box-shadow: var(--shadow); -} - -.test--comma_separated_values { - font-family: "Open Sans", sans-serif; - font-family: var(--font-family); -} - -.test--fallback { - color: blue; - color: var(--color-2, blue); -} - -.test--color_w_var { - color: rgb(255, 0, 0); - color: var(--ref-color); -} - -.test--color_w_vars { - color: hsl(0, 100%, 50%); - color: var(--color-hsl); -} - -.test--circular_var { - color: var(--circular); -} - -.test--z-index { - z-index: var(--z-index); -} - -.test--nested-fallback { - z-index: 1; - z-index: var(--xxx, var(--yyy, 1)); -} - -.text--calc { - width: calc((100% - 1px) + 10px); - width: calc((100% - var(--xxx, 1px)) + var(--yyy, 10px)); -} - -.test--linear-gradient { - background-image: linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(255, 0, 0) 100%); - background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); -} - -.test--loose-formatting { - color: rgb(255, 0, 0)/*rtl:red*/; - color: var( - --color, - blue - )/*rtl:red*/; -} - -.test--combined-selector { - color: #053; - color: var(--theme-color); -} - -.test--variable-with-url { - order: 1; - background: url("/my/path"); - background: var(--url-1); -} - -.test--variable-with-url { - order: 2; - background: url('/my/path'); - background: var(--url-2); -} - - -.test--variable-with-url { - order: 3; - background: url(/my/path); - background: var(--url-3); -} - - -.test--variable-with-url { - order: 4; - background: url(data:image/png;bm90LWFuZC1pbWFnZQ==); - background: var(--url-4); -} - -.no-prototype-collisions { - color: var(toString); -} - -.test-unicode { - color: 2em; - color: var(--✅-size); -} - -.test { - font-family: "Helvetica Neue", Arial, sans-serif; - font-family: var(--font, "Helvetica Neue", Arial, sans-serif); -} diff --git a/plugins/postcss-custom-properties/test/basic.import-override.expect.css b/plugins/postcss-custom-properties/test/basic.import-override.expect.css deleted file mode 100644 index cd0423d57f..0000000000 --- a/plugins/postcss-custom-properties/test/basic.import-override.expect.css +++ /dev/null @@ -1,111 +0,0 @@ -:root { - color: rgb(0, 0, 0); -} - -.ignore-line { - /* postcss-custom-properties: ignore next */ - color: var(--color); - background-color: yellow; -} - -.ignore-block { - /* postcss-custom-properties: off */ - color: var(--color-2, blue); - box-shadow: inset 0 -3px 0 var(--color); - background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); -} - -.test { - --skip: gray; - color: rgb(0, 0, 0); -} - -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(0, 0, 0); -} - -.test--preserve_whitespaces { - margin: 0 10px 20px 30px; -} - -.test--complex_values { - box-shadow: 0 6px 14px 0 color(rgb(0,0,0) a(.15)); -} - -.test--comma_separated_values { - font-family: "Open Sans", sans-serif; -} - -.test--fallback { - color: yellow; -} - -.test--color_w_var { - color: rgb(0, 0, 0); -} - -.test--color_w_vars { - color: hsl(0, 100%, 50%); -} - -.test--circular_var { - color: var(--circular); -} - -.test--z-index { - z-index: 10; -} - -.test--nested-fallback { - z-index: 1; -} - -.text--calc { - width: calc((100% - 1px) + 10px); -} - -.test--linear-gradient { - background-image: linear-gradient(to right, rgb(0, 0, 0) 0%, rgb(0, 0, 0) 100%); -} - -.test--loose-formatting { - color: rgb(0, 0, 0)/*rtl:red*/; -} - -.test--combined-selector { - color: #053; -} - -.test--variable-with-url { - order: 1; - background: url("/my/path"); -} - -.test--variable-with-url { - order: 2; - background: url('/my/path'); -} - - -.test--variable-with-url { - order: 3; - background: url(/my/path); -} - - -.test--variable-with-url { - order: 4; - background: url(data:image/png;bm90LWFuZC1pbWFnZQ==); -} - -.no-prototype-collisions { - color: var(toString); -} - -.test-unicode { - color: 2em; -} - -.test { - font-family: "Helvetica Neue", Arial, sans-serif; -} diff --git a/plugins/postcss-custom-properties/test/basic.import-override.inverse.expect.css b/plugins/postcss-custom-properties/test/basic.import-override.inverse.expect.css deleted file mode 100644 index 8f92924577..0000000000 --- a/plugins/postcss-custom-properties/test/basic.import-override.inverse.expect.css +++ /dev/null @@ -1,111 +0,0 @@ -:root { - color: rgb(255, 0, 0); -} - -.ignore-line { - /* postcss-custom-properties: ignore next */ - color: var(--color); - background-color: yellow; -} - -.ignore-block { - /* postcss-custom-properties: off */ - color: var(--color-2, blue); - box-shadow: inset 0 -3px 0 var(--color); - background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); -} - -.test { - --skip: gray; - color: rgb(255, 0, 0); -} - -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); -} - -.test--preserve_whitespaces { - margin: 0 10px 20px 30px; -} - -.test--complex_values { - box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); -} - -.test--comma_separated_values { - font-family: "Open Sans", sans-serif; -} - -.test--fallback { - color: yellow; -} - -.test--color_w_var { - color: rgb(255, 0, 0); -} - -.test--color_w_vars { - color: hsl(0, 100%, 50%); -} - -.test--circular_var { - color: var(--circular); -} - -.test--z-index { - z-index: 10; -} - -.test--nested-fallback { - z-index: 1; -} - -.text--calc { - width: calc((100% - 1px) + 10px); -} - -.test--linear-gradient { - background-image: linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(255, 0, 0) 100%); -} - -.test--loose-formatting { - color: rgb(255, 0, 0)/*rtl:red*/; -} - -.test--combined-selector { - color: #053; -} - -.test--variable-with-url { - order: 1; - background: url("/my/path"); -} - -.test--variable-with-url { - order: 2; - background: url('/my/path'); -} - - -.test--variable-with-url { - order: 3; - background: url(/my/path); -} - - -.test--variable-with-url { - order: 4; - background: url(data:image/png;bm90LWFuZC1pbWFnZQ==); -} - -.no-prototype-collisions { - color: var(toString); -} - -.test-unicode { - color: 2em; -} - -.test { - font-family: "Helvetica Neue", Arial, sans-serif; -} diff --git a/plugins/postcss-custom-properties/test/basic.import.expect.css b/plugins/postcss-custom-properties/test/basic.import.expect.css deleted file mode 100644 index cbb490f976..0000000000 --- a/plugins/postcss-custom-properties/test/basic.import.expect.css +++ /dev/null @@ -1,162 +0,0 @@ -html { - --ref-color: skip; -} - -:root { - --color: rgb(255, 0, 0); - --color-h: 0; - --color-s: 100%; - --color-l: 50%; - --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); - --ref-color: var(--color); - --circular: var(--circular-2); - --circular-2: var(--circular); - --margin: 0 10px 20px 30px; - --shadow-color: rgb(255,0,0); - --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); - --font-family: "Open Sans", sans-serif; - --url-1: url("/my/path"); - --url-2: url('/my/path'); - --url-3: url(/my/path); - --url-4: url(data:image/png;bm90LWFuZC1pbWFnZQ==); - --✅-size: 2em; - color: rgb(255, 0, 0); - color: var(--color); -} - -:root, -[data-theme=light] { - --theme-color: #053; -} - -.ignore-line { - /* postcss-custom-properties: ignore next */ - color: var(--color); - background-color: yellow; - background-color: var(--color-2, blue); -} - -.ignore-block { - /* postcss-custom-properties: off */ - color: var(--color-2, blue); - box-shadow: inset 0 -3px 0 var(--color); - background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); -} - -.test { - --skip: gray; - color: rgb(255, 0, 0); - color: var(--override, var(--color)); -} - -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); - box-shadow: inset 0 -3px 0 var(--color); -} - -.test--preserve_whitespaces { - margin: 0 10px 20px 30px; - margin: var(--margin); -} - -.test--complex_values { - box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); - box-shadow: var(--shadow); -} - -.test--comma_separated_values { - font-family: "Open Sans", sans-serif; - font-family: var(--font-family); -} - -.test--fallback { - color: yellow; - color: var(--color-2, blue); -} - -.test--color_w_var { - color: rgb(255, 0, 0); - color: var(--ref-color); -} - -.test--color_w_vars { - color: hsl(0, 100%, 50%); - color: var(--color-hsl); -} - -.test--circular_var { - color: var(--circular); -} - -.test--z-index { - z-index: 10; - z-index: var(--z-index); -} - -.test--nested-fallback { - z-index: 1; - z-index: var(--xxx, var(--yyy, 1)); -} - -.text--calc { - width: calc((100% - 1px) + 10px); - width: calc((100% - var(--xxx, 1px)) + var(--yyy, 10px)); -} - -.test--linear-gradient { - background-image: linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(255, 0, 0) 100%); - background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); -} - -.test--loose-formatting { - color: rgb(255, 0, 0)/*rtl:red*/; - color: var( - --color, - blue - )/*rtl:red*/; -} - -.test--combined-selector { - color: #053; - color: var(--theme-color); -} - -.test--variable-with-url { - order: 1; - background: url("/my/path"); - background: var(--url-1); -} - -.test--variable-with-url { - order: 2; - background: url('/my/path'); - background: var(--url-2); -} - - -.test--variable-with-url { - order: 3; - background: url(/my/path); - background: var(--url-3); -} - - -.test--variable-with-url { - order: 4; - background: url(data:image/png;bm90LWFuZC1pbWFnZQ==); - background: var(--url-4); -} - -.no-prototype-collisions { - color: var(toString); -} - -.test-unicode { - color: 2em; - color: var(--✅-size); -} - -.test { - font-family: "Helvetica Neue", Arial, sans-serif; - font-family: var(--font, "Helvetica Neue", Arial, sans-serif); -} diff --git a/plugins/postcss-custom-properties/test/basic.preserve.expect.css b/plugins/postcss-custom-properties/test/basic.preserve.expect.css index 01b766559d..f7a17f75eb 100644 --- a/plugins/postcss-custom-properties/test/basic.preserve.expect.css +++ b/plugins/postcss-custom-properties/test/basic.preserve.expect.css @@ -1,7 +1,33 @@ +html { + --ref-color: skip; +} + :root { + --color: rgb(255, 0, 0); + --color-h: 0; + --color-s: 100%; + --color-l: 50%; + --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); + --ref-color: var(--color); + --circular: var(--circular-2); + --circular-2: var(--circular); + --margin: 0 10px 20px 30px; + --shadow-color: rgb(255,0,0); + --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); + --font-family: "Open Sans", sans-serif; + --url-1: url("/my/path"); + --url-2: url('/my/path'); + --url-3: url(/my/path); + --url-4: url(data:image/png;bm90LWFuZC1pbWFnZQ==); + --✅-size: 2em; color: rgb(255, 0, 0); } +:root, +[data-theme=light] { + --theme-color: #053; +} + .ignore-line { /* postcss-custom-properties: ignore next */ color: var(--color); @@ -109,3 +135,7 @@ .test { font-family: "Helvetica Neue", Arial, sans-serif; } + +.fallbacks-with-main-values-that-dont-exist { + color: rgb(255, 0, 0) +} diff --git a/plugins/postcss-custom-properties/test/export-properties.css b/plugins/postcss-custom-properties/test/export-properties.css deleted file mode 100644 index 6c5bc15ff7..0000000000 --- a/plugins/postcss-custom-properties/test/export-properties.css +++ /dev/null @@ -1,20 +0,0 @@ -:root { - --ref-color: var(--color); - --color: rgb(255, 0, 0); - --color-h: 0; - --color-s: 100%; - --color-l: 50%; - --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); - --circular: var(--circular-2); - --circular-2: var(--circular); - --margin: 0 10px 20px 30px; - --shadow-color: rgb(255,0,0); - --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); - --font-family: "Open Sans", sans-serif; - --url-1: url("/my/path"); - --url-2: url('/my/path'); - --url-3: url(/my/path); - --url-4: url(data:image/png;bm90LWFuZC1pbWFnZQ==); - --✅-size: 2em; - --theme-color: #053; -} diff --git a/plugins/postcss-custom-properties/test/export-properties.js b/plugins/postcss-custom-properties/test/export-properties.js deleted file mode 100644 index 4a881c6cd8..0000000000 --- a/plugins/postcss-custom-properties/test/export-properties.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = { - customProperties: { - '--ref-color': 'var(--color)', - '--color': 'rgb(255, 0, 0)', - '--color-h': '0', - '--color-s': '100%', - '--color-l': '50%', - '--color-hsl': 'hsl(var(--color-h), var(--color-s), var(--color-l))', - '--circular': 'var(--circular-2)', - '--circular-2': 'var(--circular)', - '--margin': '0 10px 20px 30px', - '--shadow-color': 'rgb(255,0,0)', - '--shadow': '0 6px 14px 0 color(var(--shadow-color) a(.15))', - '--font-family': '"Open Sans", sans-serif', - '--url-1': 'url("/my/path")', - '--url-2': 'url(\'/my/path\')', - '--url-3': 'url(/my/path)', - '--url-4': 'url(data:image/png;bm90LWFuZC1pbWFnZQ==)', - '--✅-size': '2em', - '--theme-color': '#053' - } -}; diff --git a/plugins/postcss-custom-properties/test/export-properties.json b/plugins/postcss-custom-properties/test/export-properties.json deleted file mode 100644 index 723f042baf..0000000000 --- a/plugins/postcss-custom-properties/test/export-properties.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "custom-properties": { - "--ref-color": "var(--color)", - "--color": "rgb(255, 0, 0)", - "--color-h": "0", - "--color-s": "100%", - "--color-l": "50%", - "--color-hsl": "hsl(var(--color-h), var(--color-s), var(--color-l))", - "--circular": "var(--circular-2)", - "--circular-2": "var(--circular)", - "--margin": "0 10px 20px 30px", - "--shadow-color": "rgb(255,0,0)", - "--shadow": "0 6px 14px 0 color(var(--shadow-color) a(.15))", - "--font-family": "\"Open Sans\", sans-serif", - "--url-1": "url(\"/my/path\")", - "--url-2": "url('/my/path')", - "--url-3": "url(/my/path)", - "--url-4": "url(data:image/png;bm90LWFuZC1pbWFnZQ==)", - "--✅-size": "2em", - "--theme-color": "#053" - } -} diff --git a/plugins/postcss-custom-properties/test/export-properties.mjs b/plugins/postcss-custom-properties/test/export-properties.mjs deleted file mode 100644 index 30e030b941..0000000000 --- a/plugins/postcss-custom-properties/test/export-properties.mjs +++ /dev/null @@ -1,20 +0,0 @@ -export const customProperties = { - '--ref-color': 'var(--color)', - '--color': 'rgb(255, 0, 0)', - '--color-h': '0', - '--color-s': '100%', - '--color-l': '50%', - '--color-hsl': 'hsl(var(--color-h), var(--color-s), var(--color-l))', - '--circular': 'var(--circular-2)', - '--circular-2': 'var(--circular)', - '--margin': '0 10px 20px 30px', - '--shadow-color': 'rgb(255,0,0)', - '--shadow': '0 6px 14px 0 color(var(--shadow-color) a(.15))', - '--font-family': '"Open Sans", sans-serif', - '--url-1': 'url("/my/path")', - '--url-2': 'url(\'/my/path\')', - '--url-3': 'url(/my/path)', - '--url-4': 'url(data:image/png;bm90LWFuZC1pbWFnZQ==)', - '--✅-size': '2em', - '--theme-color': '#053' -}; diff --git a/plugins/postcss-custom-properties/test/export-properties.scss b/plugins/postcss-custom-properties/test/export-properties.scss deleted file mode 100644 index a920224bb1..0000000000 --- a/plugins/postcss-custom-properties/test/export-properties.scss +++ /dev/null @@ -1,18 +0,0 @@ -$ref-color: var(--color); -$color: rgb(255, 0, 0); -$color-h: 0; -$color-s: 100%; -$color-l: 50%; -$color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); -$circular: var(--circular-2); -$circular-2: var(--circular); -$margin: 0 10px 20px 30px; -$shadow-color: rgb(255,0,0); -$shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); -$font-family: "Open Sans", sans-serif; -$url-1: url("/my/path"); -$url-2: url('/my/path'); -$url-3: url(/my/path); -$url-4: url(data:image/png;bm90LWFuZC1pbWFnZQ==); -$✅-size: 2em; -$theme-color: #053; diff --git a/plugins/postcss-custom-properties/test/import-properties-2.cjs b/plugins/postcss-custom-properties/test/import-properties-2.cjs deleted file mode 100644 index a9ac867613..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties-2.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - customProperties: { - '--color': 'rgb(255, 0, 0)', - '--color-2': 'yellow', - }, -}; diff --git a/plugins/postcss-custom-properties/test/import-properties-2.css b/plugins/postcss-custom-properties/test/import-properties-2.css deleted file mode 100644 index 3f814966ad..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties-2.css +++ /dev/null @@ -1,4 +0,0 @@ -:root { - --color: rgb(255, 0, 0); - --color-2: yellow; -} diff --git a/plugins/postcss-custom-properties/test/import-properties-2.js b/plugins/postcss-custom-properties/test/import-properties-2.js deleted file mode 100644 index a9ac867613..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties-2.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - customProperties: { - '--color': 'rgb(255, 0, 0)', - '--color-2': 'yellow', - }, -}; diff --git a/plugins/postcss-custom-properties/test/import-properties-2.mjs b/plugins/postcss-custom-properties/test/import-properties-2.mjs deleted file mode 100644 index 22617d2ef8..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties-2.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - customProperties: { - '--color': 'rgb(255, 0, 0)', - '--color-2': 'yellow', - }, -}; diff --git a/plugins/postcss-custom-properties/test/import-properties.cjs b/plugins/postcss-custom-properties/test/import-properties.cjs deleted file mode 100644 index 4b2551bb6b..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - customProperties: { - '--ref-color': 'var(--color)', - '--z-index': 10, - }, -}; diff --git a/plugins/postcss-custom-properties/test/import-properties.css b/plugins/postcss-custom-properties/test/import-properties.css deleted file mode 100644 index a01ea3e89b..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties.css +++ /dev/null @@ -1,4 +0,0 @@ -:root { - --ref-color: var(--color); - --z-index: 10; -} diff --git a/plugins/postcss-custom-properties/test/import-properties.js b/plugins/postcss-custom-properties/test/import-properties.js deleted file mode 100644 index 4b2551bb6b..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - customProperties: { - '--ref-color': 'var(--color)', - '--z-index': 10, - }, -}; diff --git a/plugins/postcss-custom-properties/test/import-properties.json b/plugins/postcss-custom-properties/test/import-properties.json deleted file mode 100644 index d4125fc5d5..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "custom-properties": { - "--color": "rgb(255, 0, 0)", - "--color-2": "yellow", - "--ref-color": "var(--color)", - "--z-index": 10 - } -} diff --git a/plugins/postcss-custom-properties/test/import-properties.mjs b/plugins/postcss-custom-properties/test/import-properties.mjs deleted file mode 100644 index 78c3b75a2e..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - customProperties: { - '--ref-color': 'var(--color)', - '--z-index': 10, - }, -}; diff --git a/plugins/postcss-custom-properties/test/import-properties.pcss b/plugins/postcss-custom-properties/test/import-properties.pcss deleted file mode 100644 index a01ea3e89b..0000000000 --- a/plugins/postcss-custom-properties/test/import-properties.pcss +++ /dev/null @@ -1,4 +0,0 @@ -:root { - --ref-color: var(--color); - --z-index: 10; -} diff --git a/plugins/postcss-custom-selectors/.tape.cjs b/plugins/postcss-custom-selectors/.tape.cjs deleted file mode 100644 index 5d857dd120..0000000000 --- a/plugins/postcss-custom-selectors/.tape.cjs +++ /dev/null @@ -1,244 +0,0 @@ -const postcssTape = require('../../packages/postcss-tape/dist/index.cjs'); -const plugin = require('postcss-custom-selectors'); - -postcssTape(plugin)({ - 'basic': { - message: 'supports basic usage' - }, - 'basic:preserve': { - message: 'supports { preserve: true } usage', - options: { - preserve: true - } - }, - 'examples/example': { - message: 'minimal example', - }, - 'examples/example:preserve': { - message: 'minimal example', - options: { - preserve: true - } - }, - 'complex': { - message: 'supports complex usage' - }, - 'safety': { - message: 'supports safe tag ordering (.foo:--h1 becomes h1.foo instead of .fooh1)' - }, - 'basic-import': { - message: 'supports { importFrom: { customSelectors: { ... } } } usage', - options: { - importFrom: { - customSelectors: { - ':--heading': 'h1, h2, h3' - } - } - } - }, - 'basic-import:fn': { - message: 'supports { importFrom() } usage', - options: { - importFrom() { - return { - customSelectors: { - ':--heading': 'h1, h2, h3' - } - }; - } - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:fn-promise': { - message: 'supports { async importFrom() } usage', - options: { - importFrom() { - return new Promise(resolve => { - resolve({ - customSelectors: { - ':--heading': 'h1, h2, h3' - } - }) - }); - } - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:json': { - message: 'supports { importFrom: "test/import-selectors.json" } usage', - options: { - importFrom: 'test/import-selectors.json' - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:js': { - message: 'supports { importFrom: "test/import-selectors.js" } usage', - options: { - importFrom: 'test/import-selectors.js' - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css': { - message: 'supports { importFrom: "test/import-selectors.css" } usage', - options: { - importFrom: 'test/import-selectors.css' - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css-from': { - message: 'supports { importFrom: { from: "test/import-selectors.css" } } usage', - options: { - importFrom: { from: 'test/import-selectors.css' } - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css-from-multiple-files': { - message: 'supports { importFrom: ["test/empty.css", "test/import-selectors.css"] } usage', - options: { - importFrom: ["test/empty.css", "test/import-selectors.css"] - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css-from-type': { - message: 'supports { importFrom: [ { from: "test/import-selectors.css", type: "css" } ] } usage', - options: { - importFrom: [{ from: 'test/import-selectors.css', type: 'css' }] - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:empty': { - message: 'supports { importFrom: {} } usage', - options: { - importFrom: {} - } - }, - 'basic:export': { - message: 'supports { exportTo: { customSelectors: { ... } } } usage', - options: { - exportTo: (global.__exportSelectorObject = global.__exportSelectorObject || { - customSelectors: null - }) - }, - after() { - if (__exportSelectorObject.customSelectors[':--foo'] !== '.foo') { - throw new Error('The exportTo function failed'); - } - } - }, - 'basic:export-fn': { - message: 'supports { exportTo() } usage', - options: { - exportTo(customProperties) { - if (customProperties[':--foo'] !== '.foo') { - throw new Error('The exportTo function failed'); - } - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-fn-promise': { - message: 'supports { async exportTo() } usage', - options: { - exportTo(customProperties) { - return new Promise((resolve, reject) => { - if (customProperties[':--foo'] !== '.foo') { - reject('The exportTo function failed'); - } else { - resolve(); - } - }); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-json': { - message: 'supports { exportTo: "test/export-selectors.json" } usage', - options: { - exportTo: 'test/export-selectors.json' - }, - before() { - global.__exportSelectorsString = require('fs').readFileSync('test/export-selectors.json', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== require('fs').readFileSync('test/export-selectors.json', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-js': { - message: 'supports { exportTo: "test/export-selectors.js" } usage', - options: { - exportTo: 'test/export-selectors.js' - }, - before() { - global.__exportSelectorsString = require('fs').readFileSync('test/export-selectors.js', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== require('fs').readFileSync('test/export-selectors.js', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-mjs': { - message: 'supports { exportTo: "test/export-selectors.mjs" } usage', - options: { - exportTo: 'test/export-selectors.mjs' - }, - before() { - global.__exportSelectorsString = require('fs').readFileSync('test/export-selectors.mjs', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== require('fs').readFileSync('test/export-selectors.mjs', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-css': { - message: 'supports { exportTo: "test/export-selectors.css" } usage', - options: { - exportTo: 'test/export-selectors.css' - }, - before() { - global.__exportSelectorsString = require('fs').readFileSync('test/export-selectors.css', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== require('fs').readFileSync('test/export-selectors.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-css-to': { - message: 'supports { exportTo: { to: "test/export-selectors.css" } } usage', - options: { - exportTo: { to: 'test/export-selectors.css' } - }, - before() { - global.__exportSelectorsString = require('fs').readFileSync('test/export-selectors.css', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== require('fs').readFileSync('test/export-selectors.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-css-to-type': { - message: 'supports { exportTo: { to: "test/export-selectors.css", type: "css" } } usage', - options: { - exportTo: { to: 'test/export-selectors.css', type: 'css' } - }, - before() { - global.__exportSelectorsString = require('fs').readFileSync('test/export-selectors.css', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== require('fs').readFileSync('test/export-selectors.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - } -}); diff --git a/plugins/postcss-custom-selectors/.tape.mjs b/plugins/postcss-custom-selectors/.tape.mjs index 79664b78e0..ac36035080 100644 --- a/plugins/postcss-custom-selectors/.tape.mjs +++ b/plugins/postcss-custom-selectors/.tape.mjs @@ -1,6 +1,5 @@ import postcssTape from '../../packages/postcss-tape/dist/index.mjs'; import plugin from 'postcss-custom-selectors'; -import fs from 'fs'; postcssTape(plugin)({ 'basic': { @@ -27,220 +26,4 @@ postcssTape(plugin)({ 'safety': { message: 'supports safe tag ordering (.foo:--h1 becomes h1.foo instead of .fooh1)' }, - 'basic-import': { - message: 'supports { importFrom: { customSelectors: { ... } } } usage', - options: { - importFrom: { - customSelectors: { - ':--heading': 'h1, h2, h3' - } - } - } - }, - 'basic-import:fn': { - message: 'supports { importFrom() } usage', - options: { - importFrom() { - return { - customSelectors: { - ':--heading': 'h1, h2, h3' - } - }; - } - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:fn-promise': { - message: 'supports { async importFrom() } usage', - options: { - importFrom() { - return new Promise(resolve => { - resolve({ - customSelectors: { - ':--heading': 'h1, h2, h3' - } - }) - }); - } - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:json': { - message: 'supports { importFrom: "test/import-selectors.json" } usage', - options: { - importFrom: 'test/import-selectors.json' - }, - expect: 'basic-import.expect.css' - }, - // ⚠️ Importing CJS in MJS does not work ⚠️ - // 'basic-import:js': { - // message: 'supports { importFrom: "test/import-selectors.js" } usage', - // options: { - // importFrom: 'test/import-selectors.js' - // }, - // expect: 'basic-import.expect.css' - // }, - 'basic-import:css': { - message: 'supports { importFrom: "test/import-selectors.css" } usage', - options: { - importFrom: 'test/import-selectors.css' - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css-from': { - message: 'supports { importFrom: { from: "test/import-selectors.css" } } usage', - options: { - importFrom: { from: 'test/import-selectors.css' } - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css-from-multiple-files': { - message: 'supports { importFrom: ["test/empty.css", "test/import-selectors.css"] } usage', - options: { - importFrom: ["test/empty.css", "test/import-selectors.css"] - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:css-from-type': { - message: 'supports { importFrom: [ { from: "test/import-selectors.css", type: "css" } ] } usage', - options: { - importFrom: [{ from: 'test/import-selectors.css', type: 'css' }] - }, - expect: 'basic-import.expect.css' - }, - 'basic-import:empty': { - message: 'supports { importFrom: {} } usage', - options: { - importFrom: {} - } - }, - 'basic:export': { - message: 'supports { exportTo: { customSelectors: { ... } } } usage', - options: { - exportTo: (global.__exportSelectorObject = global.__exportSelectorObject || { - customSelectors: null - }) - }, - after() { - if (__exportSelectorObject.customSelectors[':--foo'] !== '.foo') { - throw new Error('The exportTo function failed'); - } - } - }, - 'basic:export-fn': { - message: 'supports { exportTo() } usage', - options: { - exportTo(customProperties) { - if (customProperties[':--foo'] !== '.foo') { - throw new Error('The exportTo function failed'); - } - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-fn-promise': { - message: 'supports { async exportTo() } usage', - options: { - exportTo(customProperties) { - return new Promise((resolve, reject) => { - if (customProperties[':--foo'] !== '.foo') { - reject('The exportTo function failed'); - } else { - resolve(); - } - }); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-json': { - message: 'supports { exportTo: "test/export-selectors.json" } usage', - options: { - exportTo: 'test/export-selectors.json' - }, - before() { - global.__exportSelectorsString = fs.readFileSync('test/export-selectors.json', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== fs.readFileSync('test/export-selectors.json', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-js': { - message: 'supports { exportTo: "test/export-selectors.js" } usage', - options: { - exportTo: 'test/export-selectors.js' - }, - before() { - global.__exportSelectorsString = fs.readFileSync('test/export-selectors.js', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== fs.readFileSync('test/export-selectors.js', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-mjs': { - message: 'supports { exportTo: "test/export-selectors.mjs" } usage', - options: { - exportTo: 'test/export-selectors.mjs' - }, - before() { - global.__exportSelectorsString = fs.readFileSync('test/export-selectors.mjs', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== fs.readFileSync('test/export-selectors.mjs', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-css': { - message: 'supports { exportTo: "test/export-selectors.css" } usage', - options: { - exportTo: 'test/export-selectors.css' - }, - before() { - global.__exportSelectorsString = fs.readFileSync('test/export-selectors.css', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== fs.readFileSync('test/export-selectors.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-css-to': { - message: 'supports { exportTo: { to: "test/export-selectors.css" } } usage', - options: { - exportTo: { to: 'test/export-selectors.css' } - }, - before() { - global.__exportSelectorsString = fs.readFileSync('test/export-selectors.css', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== fs.readFileSync('test/export-selectors.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - }, - 'basic:export-css-to-type': { - message: 'supports { exportTo: { to: "test/export-selectors.css", type: "css" } } usage', - options: { - exportTo: { to: 'test/export-selectors.css', type: 'css' } - }, - before() { - global.__exportSelectorsString = fs.readFileSync('test/export-selectors.css', 'utf8'); - }, - after() { - if (global.__exportSelectorsString !== fs.readFileSync('test/export-selectors.css', 'utf8')) { - throw new Error('The original file did not match the freshly exported copy'); - } - }, - expect: 'basic.expect.css' - } }); diff --git a/plugins/postcss-custom-selectors/package.json b/plugins/postcss-custom-selectors/package.json index b89775092e..b5b910e7e8 100644 --- a/plugins/postcss-custom-selectors/package.json +++ b/plugins/postcss-custom-selectors/package.json @@ -33,6 +33,7 @@ }, "main": "dist/index.cjs", "module": "dist/index.mjs", + "types": "dist/index.d.ts", "exports": { ".": { "import": "./dist/index.mjs", @@ -60,9 +61,9 @@ "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", "lint:package-json": "node ../../.github/bin/format-package-json.mjs", "prepublishOnly": "npm run clean && npm run build && npm run test", - "test": "node .tape.cjs && node .tape.mjs && npm run test:exports", + "test": "node .tape.mjs && npm run test:exports", "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs", - "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs && REWRITE_EXPECTS=true node .tape.cjs" + "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs" }, "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-selectors#readme", "repository": { diff --git a/plugins/postcss-custom-selectors/src/custom-selectors-from-root.js b/plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts similarity index 69% rename from plugins/postcss-custom-selectors/src/custom-selectors-from-root.js rename to plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts index 3a9b70cb30..7c89d063b3 100644 --- a/plugins/postcss-custom-selectors/src/custom-selectors-from-root.js +++ b/plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts @@ -1,9 +1,11 @@ +import type { Root as PostCSSRoot } from 'postcss'; +import type { Root as SelectorRoot } from 'postcss-selector-parser'; import parser from 'postcss-selector-parser'; // return custom selectors from the css root, conditionally removing them -export default (root, opts) => { +export default function getCustomSelectors(root: PostCSSRoot): Map { // initialize custom selectors - const customSelectors = {}; + const customSelectors = new Map(); // for each custom selector atrule that is a child of the css root root.nodes.slice().forEach(node => { @@ -26,13 +28,8 @@ export default (root, opts) => { const name = nameNode.toString(); // re-parsing is important to obtain the correct AST shape - customSelectors[name] = parser().astSync(source.slice(name.length).trim()); - - // conditionally remove the custom selector atrule - if (!Object(opts).preserve) { - node.remove(); - } + customSelectors.set(name, parser().astSync(source.slice(name.length).trim())); }); return customSelectors; -}; +} diff --git a/plugins/postcss-custom-selectors/src/export-to.js b/plugins/postcss-custom-selectors/src/export-to.js deleted file mode 100644 index 3420fe0747..0000000000 --- a/plugins/postcss-custom-selectors/src/export-to.js +++ /dev/null @@ -1,129 +0,0 @@ -import fs from 'fs'; -import path from 'path'; - -/* Import Custom Selectors from CSS File -/* ========================================================================== */ - -async function exportCustomSelectorsToCssFile(to, customSelectors) { - const cssContent = Object.keys(customSelectors).reduce((cssLines, name) => { - cssLines.push(`@custom-selector ${name} ${customSelectors[name]};`); - - return cssLines; - }, []).join('\n'); - const css = `${cssContent}\n`; - - await writeFile(to, css); -} - -/* Import Custom Selectors from JSON file -/* ========================================================================== */ - -async function exportCustomSelectorsToJsonFile(to, customSelectors) { - const jsonContent = JSON.stringify({ - 'custom-selectors': customSelectors, - }, null, '\t'); - const json = `${jsonContent}\n`; - - await writeFile(to, json); -} - -/* Import Custom Selectors from Common JS file -/* ========================================================================== */ - -async function exportCustomSelectorsToCjsFile(to, customSelectors) { - const jsContents = Object.keys(customSelectors).reduce((jsLines, name) => { - jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(customSelectors[name])}'`); - - return jsLines; - }, []).join(',\n'); - const js = `module.exports = {\n\tcustomSelectors: {\n${jsContents}\n\t}\n};\n`; - - await writeFile(to, js); -} - -/* Import Custom Selectors from Module JS file -/* ========================================================================== */ - -async function exportCustomSelectorsToMjsFile(to, customSelectors) { - const mjsContents = Object.keys(customSelectors).reduce((mjsLines, name) => { - mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(customSelectors[name])}'`); - - return mjsLines; - }, []).join(',\n'); - const mjs = `export const customSelectors = {\n${mjsContents}\n};\n`; - - await writeFile(to, mjs); -} - -/* Export Custom Selectors to Destinations -/* ========================================================================== */ - -export default function exportCustomSelectorsToDestinations(customSelectors, destinations) { - return Promise.all(destinations.map(async destination => { - if (destination instanceof Function) { - await destination(defaultCustomSelectorsToJSON(customSelectors)); - } else { - // read the destination as an object - const opts = destination === Object(destination) ? destination : { to: String(destination) }; - - // transformer for custom selectors into a JSON-compatible object - const toJSON = opts.toJSON || defaultCustomSelectorsToJSON; - - if ('customSelectors' in opts) { - // write directly to an object as customSelectors - opts.customSelectors = toJSON(customSelectors); - } else if ('custom-selectors' in opts) { - // write directly to an object as custom-selectors - opts['custom-selectors'] = toJSON(customSelectors); - } else { - // destination pathname - const to = String(opts.to || ''); - - // type of file being written to - const type = (opts.type || path.extname(opts.to).slice(1)).toLowerCase(); - - // transformed custom selectors - const customSelectorsJSON = toJSON(customSelectors); - - if (type === 'css') { - await exportCustomSelectorsToCssFile(to, customSelectorsJSON); - } - - if (type === 'js') { - await exportCustomSelectorsToCjsFile(to, customSelectorsJSON); - } - - if (type === 'json') { - await exportCustomSelectorsToJsonFile(to, customSelectorsJSON); - } - - if (type === 'mjs') { - await exportCustomSelectorsToMjsFile(to, customSelectorsJSON); - } - } - } - })); -} - -/* Helper utilities -/* ========================================================================== */ - -const defaultCustomSelectorsToJSON = customSelectors => { - return Object.keys(customSelectors).reduce((customSelectorsJSON, key) => { - customSelectorsJSON[key] = String(customSelectors[key]); - - return customSelectorsJSON; - }, {}); -}; - -const writeFile = (to, text) => new Promise((resolve, reject) => { - fs.writeFile(to, text, error => { - if (error) { - reject(error); - } else { - resolve(); - } - }); -}); - -const escapeForJS = string => string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); diff --git a/plugins/postcss-custom-selectors/src/import-from.js b/plugins/postcss-custom-selectors/src/import-from.js deleted file mode 100644 index 61c8fb5226..0000000000 --- a/plugins/postcss-custom-selectors/src/import-from.js +++ /dev/null @@ -1,121 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import postcss from 'postcss'; -import parser from 'postcss-selector-parser'; -import getCustomSelectors from './custom-selectors-from-root'; - -/* Import Custom Selectors from CSS AST -/* ========================================================================== */ - -function importCustomSelectorsFromCSSAST(root) { - return getCustomSelectors(root); -} - -/* Import Custom Selectors from CSS File -/* ========================================================================== */ - -async function importCustomSelectorsFromCSSFile(from) { - const css = await readFile(path.resolve(from)); - const root = postcss.parse(css, { from: path.resolve(from) }); - - return importCustomSelectorsFromCSSAST(root); -} - -/* Import Custom Selectors from Object -/* ========================================================================== */ - -function importCustomSelectorsFromObject(object) { - const customSelectors = Object.assign( - {}, - Object(object).customSelectors || Object(object)['custom-selectors'], - ); - - for (const key in customSelectors) { - customSelectors[key] = parser().astSync(customSelectors[key]); - } - - return customSelectors; -} - -/* Import Custom Selectors from JSON file -/* ========================================================================== */ - -async function importCustomSelectorsFromJSONFile(from) { - const object = await readJSON(path.resolve(from)); - - return importCustomSelectorsFromObject(object); -} - -/* Import Custom Selectors from JS file -/* ========================================================================== */ - -async function importCustomSelectorsFromJSFile(from) { - const object = await import(path.resolve(from)); - - return importCustomSelectorsFromObject(object); -} - -/* Import Custom Selectors from Sources -/* ========================================================================== */ - -export default function importCustomSelectorsFromSources(sources) { - return sources.map(source => { - if (source instanceof Promise) { - return source; - } else if (source instanceof Function) { - return source(); - } - - // read the source as an object - const opts = source === Object(source) ? source : { from: String(source) }; - - // skip objects with custom selectors - if (Object(opts).customSelectors || Object(opts)['custom-selectors']) { - return opts; - } - - // source pathname - const from = String(opts.from || ''); - - // type of file being read from - const type = (opts.type || path.extname(from).slice(1)).toLowerCase(); - - return { type, from }; - }).reduce(async (customSelectorsPromise, source) => { - const customSelectors = await customSelectorsPromise; - const { type, from } = await source; - - if (type === 'ast') { - return Object.assign(customSelectors, importCustomSelectorsFromCSSAST(from)); - } - - if (type === 'css') { - return Object.assign(customSelectors, await importCustomSelectorsFromCSSFile(from)); - } - - if (type === 'js') { - return Object.assign(customSelectors, await importCustomSelectorsFromJSFile(from)); - } - - if (type === 'json') { - return Object.assign(customSelectors, await importCustomSelectorsFromJSONFile(from)); - } - - return Object.assign(customSelectors, importCustomSelectorsFromObject(await source)); - }, Promise.resolve({})); -} - -/* Helper utilities -/* ========================================================================== */ - -const readFile = from => new Promise((resolve, reject) => { - fs.readFile(from, 'utf8', (error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); -}); - -const readJSON = async from => JSON.parse(await readFile(from)); diff --git a/plugins/postcss-custom-selectors/src/index.js b/plugins/postcss-custom-selectors/src/index.js deleted file mode 100644 index 156000b8c5..0000000000 --- a/plugins/postcss-custom-selectors/src/index.js +++ /dev/null @@ -1,45 +0,0 @@ -import getCustomSelectors from './custom-selectors-from-root'; -import transformRule from './transform-rule'; -import importCustomSelectorsFromSources from './import-from'; -import exportCustomSelectorsToDestinations from './export-to'; - -const creator = (opts) => { - // whether to preserve custom selectors and rules using them - const preserve = Boolean(Object(opts).preserve); - - // sources to import custom selectors from - const importFrom = [].concat(Object(opts).importFrom || []); - - // destinations to export custom selectors to - const exportTo = [].concat(Object(opts).exportTo || []); - - // promise any custom selectors are imported - const customSelectorsPromise = importCustomSelectorsFromSources(importFrom); - - const customSelectorHelperKey = Symbol('customSelectorHelper'); - - return { - postcssPlugin: 'postcss-custom-selectors', - Once: async (root, helpers) => { - helpers[customSelectorHelperKey] = Object.assign( - await customSelectorsPromise, - getCustomSelectors(root, { preserve }), - ); - - await exportCustomSelectorsToDestinations(helpers[customSelectorHelperKey], exportTo); - }, - Rule: (rule, helpers) => { - if (!rule.selector.includes(':--')) { - return; - } - - transformRule(rule, helpers[customSelectorHelperKey], { preserve }); - }, - }; -}; - -creator.postcss = true; - -export default creator; - - diff --git a/plugins/postcss-custom-selectors/src/index.ts b/plugins/postcss-custom-selectors/src/index.ts new file mode 100644 index 0000000000..b87ca1822f --- /dev/null +++ b/plugins/postcss-custom-selectors/src/index.ts @@ -0,0 +1,37 @@ +import type { PluginCreator } from 'postcss'; +import getCustomSelectors from './custom-selectors-from-root'; +import transformRule from './transform-rule'; + +export interface PluginOptions { + /** Determines whether Custom Selectors and selectors using custom selectors should be preserved in their original form. */ + preserve?: boolean +} + +const creator: PluginCreator = (opts?: PluginOptions) => { + // whether to preserve custom selectors and rules using them + const preserve = Boolean(Object(opts).preserve); + + return { + postcssPlugin: 'postcss-custom-selectors', + prepare() { + let customSelectors = new Map(); + + return { + Once: (root) => { + customSelectors = getCustomSelectors(root); + }, + Rule: (rule) => { + if (!rule.selector.includes(':--')) { + return; + } + + transformRule(rule, customSelectors, { preserve: preserve }); + }, + }; + }, + }; +}; + +creator.postcss = true; + +export default creator; diff --git a/plugins/postcss-custom-selectors/src/transform-rule.js b/plugins/postcss-custom-selectors/src/transform-rule.js deleted file mode 100644 index 0f9eeb0c3f..0000000000 --- a/plugins/postcss-custom-selectors/src/transform-rule.js +++ /dev/null @@ -1,19 +0,0 @@ -import parser from 'postcss-selector-parser'; -import transformSelectorsByCustomSelectors from './transform-selectors-by-custom-selectors'; - -// transform custom pseudo selectors with custom selectors -export default (rule, customSelectors, opts) => { - const selector = parser(selectors => { - transformSelectorsByCustomSelectors(selectors, customSelectors, opts); - }).processSync(rule.selector); - - if (selector === rule.selector) { - return; - } - - rule.cloneBefore({ selector: selector }); - - if (!opts.preserve) { - rule.remove(); - } -}; diff --git a/plugins/postcss-custom-selectors/src/transform-rule.ts b/plugins/postcss-custom-selectors/src/transform-rule.ts new file mode 100644 index 0000000000..f317f79dd3 --- /dev/null +++ b/plugins/postcss-custom-selectors/src/transform-rule.ts @@ -0,0 +1,38 @@ +import type { Root, Selector } from 'postcss-selector-parser'; +import parser from 'postcss-selector-parser'; + +// transform custom pseudo selectors with custom selectors +export default (rule, customSelectors: Map, opts) => { + const selector = parser(selectors => { + selectors.walkPseudos((pseudo) => { + if (!customSelectors.has(pseudo.value)) { + return; + } + + const isWrapper = parser.pseudo({ + value: ':is', + nodes: [], + }); + + const base = customSelectors.get(pseudo.value); + base.each((node) => { + isWrapper.append(node.clone({}) as Selector); + }); + + const parent = pseudo.parent; + + pseudo.replaceWith(isWrapper); + + }); + }).processSync(rule.selector); + + if (selector === rule.selector) { + return; + } + + rule.cloneBefore({ selector: selector }); + + if (!opts.preserve) { + rule.remove(); + } +}; diff --git a/plugins/postcss-custom-selectors/src/transform-selectors-by-custom-selectors.js b/plugins/postcss-custom-selectors/src/transform-selectors-by-custom-selectors.js deleted file mode 100644 index 37e32d5e63..0000000000 --- a/plugins/postcss-custom-selectors/src/transform-selectors-by-custom-selectors.js +++ /dev/null @@ -1,99 +0,0 @@ -// return transformed selectors, replacing custom pseudo selectors with custom selectors -export default function transformSelectorList(selectorList, customSelectors) { - let index = selectorList.nodes.length - 1; - - while (index >= 0) { - const transformedSelectors = transformSelector(selectorList.nodes[index], customSelectors); - - if (transformedSelectors.length) { - selectorList.nodes.splice(index, 1, ...transformedSelectors); - } - - --index; - } - - return selectorList; -} - -// return custom pseudo selectors replaced with custom selectors -function transformSelector(selector, customSelectors) { - const transpiledSelectors = []; - - for (const index in selector.nodes) { - const { value, nodes } = selector.nodes[index]; - - if (value in customSelectors) { - for (const replacementSelector of customSelectors[value].nodes) { - const selectorClone = selector.clone(); - - const replacementSelectorNodes = replacementSelector.clone().nodes; - - selectorClone.nodes.splice(index, 1, ...replacementSelectorNodes.map((node, index) => { - if (node.type === 'selector') { - // use spacing from the current usage - node.spaces = { ...selector.nodes[index].spaces }; - } - - if (index === 0 && node.spaces) { - node.spaces.before = ''; - } - - if (index === (replacementSelectorNodes.length - 1) && node.spaces) { - node.spaces.after = ''; - } - - return node; - })); - - const retranspiledSelectors = transformSelector(selectorClone, customSelectors); - - adjustNodesBySelectorEnds(selectorClone.nodes, Number(index)); - - if (retranspiledSelectors.length) { - transpiledSelectors.push(...retranspiledSelectors); - } else { - transpiledSelectors.push(selectorClone); - } - } - - return transpiledSelectors; - } else if (nodes && nodes.length) { - transformSelectorList(selector.nodes[index], customSelectors); - } - } - - return transpiledSelectors; -} - -// match selectors by difficult-to-separate ends -const withoutSelectorStartMatch = /^(tag|universal)$/; -const withoutSelectorEndMatch = /^(class|id|pseudo|tag|universal)$/; - -const isWithoutSelectorStart = node => withoutSelectorStartMatch.test(Object(node).type); -const isWithoutSelectorEnd = node => withoutSelectorEndMatch.test(Object(node).type); - -// adjust nodes by selector ends (so that .class:--h1 becomes h1.class rather than .classh1) -const adjustNodesBySelectorEnds = (nodes, index) => { - if (index && isWithoutSelectorStart(nodes[index]) && isWithoutSelectorEnd(nodes[index - 1])) { - let safeIndex = index - 1; - - while (safeIndex && isWithoutSelectorEnd(nodes[safeIndex])) { - --safeIndex; - } - - if (safeIndex < index) { - const node = nodes.splice(index, 1)[0]; - - nodes.splice(safeIndex, 0, node); - - nodes[safeIndex].spaces.before = nodes[safeIndex + 1].spaces.before; - nodes[safeIndex + 1].spaces.before = ''; - - if (nodes[index]) { - nodes[index].spaces.after = nodes[safeIndex].spaces.after; - nodes[safeIndex].spaces.after = ''; - } - } - } -}; - diff --git a/plugins/postcss-custom-selectors/test/basic-import.css b/plugins/postcss-custom-selectors/test/basic-import.css deleted file mode 100644 index 23fdd405ca..0000000000 --- a/plugins/postcss-custom-selectors/test/basic-import.css +++ /dev/null @@ -1,3 +0,0 @@ -article :--heading+p { - margin-top: 0; -} diff --git a/plugins/postcss-custom-selectors/test/basic-import.empty.expect.css b/plugins/postcss-custom-selectors/test/basic-import.empty.expect.css deleted file mode 100644 index 23fdd405ca..0000000000 --- a/plugins/postcss-custom-selectors/test/basic-import.empty.expect.css +++ /dev/null @@ -1,3 +0,0 @@ -article :--heading+p { - margin-top: 0; -} diff --git a/plugins/postcss-custom-selectors/test/basic-import.expect.css b/plugins/postcss-custom-selectors/test/basic-import.expect.css deleted file mode 100644 index 51a7130f9a..0000000000 --- a/plugins/postcss-custom-selectors/test/basic-import.expect.css +++ /dev/null @@ -1,3 +0,0 @@ -article h1+p,article h2+p,article h3+p { - margin-top: 0; -} diff --git a/plugins/postcss-custom-selectors/test/basic.expect.css b/plugins/postcss-custom-selectors/test/basic.expect.css index 1a6918335a..cd57782c15 100644 --- a/plugins/postcss-custom-selectors/test/basic.expect.css +++ b/plugins/postcss-custom-selectors/test/basic.expect.css @@ -1,34 +1,69 @@ -.foo.foo { +@custom-selector :--foo .bar, .baz; + +.foo:is(.foo) { margin-top: 16px; } -h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} - -.foo > .baz {} -.fizz > .foo,.buzz > .foo {} -.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active {} - -.foo + p,.bar > .baz + p { +@custom-selector :--any-heading h1, h2, h3, h4, h5, h6; + +:is(h1, h2, h3, h4, h5, h6) + p {} + +@custom-selector :--foobar .foo, .bar; +@custom-selector :--baz .baz; +@custom-selector :--fizzbuzz .fizz, .buzz; +@custom-selector :--button-types + .btn-primary, + .btn-success, + .btn-info, + .btn-warning, + .btn-danger; + +:is(.foo) > :is(.baz) {} +:is(.fizz, .buzz) > :is(.foo) {} +:is(.btn-primary, + .btn-success, + .btn-info, + .btn-warning, + .btn-danger),:is(.btn-primary, + .btn-success, + .btn-info, + .btn-warning, + .btn-danger):active {} + +@custom-selector :--commented-foo + /* comment */ + .foo, + .bar > .baz; + +:is(.foo, + .bar > .baz) + p { display: block; } -.foo > a::before img,.foo > a::after img { +@custom-selector :--pseudo ::before, ::after; + +.foo > a:is(::before, ::after) img { display: block; } -.foo,.foo.bar { +@custom-selector :--foo .foo; + +:is(.foo),:is(.foo).bar { color: white; } -.foo .foo:hover { +:is(.foo) :is(.foo):hover { color: white; } -.fo--oo > h1,.fo--oo > h2,.fo--oo > h3 { +@custom-selector :--fo-----o h1, h2, h3; +@custom-selector :--ba-----r h4, h5, h6; + +.fo--oo > :is(h1, h2, h3) { margin: auto; } -h4:hover .ba--z,h5:hover .ba--z,h6:hover .ba--z { +:is(h4, h5, h6):hover .ba--z { display: block; } @@ -38,48 +73,64 @@ article :--heading + p { margin-top: 0; } -.foo,.bar > .baz { +@custom-selector :--multiline + .foo, + .bar > .baz; + +:is(.foo, + .bar > .baz) { display: block; } /* should works with collapsed custom selectors */ -button:hover,button:focus,.button:hover,.button:focus {} +@custom-selector :--button button, .button; +@custom-selector :--enter :hover, :focus; + +:is(button, .button):is(:hover, :focus) {} + +@custom-selector :--any-foobar .foo, .bar; -.foo h1,.bar h1 { +:is(.foo, .bar) h1 { margin-top: 16px; } -main .foo + p { +main :is(.foo) + p { margin-top: 16px; } -.foo { +@custom-selector :--foobar .foo; + +:is(.foo) { order: 1000; } -a,.foo { +a,:is(.foo) { order: 1001; } -b,.foo { +b,:is(.foo) { order: 1002; } -.foo.baz { +@custom-selector :--foobaz .foo.baz; + +:is(.foo.baz) { order: 1010; } -a,.foo.baz { +a,:is(.foo.baz) { order: 1011; } -b,.foo.baz { +b,:is(.foo.baz) { order: 1012; } -.foo .baz { +@custom-selector :--foobazz .foo .baz; + +:is(.foo .baz) { order: 1020; } -a,.foo .baz { +a,:is(.foo .baz) { order: 1021; } -b,.foo .baz { +b,:is(.foo .baz) { order: 1022; } diff --git a/plugins/postcss-custom-selectors/test/basic.export.expect.css b/plugins/postcss-custom-selectors/test/basic.export.expect.css deleted file mode 100644 index 1a6918335a..0000000000 --- a/plugins/postcss-custom-selectors/test/basic.export.expect.css +++ /dev/null @@ -1,85 +0,0 @@ -.foo.foo { - margin-top: 16px; -} - -h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} - -.foo > .baz {} -.fizz > .foo,.buzz > .foo {} -.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active {} - -.foo + p,.bar > .baz + p { - display: block; -} - -.foo > a::before img,.foo > a::after img { - display: block; -} - -.foo,.foo.bar { - color: white; -} - -.foo .foo:hover { - color: white; -} - -.fo--oo > h1,.fo--oo > h2,.fo--oo > h3 { - margin: auto; -} - -h4:hover .ba--z,h5:hover .ba--z,h6:hover .ba--z { - display: block; -} - -/* comment */ - -article :--heading + p { - margin-top: 0; -} - -.foo,.bar > .baz { - display: block; -} - -/* should works with collapsed custom selectors */ - -button:hover,button:focus,.button:hover,.button:focus {} - -.foo h1,.bar h1 { - margin-top: 16px; -} - -main .foo + p { - margin-top: 16px; -} - -.foo { - order: 1000; -} -a,.foo { - order: 1001; -} -b,.foo { - order: 1002; -} - -.foo.baz { - order: 1010; -} -a,.foo.baz { - order: 1011; -} -b,.foo.baz { - order: 1012; -} - -.foo .baz { - order: 1020; -} -a,.foo .baz { - order: 1021; -} -b,.foo .baz { - order: 1022; -} diff --git a/plugins/postcss-custom-selectors/test/basic.preserve.expect.css b/plugins/postcss-custom-selectors/test/basic.preserve.expect.css index e5a03c4b06..953cb9de28 100644 --- a/plugins/postcss-custom-selectors/test/basic.preserve.expect.css +++ b/plugins/postcss-custom-selectors/test/basic.preserve.expect.css @@ -1,6 +1,6 @@ @custom-selector :--foo .bar, .baz; -.foo.foo { +.foo:is(.foo) { margin-top: 16px; } @@ -10,7 +10,7 @@ @custom-selector :--any-heading h1, h2, h3, h4, h5, h6; -h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} +:is(h1, h2, h3, h4, h5, h6) + p {} :--any-heading + p {} @@ -24,12 +24,20 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} .btn-warning, .btn-danger; -.foo > .baz {} +:is(.foo) > :is(.baz) {} :--foobar > :--baz {} -.fizz > .foo,.buzz > .foo {} +:is(.fizz, .buzz) > :is(.foo) {} :--fizzbuzz > :--foobar {} -.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active {} +:is(.btn-primary, + .btn-success, + .btn-info, + .btn-warning, + .btn-danger),:is(.btn-primary, + .btn-success, + .btn-info, + .btn-warning, + .btn-danger):active {} :--button-types, :--button-types:active {} @custom-selector :--commented-foo @@ -37,7 +45,8 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} .foo, .bar > .baz; -.foo + p,.bar > .baz + p { +:is(.foo, + .bar > .baz) + p { display: block; } @@ -47,7 +56,7 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} @custom-selector :--pseudo ::before, ::after; -.foo > a::before img,.foo > a::after img { +.foo > a:is(::before, ::after) img { display: block; } @@ -57,7 +66,7 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} @custom-selector :--foo .foo; -.foo,.foo.bar { +:is(.foo),:is(.foo).bar { color: white; } @@ -65,7 +74,7 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} color: white; } -.foo .foo:hover { +:is(.foo) :is(.foo):hover { color: white; } @@ -76,7 +85,7 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} @custom-selector :--fo-----o h1, h2, h3; @custom-selector :--ba-----r h4, h5, h6; -.fo--oo > h1,.fo--oo > h2,.fo--oo > h3 { +.fo--oo > :is(h1, h2, h3) { margin: auto; } @@ -84,7 +93,7 @@ h1 + p,h2 + p,h3 + p,h4 + p,h5 + p,h6 + p {} margin: auto; } -h4:hover .ba--z,h5:hover .ba--z,h6:hover .ba--z { +:is(h4, h5, h6):hover .ba--z { display: block; } @@ -102,7 +111,8 @@ article :--heading + p { .foo, .bar > .baz; -.foo,.bar > .baz { +:is(.foo, + .bar > .baz) { display: block; } @@ -115,13 +125,13 @@ article :--heading + p { @custom-selector :--button button, .button; @custom-selector :--enter :hover, :focus; -button:hover,button:focus,.button:hover,.button:focus {} +:is(button, .button):is(:hover, :focus) {} :--button:--enter {} @custom-selector :--any-foobar .foo, .bar; -.foo h1,.bar h1 { +:is(.foo, .bar) h1 { margin-top: 16px; } @@ -129,7 +139,7 @@ button:hover,button:focus,.button:hover,.button:focus {} margin-top: 16px; } -main .foo + p { +main :is(.foo) + p { margin-top: 16px; } @@ -139,20 +149,20 @@ main :--foo + p { @custom-selector :--foobar .foo; -.foo { +:is(.foo) { order: 1000; } :--foobar { order: 1000; } -a,.foo { +a,:is(.foo) { order: 1001; } a, :--foobar { order: 1001; } -b,.foo { +b,:is(.foo) { order: 1002; } b,:--foobar { @@ -161,20 +171,20 @@ b,:--foobar { @custom-selector :--foobaz .foo.baz; -.foo.baz { +:is(.foo.baz) { order: 1010; } :--foobaz { order: 1010; } -a,.foo.baz { +a,:is(.foo.baz) { order: 1011; } a, :--foobaz { order: 1011; } -b,.foo.baz { +b,:is(.foo.baz) { order: 1012; } b,:--foobaz { @@ -183,20 +193,20 @@ b,:--foobaz { @custom-selector :--foobazz .foo .baz; -.foo .baz { +:is(.foo .baz) { order: 1020; } :--foobazz { order: 1020; } -a,.foo .baz { +a,:is(.foo .baz) { order: 1021; } a, :--foobazz { order: 1021; } -b,.foo .baz { +b,:is(.foo .baz) { order: 1022; } b,:--foobazz { diff --git a/plugins/postcss-custom-selectors/test/complex.expect.css b/plugins/postcss-custom-selectors/test/complex.expect.css index 971fe5f2eb..ca0e573184 100644 --- a/plugins/postcss-custom-selectors/test/complex.expect.css +++ b/plugins/postcss-custom-selectors/test/complex.expect.css @@ -1,11 +1,17 @@ -.xl3 { +@custom-selector :--3xl .xl3; + +:is(.xl3) { order: 1; } -.singer { +@custom-selector :--🧑🏾‍🎤 .singer; + +:is(.singer) { order: 2; } -.dash { +@custom-selector :------- .dash; + +:is(.dash) { order: 3; } diff --git a/plugins/postcss-custom-selectors/test/empty.css b/plugins/postcss-custom-selectors/test/empty.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/postcss-custom-selectors/test/examples/example.expect.css b/plugins/postcss-custom-selectors/test/examples/example.expect.css index 5cdcf01f41..906075f2c8 100644 --- a/plugins/postcss-custom-selectors/test/examples/example.expect.css +++ b/plugins/postcss-custom-selectors/test/examples/example.expect.css @@ -1,3 +1,5 @@ -article h1 + p,article h2 + p,article h3 + p { +@custom-selector :--heading h1, h2, h3; + +article :is(h1, h2, h3) + p { margin-top: 0; } diff --git a/plugins/postcss-custom-selectors/test/examples/example.preserve.expect.css b/plugins/postcss-custom-selectors/test/examples/example.preserve.expect.css index 00738e691e..e1e64c88dc 100644 --- a/plugins/postcss-custom-selectors/test/examples/example.preserve.expect.css +++ b/plugins/postcss-custom-selectors/test/examples/example.preserve.expect.css @@ -1,6 +1,6 @@ @custom-selector :--heading h1, h2, h3; -article h1 + p,article h2 + p,article h3 + p { +article :is(h1, h2, h3) + p { margin-top: 0; } diff --git a/plugins/postcss-custom-selectors/test/export-selectors.css b/plugins/postcss-custom-selectors/test/export-selectors.css deleted file mode 100644 index b129f13291..0000000000 --- a/plugins/postcss-custom-selectors/test/export-selectors.css +++ /dev/null @@ -1,22 +0,0 @@ -@custom-selector :--foo .foo; -@custom-selector :--any-heading h1, h2, h3, h4, h5, h6; -@custom-selector :--foobar .foo; -@custom-selector :--baz .baz; -@custom-selector :--fizzbuzz .fizz, .buzz; -@custom-selector :--button-types .btn-primary, - .btn-success, - .btn-info, - .btn-warning, - .btn-danger; -@custom-selector :--commented-foo .foo, - .bar > .baz; -@custom-selector :--pseudo ::before, ::after; -@custom-selector :--fo-----o h1, h2, h3; -@custom-selector :--ba-----r h4, h5, h6; -@custom-selector :--multiline .foo, - .bar > .baz; -@custom-selector :--button button, .button; -@custom-selector :--enter :hover, :focus; -@custom-selector :--any-foobar .foo, .bar; -@custom-selector :--foobaz .foo.baz; -@custom-selector :--foobazz .foo .baz; diff --git a/plugins/postcss-custom-selectors/test/export-selectors.js b/plugins/postcss-custom-selectors/test/export-selectors.js deleted file mode 100644 index 060a3658a5..0000000000 --- a/plugins/postcss-custom-selectors/test/export-selectors.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - customSelectors: { - ':--foo': '.foo', - ':--any-heading': 'h1, h2, h3, h4, h5, h6', - ':--foobar': '.foo', - ':--baz': '.baz', - ':--fizzbuzz': '.fizz, .buzz', - ':--button-types': '.btn-primary,\n .btn-success,\n .btn-info,\n .btn-warning,\n .btn-danger', - ':--commented-foo': '.foo,\n .bar > .baz', - ':--pseudo': '::before, ::after', - ':--fo-----o': 'h1, h2, h3', - ':--ba-----r': 'h4, h5, h6', - ':--multiline': '.foo,\n .bar > .baz', - ':--button': 'button, .button', - ':--enter': ':hover, :focus', - ':--any-foobar': '.foo, .bar', - ':--foobaz': '.foo.baz', - ':--foobazz': '.foo .baz' - } -}; diff --git a/plugins/postcss-custom-selectors/test/export-selectors.json b/plugins/postcss-custom-selectors/test/export-selectors.json deleted file mode 100644 index c7967c5e9d..0000000000 --- a/plugins/postcss-custom-selectors/test/export-selectors.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "custom-selectors": { - ":--foo": ".foo", - ":--any-heading": "h1, h2, h3, h4, h5, h6", - ":--foobar": ".foo", - ":--baz": ".baz", - ":--fizzbuzz": ".fizz, .buzz", - ":--button-types": ".btn-primary,\n\t.btn-success,\n\t.btn-info,\n\t.btn-warning,\n\t.btn-danger", - ":--commented-foo": ".foo,\n\t.bar > .baz", - ":--pseudo": "::before, ::after", - ":--fo-----o": "h1, h2, h3", - ":--ba-----r": "h4, h5, h6", - ":--multiline": ".foo,\n\t.bar > .baz", - ":--button": "button, .button", - ":--enter": ":hover, :focus", - ":--any-foobar": ".foo, .bar", - ":--foobaz": ".foo.baz", - ":--foobazz": ".foo .baz" - } -} diff --git a/plugins/postcss-custom-selectors/test/export-selectors.mjs b/plugins/postcss-custom-selectors/test/export-selectors.mjs deleted file mode 100644 index a73ac9bc5d..0000000000 --- a/plugins/postcss-custom-selectors/test/export-selectors.mjs +++ /dev/null @@ -1,18 +0,0 @@ -export const customSelectors = { - ':--foo': '.foo', - ':--any-heading': 'h1, h2, h3, h4, h5, h6', - ':--foobar': '.foo', - ':--baz': '.baz', - ':--fizzbuzz': '.fizz, .buzz', - ':--button-types': '.btn-primary,\n .btn-success,\n .btn-info,\n .btn-warning,\n .btn-danger', - ':--commented-foo': '.foo,\n .bar > .baz', - ':--pseudo': '::before, ::after', - ':--fo-----o': 'h1, h2, h3', - ':--ba-----r': 'h4, h5, h6', - ':--multiline': '.foo,\n .bar > .baz', - ':--button': 'button, .button', - ':--enter': ':hover, :focus', - ':--any-foobar': '.foo, .bar', - ':--foobaz': '.foo.baz', - ':--foobazz': '.foo .baz' -}; diff --git a/plugins/postcss-custom-selectors/test/import-selectors.css b/plugins/postcss-custom-selectors/test/import-selectors.css deleted file mode 100644 index 6926002c1b..0000000000 --- a/plugins/postcss-custom-selectors/test/import-selectors.css +++ /dev/null @@ -1 +0,0 @@ -@custom-selector :--heading h1, h2, h3; diff --git a/plugins/postcss-custom-selectors/test/import-selectors.js b/plugins/postcss-custom-selectors/test/import-selectors.js deleted file mode 100644 index d645926680..0000000000 --- a/plugins/postcss-custom-selectors/test/import-selectors.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - customSelectors: { - ':--heading': 'h1, h2, h3', - }, -}; diff --git a/plugins/postcss-custom-selectors/test/import-selectors.json b/plugins/postcss-custom-selectors/test/import-selectors.json deleted file mode 100644 index 1416489f7c..0000000000 --- a/plugins/postcss-custom-selectors/test/import-selectors.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "custom-selectors": { - ":--heading": "h1, h2, h3" - } -} diff --git a/plugins/postcss-custom-selectors/test/safety.expect.css b/plugins/postcss-custom-selectors/test/safety.expect.css index a79db51653..b448103ffb 100644 --- a/plugins/postcss-custom-selectors/test/safety.expect.css +++ b/plugins/postcss-custom-selectors/test/safety.expect.css @@ -1,11 +1,13 @@ -h1.class, h1#id, h1::before, h1* { +@custom-selector :--h1 h1; + +.class:is(h1), #id:is(h1), ::before:is(h1), *:is(h1) { order: 1; } -h1.foo.class, h1.foo#id, h1.foo::before { +.foo.class:is(h1), .foo#id:is(h1), .foo::before:is(h1) { order: 2; } -h1.foo.class, h1.foo#id, h1.foo::before { +.foo.class:is(h1), .foo#id:is(h1), .foo::before:is(h1) { order: 3; } diff --git a/plugins/postcss-custom-selectors/tsconfig.json b/plugins/postcss-custom-selectors/tsconfig.json new file mode 100644 index 0000000000..2e428a8c22 --- /dev/null +++ b/plugins/postcss-custom-selectors/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": ".", + "module": "es2020" + }, + "include": ["./src/**/*"], + "exclude": ["dist"], +} From c371eb63e213e4c1dc75878cce18e671bb052490 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Tue, 16 Aug 2022 19:31:04 +0200 Subject: [PATCH 02/11] update test expect files --- .../test/basic.ch88-ff78.expect.css | 24 +++++++++++++++++-- .../basic.ch88-ff78.no-is-pseudo.expect.css | 24 +++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css index d942ef61f0..75eb1024bd 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css @@ -93,7 +93,27 @@ @custom-selector :--heading h1, h2, h3, h4, h5, h6; -.test-custom-selectors:is(h1, h2, h3, h4, h5, h6) { +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -488,7 +508,7 @@ @custom-selector :--view-m [data-view-size=m]; -:is([data-view-size=m]) .view { +[data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css index d942ef61f0..75eb1024bd 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css @@ -93,7 +93,27 @@ @custom-selector :--heading h1, h2, h3, h4, h5, h6; -.test-custom-selectors:is(h1, h2, h3, h4, h5, h6) { +h1.test-custom-selectors { + order:12; +} + +h2.test-custom-selectors { + order:12; +} + +h3.test-custom-selectors { + order:12; +} + +h4.test-custom-selectors { + order:12; +} + +h5.test-custom-selectors { + order:12; +} + +h6.test-custom-selectors { order:12; } @@ -488,7 +508,7 @@ @custom-selector :--view-m [data-view-size=m]; -:is([data-view-size=m]) .view { +[data-view-size=m] .view { background: red; } From de02fd1f07987ca18257b1dfc3544228eccc1183 Mon Sep 17 00:00:00 2001 From: Romain Menke <11521496+romainmenke@users.noreply.github.com> Date: Sat, 20 Aug 2022 18:04:45 +0200 Subject: [PATCH 03/11] wip (#543) * wip * fixes * fmt * better comment * fixes * more tests * make tests clearer * more interop tests * changelog --- plugin-packs/postcss-preset-env/.tape.mjs | 2 + plugin-packs/postcss-preset-env/FEATURES.md | 1 - .../src/lib/ids-by-execution-order.mjs | 2 +- .../postcss-preset-env/test/layers-basic.css | 10 +- .../test/layers-basic.expect.css | 204 +++++++-------- .../layers-basic.preserve.true.expect.css | 236 +++++++----------- plugins/postcss-cascade-layers/.tape.mjs | 10 +- plugins/postcss-cascade-layers/CHANGELOG.md | 5 + .../postcss-cascade-layers/src/constants.ts | 1 + .../src/desugar-and-parse-layer-names.ts | 15 +- .../src/desugar-nested-layers.ts | 7 +- .../src/get-layer-atrule-ancestor.ts | 3 +- plugins/postcss-cascade-layers/src/index.ts | 7 +- .../src/is-processable-layer-rule.ts | 28 +++ plugins/postcss-cascade-layers/src/model.ts | 3 +- .../src/record-layer-order.ts | 3 +- .../src/sort-root-nodes.ts | 19 +- .../test/extensions.css | 23 ++ .../test/extensions.expect.css | 20 ++ .../test/invalid-nested-css.css | 14 ++ .../test/invalid-nested-css.expect.css | 14 ++ .../test/nested-case-insensitive.expect.css | 3 - .../test/nested-complex.css | 13 + .../test/nested-complex.expect.css | 13 + .../postcss-cascade-layers/test/nested.css | 18 +- .../test/nested.expect.css | 19 +- .../test/warnings.expect.css | 4 +- plugins/postcss-custom-media/README.md | 84 ------- plugins/postcss-custom-media/docs/README.md | 84 ------- .../src/custom-media-from-root.js | 4 +- plugins/postcss-custom-media/src/index.js | 27 +- .../src/transform-media-list.js | 9 +- plugins/postcss-custom-media/test/basic.css | 24 ++ .../test/basic.expect.css | 21 ++ .../test/basic.preserve.expect.css | 34 +++ plugins/postcss-custom-properties/README.md | 135 ++-------- .../get-custom-properties-from-root.ts | 0 .../postcss-custom-properties/src/index.ts | 27 +- .../src/{lib => }/is-ignored.ts | 0 .../src/{lib => }/transform-properties.ts | 4 +- .../src/{lib => }/transform-value-ast.ts | 0 plugins/postcss-custom-selectors/README.md | 85 +------ .../postcss-custom-selectors/docs/README.md | 79 ------ .../postcss-nesting/src/lib/valid-atrules.js | 2 +- plugins/postcss-nesting/test/layer.css | 2 +- plugins/postcss-nesting/test/layer.expect.css | 9 +- 46 files changed, 529 insertions(+), 798 deletions(-) create mode 100644 plugins/postcss-cascade-layers/src/is-processable-layer-rule.ts create mode 100644 plugins/postcss-cascade-layers/test/extensions.css create mode 100644 plugins/postcss-cascade-layers/test/extensions.expect.css create mode 100644 plugins/postcss-cascade-layers/test/invalid-nested-css.css create mode 100644 plugins/postcss-cascade-layers/test/invalid-nested-css.expect.css rename plugins/postcss-custom-properties/src/{lib => }/get-custom-properties-from-root.ts (100%) rename plugins/postcss-custom-properties/src/{lib => }/is-ignored.ts (100%) rename plugins/postcss-custom-properties/src/{lib => }/transform-properties.ts (91%) rename plugins/postcss-custom-properties/src/{lib => }/transform-value-ast.ts (100%) diff --git a/plugin-packs/postcss-preset-env/.tape.mjs b/plugin-packs/postcss-preset-env/.tape.mjs index 02b429ea7f..24d89777a8 100644 --- a/plugin-packs/postcss-preset-env/.tape.mjs +++ b/plugin-packs/postcss-preset-env/.tape.mjs @@ -172,6 +172,7 @@ postcssTape(plugin)({ stage: 0, browsers: '> 0%' }, + warnings: 1, }, 'layers-basic:preserve:true': { message: 'supports layers usage with { preserve: true }', @@ -180,6 +181,7 @@ postcssTape(plugin)({ stage: 0, browsers: '> 0%' }, + warnings: 1, }, 'client-side-polyfills:stage-1': { message: 'stable client side polyfill behavior', diff --git a/plugin-packs/postcss-preset-env/FEATURES.md b/plugin-packs/postcss-preset-env/FEATURES.md index 57cd3aa96b..211128ec18 100644 --- a/plugin-packs/postcss-preset-env/FEATURES.md +++ b/plugin-packs/postcss-preset-env/FEATURES.md @@ -19,7 +19,6 @@ The `ID` listed is the key for PostCSS Preset Env configuration in your project. | `dir-pseudo-class` | `:dir` Directionality Pseudo-Class | [example](https://preset-env.cssdb.org/features/#dir-pseudo-class) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-dir-pseudo-class#readme) | | `display-two-values` | Two values syntax for `display` | [example](https://preset-env.cssdb.org/features/#display-two-values) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-normalize-display-values#readme) | | `double-position-gradients` | Double Position Gradients | [example](https://preset-env.cssdb.org/features/#double-position-gradients) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-double-position-gradients#readme) | -| `environment-variables` | Custom Environment Variables | [example](https://preset-env.cssdb.org/features/#environment-variables) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-env-function#readme) | | `focus-visible-pseudo-class` | `:focus-visible` Focus-Indicated Pseudo-Class | [example](https://preset-env.cssdb.org/features/#focus-visible-pseudo-class) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-visible#readme) | | `focus-within-pseudo-class` | `:focus-within` Focus Container Pseudo-Class | [example](https://preset-env.cssdb.org/features/#focus-within-pseudo-class) | [docs](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within#readme) | | `font-format-keywords` | Font `format()` Keywords | [example](https://preset-env.cssdb.org/features/#font-format-keywords) | [docs](https://github.com/valtlai/postcss-font-format-keywords#readme) | diff --git a/plugin-packs/postcss-preset-env/src/lib/ids-by-execution-order.mjs b/plugin-packs/postcss-preset-env/src/lib/ids-by-execution-order.mjs index 6b5d9db8d9..4bbe89108b 100644 --- a/plugin-packs/postcss-preset-env/src/lib/ids-by-execution-order.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/ids-by-execution-order.mjs @@ -1,5 +1,6 @@ // ids ordered by required execution, then alphabetically export default [ + 'cascade-layers', 'custom-media-queries', 'custom-properties', 'environment-variables', // run environment-variables here to access transpiled custom media params and properties @@ -32,7 +33,6 @@ export default [ 'overflow-wrap-property', 'place-properties', 'system-ui-font-family', - 'cascade-layers', 'stepped-value-functions', 'trigonometric-functions', ]; diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.css b/plugin-packs/postcss-preset-env/test/layers-basic.css index 8542107473..d7e512a928 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.css @@ -59,7 +59,13 @@ order: 9; } -@custom-media --narrow-window (max-width: 30em); +@custom-media --narrow-window (max-width: 500px); + +@layer extensions { + @custom-media --narrow-window (max-width: 30em); + + @custom-selector :--heading h1, h2, h3, h4, h5, h6; +} @media (--narrow-window) { .test-custom-media-queries { @@ -85,8 +91,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - .test-custom-selectors:--heading { order:12; } diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css index 408647ad12..74dc70b7b7 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -1,40 +1,22 @@ - - .test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) p { - is-layer: C_D; - -webkit-box-ordinal-group: 6; - -webkit-order: 5.1; - -moz-box-ordinal-group: 6; - -ms-flex-order: 5.1; - order: 5.1; - } - -:root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + @custom-selector :--heading h1, h2, h3, h4, h5, h6;:root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; --order: 1; - } - -.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; --firebrick: rgb(179, 35, 35); - } - -@supports (color: color(display-p3 0 0 0)){ -.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }@supports (color: color(display-p3 0 0 0)){ +.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --firebrick: color(display-p3 0.64331 0.19245 0.16771); } -} - -.test-custom-properties:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +}.test-custom-properties:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: var(--order); -webkit-order: var(--order); -moz-box-ordinal-group: var(--order); -ms-flex-order: var(--order); order: var(--order); - } - -.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; background-image: url(img/test.png); background-image: -webkit-image-set(url(img/test.png) 1x, url(img/test-2x.png) 2x); @@ -44,24 +26,14 @@ -moz-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; - } - -@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi){ - - .test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi){.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-image: url(img/test-2x.png); } -} - -[dir="ltr"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ +}[dir="ltr"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ margin: 1px 4px 3px 2px; -} - -[dir="rtl"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ +}[dir="rtl"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ margin: 1px 2px 3px 4px; -} - -.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +}.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: 4; -webkit-order: 3; @@ -70,27 +42,21 @@ order: 3; padding-top: 5px; padding-bottom: 5px; - } - -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: 5; -webkit-order: 4; -moz-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; - } - -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) p { + }.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) p { is-layer: C; -webkit-box-ordinal-group: 6; -webkit-order: 5; -moz-box-ordinal-group: 6; -ms-flex-order: 5; - order: 5; - } - -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + order: 5 + }.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: 7; @@ -100,8 +66,8 @@ order: 6; } -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), -#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), +#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 8; -webkit-order: 7; -moz-box-ordinal-group: 8; @@ -109,7 +75,7 @@ order: 7; } -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p, #test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p { +.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p, #test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p { -webkit-box-ordinal-group: 9; -webkit-order: 8; -moz-box-ordinal-group: 9; @@ -117,8 +83,8 @@ order: 8; } -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), -#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), +#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 10; @@ -131,8 +97,8 @@ order: 9; } -@media (max-width: 30em) { - .test-custom-media-queries:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +@media (max-width: 500px) { + .test-custom-media-queries:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 11; -webkit-order: 10; -moz-box-ordinal-group: 11; @@ -153,15 +119,13 @@ } @media (prefers-color-scheme: dark) { - body:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + body:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: black; color: white; } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - -h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -169,7 +133,7 @@ h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -177,7 +141,7 @@ h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -185,7 +149,7 @@ h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -193,7 +157,7 @@ h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -201,7 +165,7 @@ h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -209,7 +173,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -.test-case-insensitive-attributes[frame=hsides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=Hsides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-case-insensitive-attributes[frame=hsides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=Hsides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\# { -webkit-box-ordinal-group: 14; -webkit-order: 13; -moz-box-ordinal-group: 14; @@ -217,7 +181,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 13; } -.test-rebeccapurple-color:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-rebeccapurple-color:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color: #639; -webkit-box-ordinal-group: 15; -webkit-order: 14; @@ -226,7 +190,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 14; } -.test-hexadecimal-alpha-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-hexadecimal-alpha-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: rgba(243,243,243,0.95294); color: rgba(0,0,0,0.2); -webkit-box-ordinal-group: 16; @@ -236,7 +200,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 15; } -.test-color-functional-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-color-functional-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color: rgba(178, 34, 34, 0.5); -webkit-box-ordinal-group: 17; -webkit-order: 16; @@ -245,7 +209,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 16; } -.test-lab-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-lab-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: rgb(179, 35, 35); background-color: color(display-p3 0.64331 0.19245 0.16771); color: rgba(179, 34, 35, 0.5); @@ -257,7 +221,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 17; } -.test-system-ui-font-family:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-system-ui-font-family:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; -webkit-box-ordinal-group: 19; -webkit-order: 18; @@ -266,7 +230,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 18; } -.test-font-variant-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-font-variant-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-font-feature-settings: "smcp"; -moz-font-feature-settings: "smcp"; font-feature-settings: "smcp"; @@ -278,7 +242,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 19; } -.test-all-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-all-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-animation: none 0s ease 0s 1 normal none running; -moz-animation: none 0s ease 0s 1 normal none running; -o-animation: none 0s ease 0s 1 normal none running; @@ -420,7 +384,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 20; } -.test-matches-pseudo-class:matches(:first-child, .special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-matches-pseudo-class:matches(:first-child, .special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 22; -webkit-order: 21; -moz-box-ordinal-group: 22; @@ -428,7 +392,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 21; } -.test-not-pseudo-class:not(:first-child):not(.special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-not-pseudo-class:not(:first-child):not(.special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 23; -webkit-order: 22; -moz-box-ordinal-group: 23; @@ -436,7 +400,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 22; } -.test-any-link-pseudo-class:link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), .test-any-link-pseudo-class:visited:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), area[href].test-any-link-pseudo-class:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), .test-any-link-pseudo-class:visited:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), area[href].test-any-link-pseudo-class:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 24; -webkit-order: 23; -moz-box-ordinal-group: 24; @@ -444,18 +408,18 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 23; } -.test-any-link-pseudo-class:-webkit-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:-webkit-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 24; -webkit-order: 23; order: 23; } -.test-any-link-pseudo-class:-moz-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:-moz-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -moz-box-ordinal-group: 24; order: 23; } -.test-any-link-pseudo-class:any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 24; -webkit-order: 23; -moz-box-ordinal-group: 24; @@ -463,7 +427,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 23; } -[dir="rtl"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-dir-pseudo-class { +[dir="rtl"] .test-dir-pseudo-class:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 25; -webkit-order: 24; -moz-box-ordinal-group: 25; @@ -471,7 +435,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 24; } -.test-overflow-wrap-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-overflow-wrap-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 26; -webkit-order: 25; -moz-box-ordinal-group: 26; @@ -480,7 +444,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n word-wrap: break-word; } -.test-focus-visible-pseudo-class:focus-visible:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-focus-visible-pseudo-class:focus-visible:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 27; -webkit-order: 26; -moz-box-ordinal-group: 27; @@ -488,16 +452,16 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 26; } -.test-double-position-gradients:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-double-position-gradients:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class:blank:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-blank-pseudo-class:blank:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: yellow; } -.test-has-pseudo-class:has(.inner-class):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-has-pseudo-class:has(.inner-class):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: yellow; } @@ -533,7 +497,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 27; } -.a.c:not(#\#):not(#\#):not(#\#):not(#\#) > .b + .d { +:is(.a > .b):not(#\#):not(#\#):not(#\#):not(#\#) + :is(.c > .d) { -webkit-box-ordinal-group: 29; -webkit-order: 28; -moz-box-ordinal-group: 29; @@ -541,46 +505,46 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 28; } -.test-hwb-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-hwb-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: rgba(0, 195, 255, .5); } -.test-opacity-percent:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-opacity-percent:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { opacity: 0.42; } -.clamp-same-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.clamp-same-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { width: max(10px, min(64px, 80px)); } -.complex-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.complex-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { width: max(-webkit-calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); width: max(-moz-calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); width: max(calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); } -.clamp-different-units:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.clamp-different-units:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { width: max(10%, min(2px, 4rem)); } -.mixed-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.mixed-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { grid-template-columns: max(22rem, min(40%, 32rem)) minmax(0, 1fr); margin: max(1rem, min(2%, 3rem)) 4vh; } -.calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { margin: 0 40px 0 -webkit-calc(-1 * max(32px, min(16vw, 64px))); margin: 0 40px 0 -moz-calc(-1 * max(32px, min(16vw, 64px))); margin: 0 40px 0 calc(-1 * max(32px, min(16vw, 64px))); } -.multiple-calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.multiple-calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { margin: -webkit-calc(-1 * max(1px, min(2vw, 3px))) -webkit-calc(-1 * max(4px, min(5vw, 6px))); margin: -moz-calc(-1 * max(1px, min(2vw, 3px))) -moz-calc(-1 * max(4px, min(5vw, 6px))); margin: calc(-1 * max(1px, min(2vw, 3px))) calc(-1 * max(4px, min(5vw, 6px))); } -.nested-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.nested-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { font-size: max(max(1rem, min(2vw, 3rem)), min(4vw, 5rem)); } @@ -592,42 +556,42 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n src: url(a) format("woff2"); } -.block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: block; display: block flow; } -.block-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: flow-root; display: block flow-root; } -.inline-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline; display: inline flow; } -.inline-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline-block; display: inline flow-root; } -.run-in-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.run-in-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: run-in; display: run-in flow; } -.list-item-block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.list-item-block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: list-item; display: list-item block flow; } -.inline-flow-list-item:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flow-list-item:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline list-item; display: inline flow list-item; } -.block-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -636,7 +600,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n display: block flex; } -.inline-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: -webkit-inline-box; display: -webkit-inline-flex; display: -moz-inline-box; @@ -645,52 +609,52 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n display: inline flex; } -.block-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: grid; display: block grid; } -.inline-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline-grid; display: inline grid; } -.inline-ruby:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-ruby:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: ruby; display: inline ruby; } -.block-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: table; display: block table; } -.inline-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline-table; display: inline table; } -.table-cell-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.table-cell-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: table-cell; display: table-cell flow; } -.table-caption-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.table-caption-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: table-caption; display: table-caption flow; } -.ruby-base-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.ruby-base-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: ruby-base; display: ruby-base flow; } -.ruby-text-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.ruby-text-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: ruby-text; display: ruby-text flow; } -.color-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.color-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { prop-1: rgb(0,132,94); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; prop-3: rgba(7,3,1,1); @@ -700,7 +664,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n prop-5: rgb(255,255,255); } -.oklab:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.oklab:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color-1: rgb(73, 71, 69); color-1: color(display-p3 0.28515 0.27983 0.27246); color-2: rgba(121, 34, 67, 1); @@ -726,7 +690,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n color-12: color(display-p3 0.45207 0.66555 0.91656); } -.oklch:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.oklch:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color-1: rgb(126, 37, 15); color-1: color(display-p3 0.45368 0.16978 0.09411); color-2: rgba(126, 37, 15, 1); @@ -766,7 +730,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n color-17: oklch(60% 0.1250 0.785398unknown); } -.ic-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.ic-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --value-2ic: 'something'; text-indent: 2em; content: var(--value-2ic); @@ -780,12 +744,12 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n padding: 2 ic; } -.unset:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.unset:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { clip: auto; clip: initial; } -.mod:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.mod:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { padding: 8px 3px 1px -webkit-calc(3px + 50%); padding: 8px 3px 1px -moz-calc(3px + 50%); padding: 8px 3px 1px calc(3px + 50%); @@ -797,7 +761,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n width: 2px; } -.rem:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.rem:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { padding: 8px 3px 1px -webkit-calc(3px + 50%); padding: 8px 3px 1px -moz-calc(3px + 50%); padding: 8px 3px 1px calc(3px + 50%); @@ -808,7 +772,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n transform: rotate(-50deg); } -.round:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.round:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { top: 3px; right: 3px; bottom: 3px; diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css index 34ac7426c5..dd39a88ec1 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css @@ -1,46 +1,28 @@ + @custom-media --narrow-window (max-width: 30em); - .test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) p { - is-layer: C_D; - -webkit-box-ordinal-group: 6; - -webkit-order: 5.1; - -moz-box-ordinal-group: 6; - -ms-flex-order: 5.1; - order: 5.1; - } - -:root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + @custom-selector :--heading h1, h2, h3, h4, h5, h6;:root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; --order: 1; - } - -.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; --firebrick: rgb(179, 35, 35); - } - -@supports (color: color(display-p3 0 0 0)){ -.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }@supports (color: color(display-p3 0 0 0)){ +.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --firebrick: color(display-p3 0.64331 0.19245 0.16771); } -} - -@supports (color: lab(0% 0 0)){ -.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +}@supports (color: lab(0% 0 0)){ +.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --firebrick: lab(40% 56.6 39); } -} - -.test-custom-properties:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +}.test-custom-properties:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: var(--order); -webkit-order: var(--order); -moz-box-ordinal-group: var(--order); -ms-flex-order: var(--order); order: var(--order); - } - -.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; background-image: url(img/test.png); background-image: -webkit-image-set(url(img/test.png) 1x, url(img/test-2x.png) 2x); @@ -50,32 +32,18 @@ -moz-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; - } - -@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi){ - - .test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi){.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-image: url(img/test-2x.png); } -} - -[dir="ltr"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ +}[dir="ltr"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ margin: 1px 4px 3px 2px; -} - -.test-logical-properties-and-values:dir(ltr):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ +}.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):dir(ltr){ margin: 1px 4px 3px 2px; -} - -[dir="rtl"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-logical-properties-and-values{ +}[dir="rtl"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ margin: 1px 2px 3px 4px; -} - -.test-logical-properties-and-values:dir(rtl):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ +}.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):dir(rtl){ margin: 1px 2px 3px 4px; -} - -.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +}.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; margin: logical 1px 2px 3px 4px; -webkit-box-ordinal-group: 4; @@ -86,27 +54,21 @@ padding-top: 5px; padding-bottom: 5px; padding-block: 5px; - } - -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: 5; -webkit-order: 4; -moz-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; - } - -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) p { + }.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) p { is-layer: C; -webkit-box-ordinal-group: 6; -webkit-order: 5; -moz-box-ordinal-group: 6; -ms-flex-order: 5; - order: 5; - } - -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + order: 5 + }.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; -webkit-box-ordinal-group: 7; @@ -116,8 +78,8 @@ order: 6; } -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), -#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), +#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 8; -webkit-order: 7; -moz-box-ordinal-group: 8; @@ -125,7 +87,7 @@ order: 7; } -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p, #test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p { +.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p, #test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) + p { -webkit-box-ordinal-group: 9; -webkit-order: 8; -moz-box-ordinal-group: 9; @@ -133,8 +95,8 @@ order: 8; } -.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), -#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-nesting-rules:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), +#test-is-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 10; @@ -147,10 +109,10 @@ order: 9; } -@custom-media --narrow-window (max-width: 30em); +@custom-media --narrow-window (max-width: 500px); -@media (max-width: 30em) { - .test-custom-media-queries:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +@media (max-width: 500px) { + .test-custom-media-queries:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 11; -webkit-order: 10; -moz-box-ordinal-group: 11; @@ -160,7 +122,7 @@ } @media (--narrow-window) { - .test-custom-media-queries:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + .test-custom-media-queries:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 11; -webkit-order: 10; -moz-box-ordinal-group: 11; @@ -183,22 +145,20 @@ @custom-media --dark-mode (prefers-color-scheme: dark); @media (prefers-color-scheme: dark) { - body:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + body:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: black; color: white; } } @media (--dark-mode) { - body:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + body:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: black; color: white; } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - -h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -206,7 +166,7 @@ h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -214,7 +174,7 @@ h2.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -222,7 +182,7 @@ h3.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -230,7 +190,7 @@ h4.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -238,7 +198,7 @@ h5.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -246,7 +206,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -.test-custom-selectors:is(h1, h2, h3, h4, h5, h6):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-custom-selectors:is(h1, h2, h3, h4, h5, h6):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -254,7 +214,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -.test-custom-selectors:--heading:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-custom-selectors:--heading:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group:13; -webkit-order:12; -moz-box-ordinal-group:13; @@ -262,7 +222,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order:12; } -.test-case-insensitive-attributes[frame=hsides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=Hsides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSides]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDes]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSidEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDEs]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSideS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDeS]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSidES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIdES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSiDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hsIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HsIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=hSIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#),.test-case-insensitive-attributes[frame=HSIDES]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-case-insensitive-attributes[frame=hsides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=Hsides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSides]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDes]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSidEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDEs]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSideS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDeS]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSidES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIdES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSiDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hsIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HsIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=hSIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#,.test-case-insensitive-attributes[frame=HSIDES]:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\#:not(#\#)#\##\# { -webkit-box-ordinal-group: 14; -webkit-order: 13; -moz-box-ordinal-group: 14; @@ -270,7 +230,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 13; } -.test-rebeccapurple-color:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-rebeccapurple-color:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color: #639; color: rebeccapurple; -webkit-box-ordinal-group: 15; @@ -280,7 +240,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 14; } -.test-hexadecimal-alpha-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-hexadecimal-alpha-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: rgba(243,243,243,0.95294); background-color: #f3f3f3f3; color: rgba(0,0,0,0.2); @@ -292,7 +252,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 15; } -.test-color-functional-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-color-functional-notation:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color: rgba(178, 34, 34, 0.5); color: rgb(70% 13.5% 13.5% / 50%); -webkit-box-ordinal-group: 17; @@ -302,7 +262,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 16; } -.test-lab-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-lab-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: rgb(179, 35, 35); background-color: color(display-p3 0.64331 0.19245 0.16771); background-color: lab(40% 56.6 39); @@ -316,7 +276,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 17; } -.test-system-ui-font-family:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-system-ui-font-family:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; -webkit-box-ordinal-group: 19; -webkit-order: 18; @@ -325,7 +285,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 18; } -.test-font-variant-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-font-variant-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-font-feature-settings: "smcp"; -moz-font-feature-settings: "smcp"; font-feature-settings: "smcp"; @@ -337,7 +297,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 19; } -.test-all-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-all-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-animation: none 0s ease 0s 1 normal none running; -moz-animation: none 0s ease 0s 1 normal none running; -o-animation: none 0s ease 0s 1 normal none running; @@ -479,7 +439,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 20; } -.test-matches-pseudo-class:matches(:first-child, .special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-matches-pseudo-class:matches(:first-child, .special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 22; -webkit-order: 21; -moz-box-ordinal-group: 22; @@ -487,7 +447,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 21; } -.test-not-pseudo-class:not(:first-child):not(.special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-not-pseudo-class:not(:first-child):not(.special):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 23; -webkit-order: 22; -moz-box-ordinal-group: 23; @@ -495,7 +455,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 22; } -.test-any-link-pseudo-class:link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), .test-any-link-pseudo-class:visited:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), area[href].test-any-link-pseudo-class:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), .test-any-link-pseudo-class:visited:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), area[href].test-any-link-pseudo-class:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 24; -webkit-order: 23; -moz-box-ordinal-group: 24; @@ -503,18 +463,18 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 23; } -.test-any-link-pseudo-class:-webkit-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:-webkit-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 24; -webkit-order: 23; order: 23; } -.test-any-link-pseudo-class:-moz-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:-moz-any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -moz-box-ordinal-group: 24; order: 23; } -.test-any-link-pseudo-class:any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-any-link-pseudo-class:any-link:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 24; -webkit-order: 23; -moz-box-ordinal-group: 24; @@ -522,7 +482,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 23; } -[dir="rtl"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-dir-pseudo-class { +[dir="rtl"] .test-dir-pseudo-class:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 25; -webkit-order: 24; -moz-box-ordinal-group: 25; @@ -530,7 +490,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 24; } -.test-dir-pseudo-class:dir(rtl):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-dir-pseudo-class:dir(rtl):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 25; -webkit-order: 24; -moz-box-ordinal-group: 25; @@ -538,7 +498,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 24; } -.test-overflow-wrap-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-overflow-wrap-property:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 26; -webkit-order: 25; -moz-box-ordinal-group: 26; @@ -547,7 +507,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n word-wrap: break-word; } -.test-focus-visible-pseudo-class:focus-visible:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-focus-visible-pseudo-class:focus-visible:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { -webkit-box-ordinal-group: 27; -webkit-order: 26; -moz-box-ordinal-group: 27; @@ -555,16 +515,16 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 26; } -.test-double-position-gradients:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-double-position-gradients:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class:blank:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-blank-pseudo-class:blank:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: yellow; } -.test-has-pseudo-class:has(.inner-class):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-has-pseudo-class:has(.inner-class):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: yellow; } @@ -608,14 +568,6 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 27; } -.a.c:not(#\#):not(#\#):not(#\#):not(#\#) > .b + .d { - -webkit-box-ordinal-group: 29; - -webkit-order: 28; - -moz-box-ordinal-group: 29; - -ms-flex-order: 28; - order: 28; - } - :is(.a > .b):not(#\#):not(#\#):not(#\#):not(#\#) + :is(.c > .d) { -webkit-box-ordinal-group: 29; -webkit-order: 28; @@ -624,22 +576,22 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 28; } -.test-hwb-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-hwb-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-color: rgba(0, 195, 255, .5); background-color: hwb(194 0% 0% / .5); } -.test-opacity-percent:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-opacity-percent:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { opacity: 0.42; opacity: 42%; } -.clamp-same-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.clamp-same-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { width: max(10px, min(64px, 80px)); width: clamp(10px, 64px, 80px); } -.complex-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.complex-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { width: max(-webkit-calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); width: max(-moz-calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); width: max(calc(100% - 10px), min(min(10px, 100%), max(40px, 4em))); @@ -648,19 +600,19 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n width: clamp(calc(100% - 10px), min(10px, 100%), max(40px, 4em)); } -.clamp-different-units:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.clamp-different-units:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { width: max(10%, min(2px, 4rem)); width: clamp(10%, 2px, 4rem); } -.mixed-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.mixed-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { grid-template-columns: max(22rem, min(40%, 32rem)) minmax(0, 1fr); grid-template-columns: clamp(22rem, 40%, 32rem) minmax(0, 1fr); margin: max(1rem, min(2%, 3rem)) 4vh; margin: clamp(1rem, 2%, 3rem) 4vh; } -.calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { margin: 0 40px 0 -webkit-calc(-1 * max(32px, min(16vw, 64px))); margin: 0 40px 0 -moz-calc(-1 * max(32px, min(16vw, 64px))); margin: 0 40px 0 calc(-1 * max(32px, min(16vw, 64px))); @@ -669,7 +621,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n margin: 0 40px 0 calc(-1 * clamp(32px, 16vw, 64px)); } -.multiple-calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.multiple-calc-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { margin: -webkit-calc(-1 * max(1px, min(2vw, 3px))) -webkit-calc(-1 * max(4px, min(5vw, 6px))); margin: -moz-calc(-1 * max(1px, min(2vw, 3px))) -moz-calc(-1 * max(4px, min(5vw, 6px))); margin: calc(-1 * max(1px, min(2vw, 3px))) calc(-1 * max(4px, min(5vw, 6px))); @@ -687,7 +639,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n margin: calc(-1 * clamp(1px, 2vw, 3px)) calc(-1 * clamp(4px, 5vw, 6px)); } -.nested-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.nested-clamp:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { font-size: max(max(1rem, min(2vw, 3rem)), min(4vw, 5rem)); font-size: max(clamp(1rem, 2vw, 3rem), min(4vw, 5rem)); font-size: max(1rem, min(2vw, 3rem)); @@ -703,42 +655,42 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n src: url(a) format(woff2); } -.block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: block; display: block flow; } -.block-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: flow-root; display: block flow-root; } -.inline-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline; display: inline flow; } -.inline-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flow-root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline-block; display: inline flow-root; } -.run-in-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.run-in-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: run-in; display: run-in flow; } -.list-item-block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.list-item-block-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: list-item; display: list-item block flow; } -.inline-flow-list-item:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flow-list-item:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline list-item; display: inline flow list-item; } -.block-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -747,7 +699,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n display: block flex; } -.inline-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-flex:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: -webkit-inline-box; display: -webkit-inline-flex; display: -moz-inline-box; @@ -756,52 +708,52 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n display: inline flex; } -.block-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: grid; display: block grid; } -.inline-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-grid:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline-grid; display: inline grid; } -.inline-ruby:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-ruby:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: ruby; display: inline ruby; } -.block-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.block-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: table; display: block table; } -.inline-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.inline-table:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: inline-table; display: inline table; } -.table-cell-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.table-cell-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: table-cell; display: table-cell flow; } -.table-caption-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.table-caption-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: table-caption; display: table-caption flow; } -.ruby-base-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.ruby-base-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: ruby-base; display: ruby-base flow; } -.ruby-text-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.ruby-text-flow:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { display: ruby-text; display: ruby-text flow; } -.color-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.color-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { prop-1: rgb(0,132,94); prop-1: color(display-p3 0.00000 0.51872 0.36985); prop-2: 'color(display-p3 0.02472 0.01150 0.00574 / 1)'; @@ -817,7 +769,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n prop-5: color(display-p3 1 1 1 1); } -.oklab:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.oklab:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color-1: rgb(73, 71, 69); color-1: color(display-p3 0.28515 0.27983 0.27246); color-1: oklab(40% 0.001236 0.0039); @@ -854,7 +806,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n color-12: oklab(72.322% -0.0465 -0.1150); } -.oklch:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.oklch:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color-1: rgb(126, 37, 15); color-1: color(display-p3 0.45368 0.16978 0.09411); color-1: oklch(40% 0.1268735435 34.568626); @@ -912,7 +864,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n color-17: oklch(60% 0.1250 0.785398unknown); } -.ic-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.ic-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --value-2ic: 'something'; text-indent: 2em; text-indent: 2ic; @@ -934,12 +886,12 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n padding: 2 ic; } -.unset:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.unset:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { clip: initial; clip: unset; } -.mod:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.mod:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { padding: 8px 3px 1px -webkit-calc(3px + 50%); padding: 8px 3px 1px -moz-calc(3px + 50%); padding: 8px 3px 1px calc(3px + 50%); @@ -960,7 +912,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n width: mod(mod(-18px, 5px), 5px); } -.rem:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.rem:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { padding: 8px 3px 1px -webkit-calc(3px + 50%); padding: 8px 3px 1px -moz-calc(3px + 50%); padding: 8px 3px 1px calc(3px + 50%); @@ -979,7 +931,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n transform: rotate(rem(-140deg, -90deg)); } -.round:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.round:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { top: 3px; top: round(2.5px, 1px); right: 3px; diff --git a/plugins/postcss-cascade-layers/.tape.mjs b/plugins/postcss-cascade-layers/.tape.mjs index f7b2cc76e3..55306ba95e 100644 --- a/plugins/postcss-cascade-layers/.tape.mjs +++ b/plugins/postcss-cascade-layers/.tape.mjs @@ -24,8 +24,11 @@ postcssTape(plugin)({ 'anon-layer': { message: "supports anonymous layer usage", }, - 'examples/example': { - message: "minimal example", + 'invalid-nested-css': { + message: "ignores nested css", + }, + 'extensions': { + message: "css custom extensions", }, 'unlayered-styles': { message: 'supports unlayered styles alongside layers', @@ -64,4 +67,7 @@ postcssTape(plugin)({ 'specificity-buckets-b': { message: "creates non overlapping specificity buckets", }, + 'examples/example': { + message: "minimal example", + }, }); diff --git a/plugins/postcss-cascade-layers/CHANGELOG.md b/plugins/postcss-cascade-layers/CHANGELOG.md index bd794f6cae..35c7976e92 100644 --- a/plugins/postcss-cascade-layers/CHANGELOG.md +++ b/plugins/postcss-cascade-layers/CHANGELOG.md @@ -1,5 +1,10 @@ # Changes to PostCSS Cascade Layers +### Unreleased (major) + +- Run `postcss-cascade-layers` early compared to other PostCSS plugins (breaking) +- Fix broken `@keyframes` in `@layer` + ### 1.0.5 (July 8, 2022) - Fix case insensitive `@layer` matching (`@LaYeR`). diff --git a/plugins/postcss-cascade-layers/src/constants.ts b/plugins/postcss-cascade-layers/src/constants.ts index 70cea3be72..ddf3bcecfb 100644 --- a/plugins/postcss-cascade-layers/src/constants.ts +++ b/plugins/postcss-cascade-layers/src/constants.ts @@ -9,6 +9,7 @@ export const IMPLICIT_LAYER_SUFFIX = 'b147acf6-11a6-4338-a4d0-80aef4cd1a2f'; export const CONDITIONAL_ATRULES = [ 'media', 'supports', + 'container', ]; export const ATRULES_WITH_NON_SELECTOR_BLOCK_LISTS = [ diff --git a/plugins/postcss-cascade-layers/src/desugar-and-parse-layer-names.ts b/plugins/postcss-cascade-layers/src/desugar-and-parse-layer-names.ts index 36d34f22af..ab6734af81 100644 --- a/plugins/postcss-cascade-layers/src/desugar-and-parse-layer-names.ts +++ b/plugins/postcss-cascade-layers/src/desugar-and-parse-layer-names.ts @@ -1,17 +1,18 @@ import type { Container } from 'postcss'; import type { Model } from './model'; import selectorParser from 'postcss-selector-parser'; -import { INVALID_LAYER_NAME } from './constants'; +import { CONDITIONAL_ATRULES, INVALID_LAYER_NAME } from './constants'; import { someAtRuleInTree, someInTree } from './some-in-tree'; import { getLayerAtRuleAncestor } from './get-layer-atrule-ancestor'; import { removeEmptyAncestorBlocks, removeEmptyDescendantBlocks } from './clean-blocks'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; export function desugarAndParseLayerNames(root: Container, model: Model) { // - parse layer names // - rename anon layers // - handle empty layers root.walkAtRules((layerRule) => { - if (layerRule.name.toLowerCase() !== 'layer') { + if (!isProcessableLayerRule(layerRule)) { return; } @@ -90,7 +91,7 @@ export function desugarAndParseLayerNames(root: Container, model: Model) { layerRule.params = model.createAnonymousLayerName(); } - const hasNestedLayers = someAtRuleInTree(layerRule, (node) => node.name.toLowerCase() === 'layer'); + const hasNestedLayers = someAtRuleInTree(layerRule, (node) => isProcessableLayerRule(node)); const hasUnlayeredStyles = someInTree(layerRule, (node) => { if (node.type !== 'rule') { return; @@ -109,7 +110,7 @@ export function desugarAndParseLayerNames(root: Container, model: Model) { // only keep unlayered styles for the implicit layer. implicitLayer.walkAtRules((node) => { - if (node.name.toLowerCase() !== 'layer') { + if (!isProcessableLayerRule(node)) { return; } @@ -118,7 +119,11 @@ export function desugarAndParseLayerNames(root: Container, model: Model) { // go through the unlayered rules and delete these from top level atRule layerRule.walk((node) => { - if (node.type !== 'rule') { + if (node.type === 'atrule' && isProcessableLayerRule(node)) { + return; + } + + if (node.type === 'atrule' && CONDITIONAL_ATRULES.includes(node.name.toLowerCase())) { return; } diff --git a/plugins/postcss-cascade-layers/src/desugar-nested-layers.ts b/plugins/postcss-cascade-layers/src/desugar-nested-layers.ts index 85ea28d440..67e540fdc3 100644 --- a/plugins/postcss-cascade-layers/src/desugar-nested-layers.ts +++ b/plugins/postcss-cascade-layers/src/desugar-nested-layers.ts @@ -1,18 +1,19 @@ import type { Container, AtRule, ChildNode } from 'postcss'; import { removeEmptyAncestorBlocks, removeEmptyDescendantBlocks } from './clean-blocks'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; import type { Model } from './model'; import { someAtRuleInTree } from './some-in-tree'; export function desugarNestedLayers(root: Container, model: Model) { while (someAtRuleInTree(root, (node) => { return node.nodes && someAtRuleInTree(node, (nested) => { - return nested.name.toLowerCase() === 'layer'; + return isProcessableLayerRule(nested); }); })) { let foundUnexpectedLayerNesting = false; root.walkAtRules((layerRule) => { - if (layerRule.name.toLowerCase() !== 'layer') { + if (!isProcessableLayerRule(layerRule)) { return; } @@ -20,7 +21,7 @@ export function desugarNestedLayers(root: Container, model: Model) { return; } - if (layerRule.parent.type === 'atrule' && (layerRule.parent as AtRule).name.toLowerCase() === 'layer') { + if (layerRule.parent.type === 'atrule' && isProcessableLayerRule(layerRule.parent as AtRule)) { const parent = layerRule.parent as AtRule; // Concatenate the current layer params with those of the parent. Store the result in the data model. diff --git a/plugins/postcss-cascade-layers/src/get-layer-atrule-ancestor.ts b/plugins/postcss-cascade-layers/src/get-layer-atrule-ancestor.ts index 26f0e81e87..8bbe7a141c 100644 --- a/plugins/postcss-cascade-layers/src/get-layer-atrule-ancestor.ts +++ b/plugins/postcss-cascade-layers/src/get-layer-atrule-ancestor.ts @@ -1,4 +1,5 @@ import type { AtRule, Node } from 'postcss'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; // Returns the first ancestor of the current node that is an @layer rule. export function getLayerAtRuleAncestor(node: Node): AtRule | null { @@ -9,7 +10,7 @@ export function getLayerAtRuleAncestor(node: Node): AtRule | null { continue; } - if ((parent as AtRule).name.toLowerCase() === 'layer') { + if (isProcessableLayerRule(parent as AtRule)) { return parent as AtRule; } diff --git a/plugins/postcss-cascade-layers/src/index.ts b/plugins/postcss-cascade-layers/src/index.ts index 8e0292b829..46112b2178 100644 --- a/plugins/postcss-cascade-layers/src/index.ts +++ b/plugins/postcss-cascade-layers/src/index.ts @@ -12,6 +12,7 @@ import { recordLayerOrder } from './record-layer-order'; import { ATRULES_WITH_NON_SELECTOR_BLOCK_LISTS, INVALID_LAYER_NAME } from './constants'; import { splitImportantStyles } from './split-important-styles'; import { pluginOptions } from './options'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; const creator: PluginCreator = (opts?: pluginOptions) => { const options = Object.assign({ @@ -22,7 +23,7 @@ const creator: PluginCreator = (opts?: pluginOptions) => { return { postcssPlugin: 'postcss-cascade-layers', - OnceExit(root: Container, { result }: { result: Result }) { + Once(root: Container, { result }: { result: Result }) { // Warnings if (options.onRevertLayerKeyword) { @@ -135,9 +136,9 @@ const creator: PluginCreator = (opts?: pluginOptions) => { // Remove all @layer at-rules // Contained styles are inserted before - while (someAtRuleInTree(root, (node) => node.name.toLowerCase() === 'layer')) { + while (someAtRuleInTree(root, (node) => isProcessableLayerRule(node))) { root.walkAtRules((atRule) => { - if (atRule.name.toLowerCase() !== 'layer') { + if (!isProcessableLayerRule(atRule)) { return; } diff --git a/plugins/postcss-cascade-layers/src/is-processable-layer-rule.ts b/plugins/postcss-cascade-layers/src/is-processable-layer-rule.ts new file mode 100644 index 0000000000..5b42e028d4 --- /dev/null +++ b/plugins/postcss-cascade-layers/src/is-processable-layer-rule.ts @@ -0,0 +1,28 @@ +import type { AtRule, ChildNode, Container, Document } from 'postcss'; + +const allowedParentAtRules = new Set(['layer', 'supports', 'media']); + +export function isProcessableLayerRule(atRule: AtRule): boolean { + if (atRule.type !== 'atrule') { + return false; + } + + if (atRule.name.toLowerCase() !== 'layer') { + return false; + } + + let parent : Container|Document = atRule.parent; + while (parent) { + if (parent.type === 'rule') { + return false; + } + + if (parent.type === 'atrule' && !allowedParentAtRules.has((parent as AtRule).name.toLowerCase())) { + return false; + } + + parent = parent.parent; + } + + return true; +} diff --git a/plugins/postcss-cascade-layers/src/model.ts b/plugins/postcss-cascade-layers/src/model.ts index bed9874601..41b761e5a0 100644 --- a/plugins/postcss-cascade-layers/src/model.ts +++ b/plugins/postcss-cascade-layers/src/model.ts @@ -1,5 +1,6 @@ import type { AtRule, Node } from 'postcss'; import { ANONYMOUS_LAYER_SUFFIX, IMPLICIT_LAYER_SUFFIX } from './constants'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; export class Model { anonymousLayerCount = 0; @@ -79,7 +80,7 @@ export class Model { continue; } - if ((parent as AtRule).name.toLowerCase() === 'layer') { + if (isProcessableLayerRule(parent as AtRule)) { params.push(...this.layerParamsParsed.get((parent as AtRule).params)); } diff --git a/plugins/postcss-cascade-layers/src/record-layer-order.ts b/plugins/postcss-cascade-layers/src/record-layer-order.ts index 36a54723df..058c939fd2 100644 --- a/plugins/postcss-cascade-layers/src/record-layer-order.ts +++ b/plugins/postcss-cascade-layers/src/record-layer-order.ts @@ -1,13 +1,14 @@ import type { Container, Result } from 'postcss'; import { ANONYMOUS_LAYER_SUFFIX, IMPLICIT_LAYER_SUFFIX } from './constants'; import { getConditionalAtRuleAncestor } from './get-conditional-atrule-ancestor'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; import type { Model } from './model'; import { pluginOptions } from './options'; export function recordLayerOrder(root: Container, model: Model, { result, options }: { result: Result, options: pluginOptions }) { // record layer order root.walkAtRules((layerRule) => { - if (layerRule.name.toLowerCase() !== 'layer') { + if (!isProcessableLayerRule(layerRule)) { return; } diff --git a/plugins/postcss-cascade-layers/src/sort-root-nodes.ts b/plugins/postcss-cascade-layers/src/sort-root-nodes.ts index 8ad77c4fec..c75f08301f 100644 --- a/plugins/postcss-cascade-layers/src/sort-root-nodes.ts +++ b/plugins/postcss-cascade-layers/src/sort-root-nodes.ts @@ -3,13 +3,14 @@ import type { Model } from './model'; import { ATRULES_WITH_NON_SELECTOR_BLOCK_LISTS, CONDITIONAL_ATRULES, WITH_SELECTORS_LAYER_NAME } from './constants'; import { someInTree } from './some-in-tree'; import { removeEmptyAncestorBlocks, removeEmptyDescendantBlocks } from './clean-blocks'; +import { isProcessableLayerRule } from './is-processable-layer-rule'; // Sort root nodes to apply the preferred order by layer priority for non-selector rules. // Selector rules are adjusted by specificity. export function sortRootNodes(root: Container, model: Model) { // Separate selector rules from other rules root.walkAtRules((layerRule) => { - if (layerRule.name.toLowerCase() !== 'layer') { + if (!isProcessableLayerRule(layerRule)) { return; } @@ -70,22 +71,6 @@ export function sortRootNodes(root: Container, model: Model) { }); root.nodes.sort((a, b) => { - const aIsCharset = a.type === 'atrule' && a.name.toLowerCase() === 'charset'; - const bIsCharset = b.type === 'atrule' && b.name.toLowerCase() === 'charset'; - if (aIsCharset && bIsCharset) { - return 0; - } else if (aIsCharset !== bIsCharset) { - return aIsCharset ? -1 : 1; - } - - const aIsImport = a.type === 'atrule' && a.name.toLowerCase() === 'import'; - const bIsImport = b.type === 'atrule' && b.name.toLowerCase() === 'import'; - if (aIsImport && bIsImport) { - return 0; - } else if (aIsImport !== bIsImport) { - return aIsImport ? -1 : 1; - } - const aIsLayer = a.type === 'atrule' && a.name.toLowerCase() === 'layer'; const bIsLayer = b.type === 'atrule' && b.name.toLowerCase() === 'layer'; if (aIsLayer && bIsLayer) { diff --git a/plugins/postcss-cascade-layers/test/extensions.css b/plugins/postcss-cascade-layers/test/extensions.css new file mode 100644 index 0000000000..11e13b8466 --- /dev/null +++ b/plugins/postcss-cascade-layers/test/extensions.css @@ -0,0 +1,23 @@ +/* We expect unlayered extensions to appear later so that they override layered extensions */ + +@custom-media --custom-media-query: unlayered; + +@custom-selector --custom-selector: #unlayered; + +@property --property { + syntax: ''; + inherits: false; + initial-value: unlayered; +} + +@layer A { + @custom-media --custom-media-query: layered; + + @custom-selector --custom-selector: #layered; + + @property --property { + syntax: ''; + inherits: false; + initial-value: layered; + } +} diff --git a/plugins/postcss-cascade-layers/test/extensions.expect.css b/plugins/postcss-cascade-layers/test/extensions.expect.css new file mode 100644 index 0000000000..ff6d2b89b1 --- /dev/null +++ b/plugins/postcss-cascade-layers/test/extensions.expect.css @@ -0,0 +1,20 @@ + + @custom-media --custom-media-query: layered; + + @custom-selector --custom-selector: #layered; + + @property --property { + syntax: ''; + inherits: false; + initial-value: layered; + }/* We expect unlayered extensions to appear later so that they override layered extensions */ + +@custom-media --custom-media-query: unlayered; + +@custom-selector --custom-selector: #unlayered; + +@property --property { + syntax: ''; + inherits: false; + initial-value: unlayered; +} diff --git a/plugins/postcss-cascade-layers/test/invalid-nested-css.css b/plugins/postcss-cascade-layers/test/invalid-nested-css.css new file mode 100644 index 0000000000..98c291e2d5 --- /dev/null +++ b/plugins/postcss-cascade-layers/test/invalid-nested-css.css @@ -0,0 +1,14 @@ +.unlayered { + contain: layout inline-size; +} + +.partially-layered { + background-color: blue; + height: 100px; + width: 100px; + + @layer A { + /* Only conditional rules are allowed to be nested */ + background-color: red; + } +} diff --git a/plugins/postcss-cascade-layers/test/invalid-nested-css.expect.css b/plugins/postcss-cascade-layers/test/invalid-nested-css.expect.css new file mode 100644 index 0000000000..98c291e2d5 --- /dev/null +++ b/plugins/postcss-cascade-layers/test/invalid-nested-css.expect.css @@ -0,0 +1,14 @@ +.unlayered { + contain: layout inline-size; +} + +.partially-layered { + background-color: blue; + height: 100px; + width: 100px; + + @layer A { + /* Only conditional rules are allowed to be nested */ + background-color: red; + } +} diff --git a/plugins/postcss-cascade-layers/test/nested-case-insensitive.expect.css b/plugins/postcss-cascade-layers/test/nested-case-insensitive.expect.css index 08951e228b..479aaaf1e4 100644 --- a/plugins/postcss-cascade-layers/test/nested-case-insensitive.expect.css +++ b/plugins/postcss-cascade-layers/test/nested-case-insensitive.expect.css @@ -9,9 +9,6 @@ } } -@KEYFRAMES slide-left { - } - target { color: yellow; } diff --git a/plugins/postcss-cascade-layers/test/nested-complex.css b/plugins/postcss-cascade-layers/test/nested-complex.css index 8e87cff03a..ce6fbcfbf6 100644 --- a/plugins/postcss-cascade-layers/test/nested-complex.css +++ b/plugins/postcss-cascade-layers/test/nested-complex.css @@ -10,6 +10,12 @@ order: 2; } } + + @container (min-width: 700px) { + target { + order: 2.1; + } + } } @media screen { @@ -18,6 +24,13 @@ order: 3; } + @container (min-width: 701px) { + target { + layered: no; + order: 3.1; + } + } + @layer E { target { order: 4; diff --git a/plugins/postcss-cascade-layers/test/nested-complex.expect.css b/plugins/postcss-cascade-layers/test/nested-complex.expect.css index 0e3f84e5d1..c58fac0341 100644 --- a/plugins/postcss-cascade-layers/test/nested-complex.expect.css +++ b/plugins/postcss-cascade-layers/test/nested-complex.expect.css @@ -9,6 +9,12 @@ } } + @container (min-width: 700px) { + target { + order: 2.1; + } + } + @media screen { target:not(#\#) { order: 4; @@ -20,6 +26,13 @@ layered: no; order: 3; } + + @container (min-width: 701px) { + target:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + layered: no; + order: 3.1; + } + } } @media screen { diff --git a/plugins/postcss-cascade-layers/test/nested.css b/plugins/postcss-cascade-layers/test/nested.css index b6363946b1..477ce741c1 100644 --- a/plugins/postcss-cascade-layers/test/nested.css +++ b/plugins/postcss-cascade-layers/test/nested.css @@ -1,3 +1,9 @@ +@font-face { + font-family: "Open Sans"; + src: url("/fonts/OpenSans-Regular-webfont.woff2#unlayered") format("woff2"), + url("/fonts/OpenSans-Regular-webfont.woff#unlayered") format("woff"); +} + @layer A { target { color: red; @@ -29,6 +35,12 @@ } } + @font-face { + font-family: "Open Sans"; + src: url("/fonts/OpenSans-Regular-webfont.woff2#layered") format("woff2"), + url("/fonts/OpenSans-Regular-webfont.woff#layered") format("woff"); + } + @layer Z { target { color: yellow; @@ -43,8 +55,12 @@ } } + h1 { + color: pink; + } + @media (prefers-color-scheme: dark) { - h1 { + h2 { color: red; background: black; } diff --git a/plugins/postcss-cascade-layers/test/nested.expect.css b/plugins/postcss-cascade-layers/test/nested.expect.css index 777ffc2e03..fa78ccfa39 100644 --- a/plugins/postcss-cascade-layers/test/nested.expect.css +++ b/plugins/postcss-cascade-layers/test/nested.expect.css @@ -9,10 +9,17 @@ } } -@keyframes slide-left { - } + @font-face { + font-family: "Open Sans"; + src: url("/fonts/OpenSans-Regular-webfont.woff2#layered") format("woff2"), + url("/fonts/OpenSans-Regular-webfont.woff#layered") format("woff"); + }@font-face { + font-family: "Open Sans"; + src: url("/fonts/OpenSans-Regular-webfont.woff2#unlayered") format("woff2"), + url("/fonts/OpenSans-Regular-webfont.woff#unlayered") format("woff"); +} - target { +target { color: yellow; } @@ -36,8 +43,12 @@ target:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color: yellow; } +h1:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + color: pink; + } + @media (prefers-color-scheme: dark) { - h1:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + h2:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { color: red; background: black; } diff --git a/plugins/postcss-cascade-layers/test/warnings.expect.css b/plugins/postcss-cascade-layers/test/warnings.expect.css index 5f63c90626..d6bb4b8743 100644 --- a/plugins/postcss-cascade-layers/test/warnings.expect.css +++ b/plugins/postcss-cascade-layers/test/warnings.expect.css @@ -1,5 +1,5 @@ - -@import 'imports/theme.css' layer(utilities);/* [postcss-cascade-layers]: To use the @import at-rule with layer, the postcss-import plugin is also required. This plugin alone will not support importing layers. */ +/* [postcss-cascade-layers]: To use the @import at-rule with layer, the postcss-import plugin is also required. This plugin alone will not support importing layers. */ +@import 'imports/theme.css' layer(utilities); /* [postcss-cascade-layers]: handling "revert-layer" is unsupported by this plugin and will cause style differences between browser versions. */ .foo { diff --git a/plugins/postcss-custom-media/README.md b/plugins/postcss-custom-media/README.md index 73437387f8..e847e2fbaa 100644 --- a/plugins/postcss-custom-media/README.md +++ b/plugins/postcss-custom-media/README.md @@ -74,90 +74,6 @@ postcssCustomMedia({ preserve: true }) } ``` - -### importFrom - -The `importFrom` option specifies sources where custom media can be imported -from, which might be CSS, JS, and JSON files, functions, and directly passed -objects. - -```js -postcssCustomMedia({ - importFrom: 'path/to/file.css' // => @custom-selector --small-viewport (max-width: 30em); -}); -``` - -```pcss -@media (max-width: 30em) { - /* styles for small viewport */ -} - -@media (--small-viewport) { - /* styles for small viewport */ -} -``` - -Multiple sources can be passed into this option, and they will be parsed in the -order they are received. JavaScript files, JSON files, functions, and objects -will need to namespace custom media using the `customMedia` or -`custom-media` key. - -```js -postcssCustomMedia({ - importFrom: [ - 'path/to/file.css', - 'and/then/this.js', - 'and/then/that.json', - { - customMedia: { '--small-viewport': '(max-width: 30em)' } - }, - () => { - const customMedia = { '--small-viewport': '(max-width: 30em)' }; - - return { customMedia }; - } - ] -}); -``` - -### exportTo - -The `exportTo` option specifies destinations where custom media can be exported -to, which might be CSS, JS, and JSON files, functions, and directly passed -objects. - -```js -postcssCustomMedia({ - exportTo: 'path/to/file.css' // @custom-media --small-viewport (max-width: 30em); -}); -``` - -Multiple destinations can be passed into this option, and they will be parsed -in the order they are received. JavaScript files, JSON files, and objects will -need to namespace custom media using the `customMedia` or -`custom-media` key. - -```js -const cachedObject = { customMedia: {} }; - -postcssCustomMedia({ - exportTo: [ - 'path/to/file.css', // @custom-media --small-viewport (max-width: 30em); - 'and/then/this.js', // module.exports = { customMedia: { '--small-viewport': '(max-width: 30em)' } } - 'and/then/this.mjs', // export const customMedia = { '--small-viewport': '(max-width: 30em)' } } - 'and/then/that.json', // { "custom-media": { "--small-viewport": "(max-width: 30em)" } } - cachedObject, - customMedia => { - customMedia // { '--small-viewport': '(max-width: 30em)' } - } - ] -}); -``` - -See example exports written to [CSS](test/export-media.css), -[JS](test/export-media.js), [MJS](test/export-media.mjs), and -[JSON](test/export-media.json). - [cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test [css-url]: https://cssdb.org/#custom-media-queries [discord]: https://discord.gg/bUadyRwkJS diff --git a/plugins/postcss-custom-media/docs/README.md b/plugins/postcss-custom-media/docs/README.md index 9961d39fd4..6d3d8dc767 100644 --- a/plugins/postcss-custom-media/docs/README.md +++ b/plugins/postcss-custom-media/docs/README.md @@ -49,89 +49,5 @@ is preserved. By default, it is not preserved. ``` - -### importFrom - -The `importFrom` option specifies sources where custom media can be imported -from, which might be CSS, JS, and JSON files, functions, and directly passed -objects. - -```js -({ - importFrom: 'path/to/file.css' // => @custom-selector --small-viewport (max-width: 30em); -}); -``` - -```pcss -@media (max-width: 30em) { - /* styles for small viewport */ -} - -@media (--small-viewport) { - /* styles for small viewport */ -} -``` - -Multiple sources can be passed into this option, and they will be parsed in the -order they are received. JavaScript files, JSON files, functions, and objects -will need to namespace custom media using the `customMedia` or -`custom-media` key. - -```js -({ - importFrom: [ - 'path/to/file.css', - 'and/then/this.js', - 'and/then/that.json', - { - customMedia: { '--small-viewport': '(max-width: 30em)' } - }, - () => { - const customMedia = { '--small-viewport': '(max-width: 30em)' }; - - return { customMedia }; - } - ] -}); -``` - -### exportTo - -The `exportTo` option specifies destinations where custom media can be exported -to, which might be CSS, JS, and JSON files, functions, and directly passed -objects. - -```js -({ - exportTo: 'path/to/file.css' // @custom-media --small-viewport (max-width: 30em); -}); -``` - -Multiple destinations can be passed into this option, and they will be parsed -in the order they are received. JavaScript files, JSON files, and objects will -need to namespace custom media using the `customMedia` or -`custom-media` key. - -```js -const cachedObject = { customMedia: {} }; - -({ - exportTo: [ - 'path/to/file.css', // @custom-media --small-viewport (max-width: 30em); - 'and/then/this.js', // module.exports = { customMedia: { '--small-viewport': '(max-width: 30em)' } } - 'and/then/this.mjs', // export const customMedia = { '--small-viewport': '(max-width: 30em)' } } - 'and/then/that.json', // { "custom-media": { "--small-viewport": "(max-width: 30em)" } } - cachedObject, - customMedia => { - customMedia // { '--small-viewport': '(max-width: 30em)' } - } - ] -}); -``` - -See example exports written to [CSS](test/export-media.css), -[JS](test/export-media.js), [MJS](test/export-media.mjs), and -[JSON](test/export-media.json). - [Custom Media Specification]: diff --git a/plugins/postcss-custom-media/src/custom-media-from-root.js b/plugins/postcss-custom-media/src/custom-media-from-root.js index d2ddbef6a3..f1c0f06935 100644 --- a/plugins/postcss-custom-media/src/custom-media-from-root.js +++ b/plugins/postcss-custom-media/src/custom-media-from-root.js @@ -4,7 +4,7 @@ import valueParser from 'postcss-value-parser'; // return custom selectors from the css root, conditionally removing them export default (root, opts) => { // initialize custom selectors - const customMedias = {}; + const customMedias = new Map(); // for each custom selector atrule that is a child of the css root root.nodes.slice().forEach(node => { @@ -50,7 +50,7 @@ export default (root, opts) => { const selectors = valueParser.stringify(paramsAst.nodes.slice(nameNodeIndex + 1)).trim(); // write the parsed selectors to the custom selector - customMedias[name] = mediaASTFromString(selectors); + customMedias.set(name, mediaASTFromString(selectors)); // conditionally remove the custom selector atrule if (!Object(opts).preserve) { diff --git a/plugins/postcss-custom-media/src/index.js b/plugins/postcss-custom-media/src/index.js index 78d2136796..3a9e6a7640 100644 --- a/plugins/postcss-custom-media/src/index.js +++ b/plugins/postcss-custom-media/src/index.js @@ -1,25 +1,28 @@ import getCustomMediaFromRoot from './custom-media-from-root'; -import transformAtrules from './transform-atrules'; +import transformAtRules from './transform-atrules'; const creator = opts => { // whether to preserve custom media and at-rules using them const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : false; - const customMediaHelperKey = Symbol('customMediaHelper'); - return { postcssPlugin: 'postcss-custom-media', - Once: async (root, helpers) => { + prepare() { + let customMedia = new Map(); - // combine rules from root and from imports - helpers[customMediaHelperKey] = getCustomMediaFromRoot(root, { preserve }); - }, - AtRule: (atrule, helpers) => { - if (atrule.name !== 'media') { - return; - } + return { + Once: (root) => { + // combine rules from root and from imports + customMedia = getCustomMediaFromRoot(root, { preserve: preserve }); + }, + AtRule: (atrule) => { + if (atrule.name.toLowerCase() !== 'media') { + return; + } - transformAtrules(atrule, helpers[customMediaHelperKey], { preserve }); + transformAtRules(atrule, customMedia, { preserve: preserve }); + }, + }; }, }; }; diff --git a/plugins/postcss-custom-media/src/transform-media-list.js b/plugins/postcss-custom-media/src/transform-media-list.js index 2eed88fdb0..e6180cf0b0 100644 --- a/plugins/postcss-custom-media/src/transform-media-list.js +++ b/plugins/postcss-custom-media/src/transform-media-list.js @@ -24,8 +24,8 @@ function transformMedia(media, customMedias) { for (const index in media.nodes) { const { value, nodes } = media.nodes[index]; const key = getCustomMediaNameReference(value); - if (key && (key in customMedias)) { - for (const replacementMedia of customMedias[key].nodes) { + if (key && customMedias.has(key)) { + for (const replacementMedia of customMedias.get(key).nodes) { // use the first available modifier unless they cancel each other out const modifier = media.modifier !== replacementMedia.modifier ? media.modifier || replacementMedia.modifier @@ -80,9 +80,8 @@ function transformMedia(media, customMedias) { } const getCustomMediasWithoutKey = (customMedias, key) => { - const nextCustomMedias = Object.assign({}, customMedias); - - delete nextCustomMedias[key]; + const nextCustomMedias = new Map(customMedias); + nextCustomMedias.delete(key); return nextCustomMedias; }; diff --git a/plugins/postcss-custom-media/test/basic.css b/plugins/postcss-custom-media/test/basic.css index a992cfe2ff..6b60b60a52 100644 --- a/plugins/postcss-custom-media/test/basic.css +++ b/plugins/postcss-custom-media/test/basic.css @@ -130,3 +130,27 @@ } @custom-media trailer-- (min-width: 320px); + +/* Handled incorrectly : */ +@custom-media --truthy true; +/* Handled incorrectly : */ +@custom-media --falsy false; + +@media screen or (--truthy) { + body { + order: 1007; + } +} + +@media screen and (--falsy) { + body { + order: 1008; + } +} + +/* Handled incorrectly : */ +@custom-media --modern (color), (hover); + +@media (--modern) and (width > 1024px) { + .a { color: green; } +} diff --git a/plugins/postcss-custom-media/test/basic.expect.css b/plugins/postcss-custom-media/test/basic.expect.css index ed797941cc..efbd1a2145 100644 --- a/plugins/postcss-custom-media/test/basic.expect.css +++ b/plugins/postcss-custom-media/test/basic.expect.css @@ -115,3 +115,24 @@ } @custom-media trailer-- (min-width: 320px); + +/* Handled incorrectly : */ +/* Handled incorrectly : */ + +@media screen or (--truthy) { + body { + order: 1007; + } +} + +@media screen and false { + body { + order: 1008; + } +} + +/* Handled incorrectly : */ + +@media (color) and (width > 1024px),(hover) and (width > 1024px) { + .a { color: green; } +} diff --git a/plugins/postcss-custom-media/test/basic.preserve.expect.css b/plugins/postcss-custom-media/test/basic.preserve.expect.css index 4c8aefc634..50951ef66e 100644 --- a/plugins/postcss-custom-media/test/basic.preserve.expect.css +++ b/plugins/postcss-custom-media/test/basic.preserve.expect.css @@ -222,3 +222,37 @@ } @custom-media trailer-- (min-width: 320px); + +/* Handled incorrectly : */ +@custom-media --truthy true; +/* Handled incorrectly : */ +@custom-media --falsy false; + +@media screen or (--truthy) { + body { + order: 1007; + } +} + +@media screen and false { + body { + order: 1008; + } +} + +@media screen and (--falsy) { + body { + order: 1008; + } +} + +/* Handled incorrectly : */ +@custom-media --modern (color), (hover); + +@media (color) and (width > 1024px),(hover) and (width > 1024px) { + .a { color: green; } +} + +@media (--modern) and (width > 1024px) { + .a { color: green; } +} diff --git a/plugins/postcss-custom-properties/README.md b/plugins/postcss-custom-properties/README.md index ab48d6d96d..9decb1707b 100644 --- a/plugins/postcss-custom-properties/README.md +++ b/plugins/postcss-custom-properties/README.md @@ -12,26 +12,26 @@ the [CSS Custom Properties] specification. ```pcss :root { - --color: red; + --color: red; } h1 { - color: var(--color); + color: var(--color); } /* becomes */ :root { - --color: red; + --color: red; } h1 { - color: red; - color: var(--color); + color: red; + color: var(--color); } ``` -**Note:** This plugin only processes variables that are defined in the `:root` selector. +**Note:** This plugin only processes variables that are defined in the `:root` or `html` selector. ## Usage @@ -48,7 +48,7 @@ const postcss = require('postcss'); const postcssCustomProperties = require('postcss-custom-properties'); postcss([ - postcssCustomProperties(/* pluginOptions */) + postcssCustomProperties(/* pluginOptions */) ]).process(YOUR_CSS /*, processOptions */); ``` @@ -61,138 +61,37 @@ postcss([ ### preserve -The `preserve` option determines whether Custom Properties and properties using -custom properties should be preserved in their original form. By default, both -of these are preserved. +The `preserve` option determines whether properties using +custom properties should be preserved in their original form. By default these are preserved. ```js postcssCustomProperties({ - preserve: false + preserve: false }); ``` ```pcss :root { - --color: red; + --color: red; } h1 { - color: var(--color); + color: var(--color); } /* becomes */ -h1 { - color: red; -} -``` - -### importFrom - -The `importFrom` option specifies sources where Custom Properties can be imported -from, which might be CSS, JS, and JSON files, functions, and directly passed -objects. - -```js -postcssCustomProperties({ - importFrom: 'path/to/file.css' // => :root { --color: red } -}); -``` - -```pcss -h1 { - color: var(--color); +:root { + --color: red; } -/* becomes */ - h1 { - color: red; + color: red; } ``` -Multiple sources can be passed into this option, and they will be parsed in the -order they are received. JavaScript files, JSON files, functions, and objects -will need to namespace Custom Properties using the `customProperties` or -`custom-properties` key. - -```js -postcssCustomProperties({ - importFrom: [ - 'path/to/file.css', // :root { --color: red; } - 'and/then/this.js', // module.exports = { customProperties: { '--color': 'red' } } - 'and/then/that.json', // { "custom-properties": { "--color": "red" } } - { - customProperties: { '--color': 'red' } - }, - () => { - const customProperties = { '--color': 'red' }; - - return { customProperties }; - } - ] -}); -``` - -See example imports written in [CSS](test/import-properties.css), -[JS](test/import-properties.js), and [JSON](test/import-properties.json). - -### overrideImportFromWithRoot - -The `overrideImportFromWithRoot` option determines if properties added via `importFrom` are overridden by properties that exist in `:root`. -Defaults to `false`. - -```js -postcssCustomProperties({ - overrideImportFromWithRoot: true -}); -``` - -### exportTo - -The `exportTo` option specifies destinations where Custom Properties can be exported -to, which might be CSS, JS, and JSON files, functions, and directly passed -objects. - -```js -postcssCustomProperties({ - exportTo: 'path/to/file.css' // :root { --color: red; } -}); -``` - -Multiple destinations can be passed into this option, and they will be parsed -in the order they are received. JavaScript files, JSON files, and objects will -need to namespace Custom Properties using the `customProperties` or -`custom-properties` key. - -```js -const cachedObject = { customProperties: {} }; - -postcssCustomProperties({ - exportTo: [ - 'path/to/file.css', // :root { --color: red; } - 'and/then/this.js', // module.exports = { customProperties: { '--color': 'red' } } - 'and/then/this.mjs', // export const customProperties = { '--color': 'red' } } - 'and/then/that.json', // { "custom-properties": { "--color": "red" } } - 'and/then/that.scss', // $color: red; - cachedObject, - customProperties => { - customProperties // { '--color': 'red' } - } - ] -}); -``` - -See example exports written to [CSS](test/export-properties.css), -[JS](test/export-properties.js), [MJS](test/export-properties.mjs), -[JSON](test/export-properties.json) and [SCSS](test/export-properties.scss). - -### disableDeprecationNotice - -Silence the deprecation notice that is printed to the console when using `importFrom` or `exportTo`. - -> "importFrom" and "exportTo" will be removed in a future version of postcss-custom-properties. -> Check the discussion on github for more details. https://github.com/csstools/postcss-plugins/discussions/192 +No Custom Properties will be removed from `:root` or `html` even when `preserve` is false. +It is impossible to know if a Custom Property is truly unused or only unused in the current stylesheet. [cli-img]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml/badge.svg [cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test diff --git a/plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts b/plugins/postcss-custom-properties/src/get-custom-properties-from-root.ts similarity index 100% rename from plugins/postcss-custom-properties/src/lib/get-custom-properties-from-root.ts rename to plugins/postcss-custom-properties/src/get-custom-properties-from-root.ts diff --git a/plugins/postcss-custom-properties/src/index.ts b/plugins/postcss-custom-properties/src/index.ts index 9e54f98317..62ecbb6f1e 100644 --- a/plugins/postcss-custom-properties/src/index.ts +++ b/plugins/postcss-custom-properties/src/index.ts @@ -1,29 +1,30 @@ import type { PluginCreator } from 'postcss'; import type valuesParser from 'postcss-value-parser'; -import getCustomPropertiesFromRoot from './lib/get-custom-properties-from-root'; -import transformProperties from './lib/transform-properties'; +import getCustomPropertiesFromRoot from './get-custom-properties-from-root'; +import transformProperties from './transform-properties'; export interface PluginOptions { - /** Determines whether Custom Properties and properties using custom properties should be preserved in their original form. */ + /** Determines whether properties using custom properties should be preserved in their original form. */ preserve?: boolean } const creator: PluginCreator = (opts?: PluginOptions) => { - // whether to preserve custom selectors and rules using them const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true; - let customProperties : Map = new Map(); return { postcssPlugin: 'postcss-custom-properties', - Once: (root) => { - customProperties = getCustomPropertiesFromRoot(root); - }, - Declaration: (decl) => { - transformProperties(decl, customProperties, { preserve: preserve }); - }, - OnceExit: () => { - customProperties.clear(); + prepare: () => { + let customProperties: Map = new Map(); + + return { + Once: (root) => { + customProperties = getCustomPropertiesFromRoot(root); + }, + Declaration: (decl) => { + transformProperties(decl, customProperties, { preserve: preserve }); + }, + }; }, }; }; diff --git a/plugins/postcss-custom-properties/src/lib/is-ignored.ts b/plugins/postcss-custom-properties/src/is-ignored.ts similarity index 100% rename from plugins/postcss-custom-properties/src/lib/is-ignored.ts rename to plugins/postcss-custom-properties/src/is-ignored.ts diff --git a/plugins/postcss-custom-properties/src/lib/transform-properties.ts b/plugins/postcss-custom-properties/src/transform-properties.ts similarity index 91% rename from plugins/postcss-custom-properties/src/lib/transform-properties.ts rename to plugins/postcss-custom-properties/src/transform-properties.ts index fe09c4e360..03a0e8db70 100644 --- a/plugins/postcss-custom-properties/src/lib/transform-properties.ts +++ b/plugins/postcss-custom-properties/src/transform-properties.ts @@ -12,7 +12,7 @@ export default (decl, customProperties, opts) => { // protect against circular references const valueSet = new Set(); - while (value.includes('--') && value.includes('var(') && !valueSet.has(value)) { + while (value.includes('--') && value.toLowerCase().includes('var(') && !valueSet.has(value)) { valueSet.add(value); const parsedValueAST = valuesParser(value); value = transformValueAST(parsedValueAST, customProperties); @@ -42,7 +42,7 @@ export default (decl, customProperties, opts) => { // match custom properties // whether the declaration should be potentially transformed -const isTransformableDecl = decl => !decl.variable && decl.value.includes('--') && decl.value.includes('var('); +const isTransformableDecl = decl => !decl.variable && decl.value.includes('--') && decl.value.toLowerCase().includes('var('); // whether the declaration has a trailing comment const hasTrailingComment = decl => 'value' in Object(Object(decl.raws).value) && 'raw' in decl.raws.value && trailingCommentRegExp.test(decl.raws.value.raw); diff --git a/plugins/postcss-custom-properties/src/lib/transform-value-ast.ts b/plugins/postcss-custom-properties/src/transform-value-ast.ts similarity index 100% rename from plugins/postcss-custom-properties/src/lib/transform-value-ast.ts rename to plugins/postcss-custom-properties/src/transform-value-ast.ts diff --git a/plugins/postcss-custom-selectors/README.md b/plugins/postcss-custom-selectors/README.md index 5b57aeeb09..dcc7258540 100644 --- a/plugins/postcss-custom-selectors/README.md +++ b/plugins/postcss-custom-selectors/README.md @@ -13,7 +13,9 @@ article :--heading + p { /* becomes */ -article h1 + p,article h2 + p,article h3 + p { +@custom-selector :--heading h1, h2, h3; + +article :is(h1, h2, h3) + p { margin-top: 0; } ``` @@ -65,7 +67,7 @@ article :--heading + p { @custom-selector :--heading h1, h2, h3; -article h1 + p,article h2 + p,article h3 + p { +article :is(h1, h2, h3) + p { margin-top: 0; } @@ -74,85 +76,6 @@ article :--heading + p { } ``` -### importFrom - -The `importFrom` option specifies sources where custom selectors can be -imported from, which might be CSS, JS, and JSON files, functions, and directly -passed objects. - -```js -postcssCustomSelectors({ - importFrom: 'path/to/file.css' // => @custom-selector :--heading h1, h2, h3; -}); -``` - -```pcss -article :--heading + p { - margin-top: 0; -} - -/* becomes */ - -article h1 + p, article h2 + p, article h3 + p {} -``` - -Multiple sources can be passed into this option, and they will be parsed in the -order they are received. JavaScript files, JSON files, functions, and objects -will need to namespace custom selectors using the `customProperties` or -`custom-properties` key. - -```js -postcssCustomSelectors({ - importFrom: [ - 'path/to/file.css', - 'and/then/this.js', - 'and/then/that.json', - { - customSelectors: { ':--heading': 'h1, h2, h3' } - }, - () => { - const customProperties = { ':--heading': 'h1, h2, h3' }; - - return { customProperties }; - } - ] -}); -``` - -### exportTo - -The `exportTo` option specifies destinations where custom selectors can be -exported to, which might be CSS, JS, and JSON files, functions, and directly -passed objects. - -```js -postcssCustomSelectors({ - exportTo: 'path/to/file.css' // @custom-selector :--heading h1, h2, h3; -}); -``` - -Multiple destinations can be passed into this option, and they will be parsed -in the order they are received. JavaScript files, JSON files, and objects will -need to namespace custom selectors using the `customProperties` or -`custom-properties` key. - -```js -const cachedObject = { customSelectors: {} }; - -postcssCustomSelectors({ - exportTo: [ - 'path/to/file.css', // @custom-selector :--heading h1, h2, h3; - 'and/then/this.js', // module.exports = { customSelectors: { ':--heading': 'h1, h2, h3' } } - 'and/then/this.mjs', // export const customSelectors = { ':--heading': 'h1, h2, h3' } } - 'and/then/that.json', // { "custom-selectors": { ":--heading": "h1, h2, h3" } } - cachedObject, - customProperties => { - customProperties // { ':--heading': 'h1, h2, h3' } - } - ] -}); -``` - [cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test [css-url]: https://cssdb.org/#custom-selectors [discord]: https://discord.gg/bUadyRwkJS diff --git a/plugins/postcss-custom-selectors/docs/README.md b/plugins/postcss-custom-selectors/docs/README.md index 94e7d6e0f2..9537100cae 100644 --- a/plugins/postcss-custom-selectors/docs/README.md +++ b/plugins/postcss-custom-selectors/docs/README.md @@ -49,84 +49,5 @@ is preserved. By default, it is not preserved. ``` -### importFrom - -The `importFrom` option specifies sources where custom selectors can be -imported from, which might be CSS, JS, and JSON files, functions, and directly -passed objects. - -```js -({ - importFrom: 'path/to/file.css' // => @custom-selector :--heading h1, h2, h3; -}); -``` - -```pcss -article :--heading + p { - margin-top: 0; -} - -/* becomes */ - -article h1 + p, article h2 + p, article h3 + p {} -``` - -Multiple sources can be passed into this option, and they will be parsed in the -order they are received. JavaScript files, JSON files, functions, and objects -will need to namespace custom selectors using the `customProperties` or -`custom-properties` key. - -```js -({ - importFrom: [ - 'path/to/file.css', - 'and/then/this.js', - 'and/then/that.json', - { - customSelectors: { ':--heading': 'h1, h2, h3' } - }, - () => { - const customProperties = { ':--heading': 'h1, h2, h3' }; - - return { customProperties }; - } - ] -}); -``` - -### exportTo - -The `exportTo` option specifies destinations where custom selectors can be -exported to, which might be CSS, JS, and JSON files, functions, and directly -passed objects. - -```js -({ - exportTo: 'path/to/file.css' // @custom-selector :--heading h1, h2, h3; -}); -``` - -Multiple destinations can be passed into this option, and they will be parsed -in the order they are received. JavaScript files, JSON files, and objects will -need to namespace custom selectors using the `customProperties` or -`custom-properties` key. - -```js -const cachedObject = { customSelectors: {} }; - -({ - exportTo: [ - 'path/to/file.css', // @custom-selector :--heading h1, h2, h3; - 'and/then/this.js', // module.exports = { customSelectors: { ':--heading': 'h1, h2, h3' } } - 'and/then/this.mjs', // export const customSelectors = { ':--heading': 'h1, h2, h3' } } - 'and/then/that.json', // { "custom-selectors": { ":--heading": "h1, h2, h3" } } - cachedObject, - customProperties => { - customProperties // { ':--heading': 'h1, h2, h3' } - } - ] -}); -``` - [Custom Selectors Specification]: diff --git a/plugins/postcss-nesting/src/lib/valid-atrules.js b/plugins/postcss-nesting/src/lib/valid-atrules.js index 82a9318e46..92dff47cde 100644 --- a/plugins/postcss-nesting/src/lib/valid-atrules.js +++ b/plugins/postcss-nesting/src/lib/valid-atrules.js @@ -1 +1 @@ -export default ['container', 'document', 'media', 'supports', 'layer']; +export default ['container', 'document', 'media', 'supports']; diff --git a/plugins/postcss-nesting/test/layer.css b/plugins/postcss-nesting/test/layer.css index e9bd943417..98c291e2d5 100644 --- a/plugins/postcss-nesting/test/layer.css +++ b/plugins/postcss-nesting/test/layer.css @@ -8,7 +8,7 @@ width: 100px; @layer A { - /* There is no definition for this behavior */ + /* Only conditional rules are allowed to be nested */ background-color: red; } } diff --git a/plugins/postcss-nesting/test/layer.expect.css b/plugins/postcss-nesting/test/layer.expect.css index 94b71699a2..98c291e2d5 100644 --- a/plugins/postcss-nesting/test/layer.expect.css +++ b/plugins/postcss-nesting/test/layer.expect.css @@ -6,12 +6,9 @@ background-color: blue; height: 100px; width: 100px; -} - -@layer A { -.partially-layered { - /* There is no definition for this behavior */ + @layer A { + /* Only conditional rules are allowed to be nested */ background-color: red; -} } +} From f5fe2a1f3bda3bec003e9ce688597201adc05fb1 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sun, 21 Aug 2022 10:58:41 +0200 Subject: [PATCH 04/11] custom-properties: add support for locally defined values and handle 'initial' as invalid --- .../test/basic.autoprefixer.expect.css | 2 +- .../test/basic.autoprefixer.false.expect.css | 2 +- .../test/basic.ch38.expect.css | 2 +- .../test/basic.ch88-ff78-saf10.expect.css | 2 +- .../test/basic.ch88-ff78.expect.css | 2 +- .../basic.ch88-ff78.no-is-pseudo.expect.css | 2 +- .../postcss-preset-env/test/basic.css | 2 +- .../postcss-preset-env/test/basic.expect.css | 2 +- .../test/basic.ff49.expect.css | 2 +- .../test/basic.ff66.expect.css | 2 +- .../test/basic.ie10.expect.css | 2 +- .../test/basic.nesting.false.expect.css | 2 +- .../test/basic.nesting.true.expect.css | 2 +- .../test/basic.op_mini.expect.css | 2 +- .../test/basic.preserve.true.expect.css | 2 +- .../test/basic.safari15.expect.css | 2 +- .../test/basic.stage0-ff49.expect.css | 2 +- .../test/basic.stage0-ff66.expect.css | 2 +- .../test/basic.stage0.expect.css | 2 +- .../test/basic.vendors-1.expect.css | 2 +- .../test/basic.vendors-2.expect.css | 2 +- .../test/basic.vendors-3.expect.css | 2 +- .../test/layers-basic.expect.css | 1 + .../layers-basic.preserve.true.expect.css | 1 + plugins/postcss-custom-properties/.tape.mjs | 9 +++++ .../src/get-custom-properties-from-root.ts | 8 +++++ .../postcss-custom-properties/src/index.ts | 36 +++++++++++++++++-- .../postcss-custom-properties/test/basic.css | 31 ++++++++++++++++ .../test/basic.expect.css | 36 +++++++++++++++++++ .../test/basic.preserve.expect.css | 31 ++++++++++++++++ .../test/examples/example.css | 19 ++++++++++ .../test/examples/example.expect.css | 21 +++++++++++ .../test/examples/example.preserve.expect.css | 19 ++++++++++ 33 files changed, 232 insertions(+), 24 deletions(-) create mode 100644 plugins/postcss-custom-properties/test/examples/example.css create mode 100644 plugins/postcss-custom-properties/test/examples/example.expect.css create mode 100644 plugins/postcss-custom-properties/test/examples/example.preserve.expect.css diff --git a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css index 53d2ddca15..f8fd799d75 100644 --- a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css @@ -496,7 +496,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css index 53d2ddca15..f8fd799d75 100644 --- a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.false.expect.css @@ -496,7 +496,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css index b42d01e7b9..f019302cd9 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css @@ -408,7 +408,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css index 024bed0c45..7a5adba8ef 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css @@ -437,7 +437,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css index 75eb1024bd..cd2a9b6654 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css @@ -437,7 +437,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css index 75eb1024bd..cd2a9b6654 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css @@ -437,7 +437,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.css b/plugin-packs/postcss-preset-env/test/basic.css index 260b431cec..7012894ad9 100644 --- a/plugin-packs/postcss-preset-env/test/basic.css +++ b/plugin-packs/postcss-preset-env/test/basic.css @@ -324,7 +324,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2ic; content: var(--value-2ic); left: var(--non-existing, 2ic); diff --git a/plugin-packs/postcss-preset-env/test/basic.expect.css b/plugin-packs/postcss-preset-env/test/basic.expect.css index bf38fe3e28..1dbe6a053c 100644 --- a/plugin-packs/postcss-preset-env/test/basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.expect.css @@ -519,7 +519,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css b/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css index 50da8804e0..9abe2ee2ea 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css @@ -412,7 +412,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css b/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css index 1ea635f67a..5af186590b 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css @@ -396,7 +396,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css b/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css index 32b9e9c643..ca64a16506 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css @@ -534,7 +534,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css index 9f6960a3b6..ffce374455 100644 --- a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css @@ -539,7 +539,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css b/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css index 51505321b4..bc3752d528 100644 --- a/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.nesting.true.expect.css @@ -340,7 +340,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2ic; content: var(--value-2ic); left: var(--non-existing, 2ic); diff --git a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css index 5057188e98..a29e7bbb17 100644 --- a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css @@ -525,7 +525,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css index 3ca6e2ee79..cfe2b6ab9e 100644 --- a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css @@ -922,7 +922,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; text-indent: 2ic; content: var(--value-2ic); diff --git a/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css b/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css index 5e6f981511..85a6584d7c 100644 --- a/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css @@ -357,7 +357,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css index ed3e648193..2ebd08aa70 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css @@ -439,7 +439,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css index 16a55f51c6..856f7491b1 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css @@ -423,7 +423,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css index 2a07e832dd..b8d33273fb 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css @@ -546,7 +546,7 @@ h6.test-custom-selectors { } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css b/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css index c154a8c66d..6941f6d994 100644 --- a/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.vendors-1.expect.css @@ -523,7 +523,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css b/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css index 70bd470305..7f47b80cf0 100644 --- a/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.vendors-2.expect.css @@ -486,7 +486,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2em; content: var(--value-2ic); left: 2em; diff --git a/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css b/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css index 223d5fead2..85681e28d5 100644 --- a/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.vendors-3.expect.css @@ -459,7 +459,7 @@ } .ic-unit { - --value-2ic: 'something'; + --value-2ic: initial; text-indent: 2ic; content: var(--value-2ic); left: 2ic; diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css index 74dc70b7b7..76db6bc177 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -733,6 +733,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n .ic-unit:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --value-2ic: 'something'; text-indent: 2em; + content: 'something'; content: var(--value-2ic); left: 2em; left: var(--non-existing, 2em); diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css index dd39a88ec1..f264bc0486 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css @@ -868,6 +868,7 @@ h6.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n --value-2ic: 'something'; text-indent: 2em; text-indent: 2ic; + content: 'something'; content: var(--value-2ic); left: 2em; left: var(--non-existing, 2em); diff --git a/plugins/postcss-custom-properties/.tape.mjs b/plugins/postcss-custom-properties/.tape.mjs index ffa02a7958..c97c18e134 100644 --- a/plugins/postcss-custom-properties/.tape.mjs +++ b/plugins/postcss-custom-properties/.tape.mjs @@ -12,6 +12,15 @@ postcssTape(plugin)({ preserve: false } }, + 'examples/example': { + message: 'minimal example', + }, + 'examples/example:preserve': { + message: 'minimal example with { preserve: false }', + options: { + preserve: false + } + }, 'import': { message: 'supports "postcss-import"', plugins: [postcssImport(), plugin()] diff --git a/plugins/postcss-custom-properties/src/get-custom-properties-from-root.ts b/plugins/postcss-custom-properties/src/get-custom-properties-from-root.ts index acdd53c943..a87bda3b07 100644 --- a/plugins/postcss-custom-properties/src/get-custom-properties-from-root.ts +++ b/plugins/postcss-custom-properties/src/get-custom-properties-from-root.ts @@ -25,6 +25,10 @@ export default function getCustomPropertiesFromRoot(root: Root): Map = (opts?: PluginOptions) => { customProperties = getCustomPropertiesFromRoot(root); }, Declaration: (decl) => { - transformProperties(decl, customProperties, { preserve: preserve }); + let localCustomProperties = customProperties; + if (preserve && decl.parent) { + let didCopy = false; + + decl.parent.each((siblingDecl) => { + if (decl === siblingDecl) { + return; + } + + if (siblingDecl.type !== 'decl') { + return; + } + + if (!siblingDecl.variable || isBlockIgnored(siblingDecl)) { + return; + } + + if (!didCopy) { + localCustomProperties = new Map(customProperties); + didCopy = true; + } + + if (siblingDecl.value.toLowerCase().trim() === 'initial') { + localCustomProperties.delete(siblingDecl.prop); + return; + } + + localCustomProperties.set(siblingDecl.prop, valuesParser(siblingDecl.value)); + }); + } + + transformProperties(decl, localCustomProperties, { preserve: preserve }); }, }; }, diff --git a/plugins/postcss-custom-properties/test/basic.css b/plugins/postcss-custom-properties/test/basic.css index a30659889a..745b0cc45b 100644 --- a/plugins/postcss-custom-properties/test/basic.css +++ b/plugins/postcss-custom-properties/test/basic.css @@ -142,3 +142,34 @@ html { .fallbacks-with-main-values-that-dont-exist { color: var(--does-not-exist, var(--color)) } + +:root { + --ignored-values-1: initial; +} + +.ignored-values { + color: var(--ignored-values-1); + color: var(--ignored-values-1, green); +} + +:root { + --space-1:; + --space-2: ; + --space-3: ; +} + +.space-values { + a: list("a",var(--space-1),"c"); + b: list("a",var(--space-2),"c"); + c: list("a",var(--space-3),"c"); +} + +@media (prefers-color-scheme: dark) { + :root { + --color: rgb(255, 167, 167); + } +} + +.conditionals { + color: var(--color); +} diff --git a/plugins/postcss-custom-properties/test/basic.expect.css b/plugins/postcss-custom-properties/test/basic.expect.css index f5ec73cbc1..8ed208d3f8 100644 --- a/plugins/postcss-custom-properties/test/basic.expect.css +++ b/plugins/postcss-custom-properties/test/basic.expect.css @@ -164,3 +164,39 @@ html { color: rgb(255, 0, 0); color: var(--does-not-exist, var(--color)) } + +:root { + --ignored-values-1: initial; +} + +.ignored-values { + color: var(--ignored-values-1); + color: green; + color: var(--ignored-values-1, green); +} + +:root { + --space-1:; + --space-2: ; + --space-3: ; +} + +.space-values { + a: list("a",,"c"); + a: list("a",var(--space-1),"c"); + b: list("a", ,"c"); + b: list("a",var(--space-2),"c"); + c: list("a", ,"c"); + c: list("a",var(--space-3),"c"); +} + +@media (prefers-color-scheme: dark) { + :root { + --color: rgb(255, 167, 167); + } +} + +.conditionals { + color: rgb(255, 0, 0); + color: var(--color); +} diff --git a/plugins/postcss-custom-properties/test/basic.preserve.expect.css b/plugins/postcss-custom-properties/test/basic.preserve.expect.css index f7a17f75eb..cbe7e8d3ac 100644 --- a/plugins/postcss-custom-properties/test/basic.preserve.expect.css +++ b/plugins/postcss-custom-properties/test/basic.preserve.expect.css @@ -139,3 +139,34 @@ html { .fallbacks-with-main-values-that-dont-exist { color: rgb(255, 0, 0) } + +:root { + --ignored-values-1: initial; +} + +.ignored-values { + color: var(--ignored-values-1); + color: green; +} + +:root { + --space-1:; + --space-2: ; + --space-3: ; +} + +.space-values { + a: list("a",,"c"); + b: list("a", ,"c"); + c: list("a", ,"c"); +} + +@media (prefers-color-scheme: dark) { + :root { + --color: rgb(255, 167, 167); + } +} + +.conditionals { + color: rgb(255, 0, 0); +} diff --git a/plugins/postcss-custom-properties/test/examples/example.css b/plugins/postcss-custom-properties/test/examples/example.css new file mode 100644 index 0000000000..837daa8c6d --- /dev/null +++ b/plugins/postcss-custom-properties/test/examples/example.css @@ -0,0 +1,19 @@ +:root { + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); +} + +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid var(--border-color); + color: var(--text-color); +} + +.element--dark { + --border-color: var(--color-blue-dark); +} diff --git a/plugins/postcss-custom-properties/test/examples/example.expect.css b/plugins/postcss-custom-properties/test/examples/example.expect.css new file mode 100644 index 0000000000..1a8bce1bc2 --- /dev/null +++ b/plugins/postcss-custom-properties/test/examples/example.expect.css @@ -0,0 +1,21 @@ +:root { + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); +} + +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid rgb(0, 217, 255); + border: 1px solid var(--border-color); + color: rgb(255, 192, 211); + color: var(--text-color); +} + +.element--dark { + --border-color: var(--color-blue-dark); +} diff --git a/plugins/postcss-custom-properties/test/examples/example.preserve.expect.css b/plugins/postcss-custom-properties/test/examples/example.preserve.expect.css new file mode 100644 index 0000000000..a5620ab459 --- /dev/null +++ b/plugins/postcss-custom-properties/test/examples/example.preserve.expect.css @@ -0,0 +1,19 @@ +:root { + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); +} + +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid var(--border-color); + color: rgb(255, 192, 211); +} + +.element--dark { + --border-color: var(--color-blue-dark); +} From ee6b5fa15a679632a987d44407d2a8688483acc4 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 3 Sep 2022 14:22:58 +0200 Subject: [PATCH 05/11] more tests and docs for custom props --- plugins/postcss-custom-properties/.tape.mjs | 2 +- .../postcss-custom-properties/CHANGELOG.md | 18 +++ plugins/postcss-custom-properties/README.md | 110 +++++++++++++----- .../postcss-custom-properties/docs/README.md | 62 ++++++++++ .../postcss-custom-properties/package.json | 6 +- .../postcss-custom-properties/src/index.ts | 8 ++ .../postcss-custom-properties/test/basic.css | 11 ++ .../test/basic.expect.css | 14 +++ .../test/basic.preserve.expect.css | 11 ++ ....css => example.preserve-false.expect.css} | 0 10 files changed, 207 insertions(+), 35 deletions(-) create mode 100644 plugins/postcss-custom-properties/docs/README.md rename plugins/postcss-custom-properties/test/examples/{example.preserve.expect.css => example.preserve-false.expect.css} (100%) diff --git a/plugins/postcss-custom-properties/.tape.mjs b/plugins/postcss-custom-properties/.tape.mjs index c97c18e134..47acf12d85 100644 --- a/plugins/postcss-custom-properties/.tape.mjs +++ b/plugins/postcss-custom-properties/.tape.mjs @@ -15,7 +15,7 @@ postcssTape(plugin)({ 'examples/example': { message: 'minimal example', }, - 'examples/example:preserve': { + 'examples/example:preserve-false': { message: 'minimal example with { preserve: false }', options: { preserve: false diff --git a/plugins/postcss-custom-properties/CHANGELOG.md b/plugins/postcss-custom-properties/CHANGELOG.md index 9aee657cdb..f773cfdb9c 100644 --- a/plugins/postcss-custom-properties/CHANGELOG.md +++ b/plugins/postcss-custom-properties/CHANGELOG.md @@ -3,6 +3,24 @@ ### Unreleased (major) - Updated: Support for Node v14+ (major). +- Removed : `importFrom` feature (breaking). +- Removed : `exportTo` feature (breaking). +- Added support for local custom property declarations. + +```css +.example { + --a-value: 20px; + margin: var(--a-value); +} + +/* becomes */ + +.example { + --a-value: 20px; + margin: 20px; + margin: var(--a-value); +} +``` ### 12.1.8 (June 10, 2022) diff --git a/plugins/postcss-custom-properties/README.md b/plugins/postcss-custom-properties/README.md index 9decb1707b..1b16082c61 100644 --- a/plugins/postcss-custom-properties/README.md +++ b/plugins/postcss-custom-properties/README.md @@ -1,47 +1,71 @@ -# PostCSS Custom Properties [PostCSS][postcss] +# PostCSS Custom Properties [PostCSS Logo][postcss] -[![NPM Version][npm-img]][npm-url] -[![CSS Standard Status][css-img]][css-url] -[![Build Status][cli-img]][cli-url] -[Discord][discord] +[npm version][npm-url] [CSS Standard Status][css-url] [Build Status][cli-url] [Discord][discord] [PostCSS Custom Properties] lets you use Custom Properties in CSS, following -the [CSS Custom Properties] specification. +the [PostCSS Custom Properties] specification. [!['Can I use' table](https://caniuse.bitsofco.de/image/css-variables.png)](https://caniuse.com/#feat=css-variables) ```pcss :root { - --color: red; + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); } -h1 { - color: var(--color); +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid var(--border-color); + color: var(--text-color); +} + +.element--dark { + --border-color: var(--color-blue-dark); } /* becomes */ :root { - --color: red; + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); +} + +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid rgb(0, 217, 255); + border: 1px solid var(--border-color); + color: rgb(255, 192, 211); + color: var(--text-color); } -h1 { - color: red; - color: var(--color); +.element--dark { + --border-color: var(--color-blue-dark); } ``` **Note:** This plugin only processes variables that are defined in the `:root` or `html` selector. +Locally defined custom properties will be used as fallbacks inly within the same rule. + ## Usage Add [PostCSS Custom Properties] to your project: ```bash -npm install postcss-custom-properties --save-dev +npm install postcss postcss-custom-properties --save-dev ``` -Use [PostCSS Custom Properties] as a [PostCSS] plugin: +Use it as a [PostCSS] plugin: ```js const postcss = require('postcss'); @@ -52,7 +76,8 @@ postcss([ ]).process(YOUR_CSS /*, processOptions */); ``` -[PostCSS Custom Properties] runs in all Node environments, with special instructions for: +[PostCSS Custom Properties] runs in all Node environments, with special +instructions for: | [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) | | --- | --- | --- | --- | --- | --- | @@ -64,43 +89,64 @@ postcss([ The `preserve` option determines whether properties using custom properties should be preserved in their original form. By default these are preserved. +Custom property declarations are always preserved only `var()` functions can be omitted. + ```js -postcssCustomProperties({ - preserve: false -}); +postcssCustomProperties({ preserve: false }) ``` ```pcss :root { - --color: red; + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); } -h1 { - color: var(--color); +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid var(--border-color); + color: var(--text-color); +} + +.element--dark { + --border-color: var(--color-blue-dark); } /* becomes */ :root { - --color: red; + --color-blue-dark: rgb(0, 61, 184); + --color-blue-light: rgb(0, 217, 255); + --color-pink: rgb(255, 192, 211); + --text-color: var(--color-pink); } -h1 { - color: red; +.element { + /* custom props */ + --border-color: var(--color-blue-light); + + /* props */ + border: 1px solid var(--border-color); + color: rgb(255, 192, 211); } -``` -No Custom Properties will be removed from `:root` or `html` even when `preserve` is false. -It is impossible to know if a Custom Property is truly unused or only unused in the current stylesheet. +.element--dark { + --border-color: var(--color-blue-dark); +} +``` -[cli-img]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml/badge.svg [cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test -[css-img]: https://cssdb.org/images/badges/custom-properties.svg [css-url]: https://cssdb.org/#custom-properties [discord]: https://discord.gg/bUadyRwkJS -[npm-img]: https://img.shields.io/npm/v/postcss-custom-properties.svg [npm-url]: https://www.npmjs.com/package/postcss-custom-properties -[CSS Custom Properties]: https://www.w3.org/TR/css-variables-1/ +[Gulp PostCSS]: https://github.com/postcss/gulp-postcss +[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss [PostCSS]: https://github.com/postcss/postcss +[PostCSS Loader]: https://github.com/postcss/postcss-loader [PostCSS Custom Properties]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-properties +[PostCSS Custom Properties]: https://www.w3.org/TR/css-variables-1/ diff --git a/plugins/postcss-custom-properties/docs/README.md b/plugins/postcss-custom-properties/docs/README.md new file mode 100644 index 0000000000..e78f32eb9b --- /dev/null +++ b/plugins/postcss-custom-properties/docs/README.md @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + +
+ +[] lets you use Custom Properties in CSS, following +the [PostCSS Custom Properties] specification. + +[!['Can I use' table](https://caniuse.bitsofco.de/image/css-variables.png)](https://caniuse.com/#feat=css-variables) + +```pcss + + +/* becomes */ + + +``` + +**Note:** This plugin only processes variables that are defined in the `:root` or `html` selector. + +Locally defined custom properties will be used as fallbacks inly within the same rule. + + + + + +## Options + +### preserve + +The `preserve` option determines whether properties using +custom properties should be preserved in their original form. By default these are preserved. + +Custom property declarations are always preserved only `var()` functions can be omitted. + +```js +({ preserve: false }) +``` + +```pcss + + +/* becomes */ + + +``` + + +[PostCSS Custom Properties]: diff --git a/plugins/postcss-custom-properties/package.json b/plugins/postcss-custom-properties/package.json index f27c7ac54e..20d39c9fd5 100644 --- a/plugins/postcss-custom-properties/package.json +++ b/plugins/postcss-custom-properties/package.json @@ -43,7 +43,7 @@ "scripts": { "build": "rollup -c ../../rollup/default.js", "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true });\"", - "docs": "node ../../.github/bin/generate-docs/install.mjs", + "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs", "lint": "npm run lint:eslint && npm run lint:package-json", "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern", "lint:package-json": "node ../../.github/bin/format-package-json.mjs", @@ -73,8 +73,10 @@ "w3c" ], "csstools": { + "cssdbId": "custom-properties", "exportName": "postcssCustomProperties", - "humanReadableName": "PostCSS Custom Properties" + "humanReadableName": "PostCSS Custom Properties", + "specUrl": "https://www.w3.org/TR/css-variables-1/" }, "volta": { "extends": "../../package.json" diff --git a/plugins/postcss-custom-properties/src/index.ts b/plugins/postcss-custom-properties/src/index.ts index 4ca593301b..8085bdfdf2 100644 --- a/plugins/postcss-custom-properties/src/index.ts +++ b/plugins/postcss-custom-properties/src/index.ts @@ -13,6 +13,14 @@ export interface PluginOptions { const creator: PluginCreator = (opts?: PluginOptions) => { const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true; + if ('importFrom' in Object(opts)) { + throw new Error('[postcss-custom-properties] "importFrom" is no longer supported'); + } + + if ('exportTo' in Object(opts)) { + throw new Error('[postcss-custom-properties] "exportTo" is no longer supported'); + } + return { postcssPlugin: 'postcss-custom-properties', prepare: () => { diff --git a/plugins/postcss-custom-properties/test/basic.css b/plugins/postcss-custom-properties/test/basic.css index 745b0cc45b..5f1823dc29 100644 --- a/plugins/postcss-custom-properties/test/basic.css +++ b/plugins/postcss-custom-properties/test/basic.css @@ -7,6 +7,7 @@ html { --color-h: 0; --color-s: 100%; --color-l: 50%; + --color-components: var(--color-h), var(--color-s), var(--color-l); --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); --ref-color: var(--color); --circular: var(--circular-2); @@ -74,6 +75,11 @@ html { color: var(--color-hsl); } +.test--color_components { + color: hsl(var(--color-components)); + background-color: hsl(var(--does-not-exist, 0 , 1%, 2%)); +} + .test--circular_var { color: var(--circular); } @@ -173,3 +179,8 @@ html { .conditionals { color: var(--color); } + +.local-variable { + --local: 1; + order: var(--local); +} diff --git a/plugins/postcss-custom-properties/test/basic.expect.css b/plugins/postcss-custom-properties/test/basic.expect.css index 8ed208d3f8..3b8fbb452e 100644 --- a/plugins/postcss-custom-properties/test/basic.expect.css +++ b/plugins/postcss-custom-properties/test/basic.expect.css @@ -7,6 +7,7 @@ html { --color-h: 0; --color-s: 100%; --color-l: 50%; + --color-components: var(--color-h), var(--color-s), var(--color-l); --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); --ref-color: var(--color); --circular: var(--circular-2); @@ -84,6 +85,13 @@ html { color: var(--color-hsl); } +.test--color_components { + color: hsl(0, 100%, 50%); + color: hsl(var(--color-components)); + background-color: hsl(0 , 1%, 2%); + background-color: hsl(var(--does-not-exist, 0 , 1%, 2%)); +} + .test--circular_var { color: var(--circular); } @@ -200,3 +208,9 @@ html { color: rgb(255, 0, 0); color: var(--color); } + +.local-variable { + --local: 1; + order: 1; + order: var(--local); +} diff --git a/plugins/postcss-custom-properties/test/basic.preserve.expect.css b/plugins/postcss-custom-properties/test/basic.preserve.expect.css index cbe7e8d3ac..270d6e387d 100644 --- a/plugins/postcss-custom-properties/test/basic.preserve.expect.css +++ b/plugins/postcss-custom-properties/test/basic.preserve.expect.css @@ -7,6 +7,7 @@ html { --color-h: 0; --color-s: 100%; --color-l: 50%; + --color-components: var(--color-h), var(--color-s), var(--color-l); --color-hsl: hsl(var(--color-h), var(--color-s), var(--color-l)); --ref-color: var(--color); --circular: var(--circular-2); @@ -74,6 +75,11 @@ html { color: hsl(0, 100%, 50%); } +.test--color_components { + color: hsl(0, 100%, 50%); + background-color: hsl(0 , 1%, 2%); +} + .test--circular_var { color: var(--circular); } @@ -170,3 +176,8 @@ html { .conditionals { color: rgb(255, 0, 0); } + +.local-variable { + --local: 1; + order: var(--local); +} diff --git a/plugins/postcss-custom-properties/test/examples/example.preserve.expect.css b/plugins/postcss-custom-properties/test/examples/example.preserve-false.expect.css similarity index 100% rename from plugins/postcss-custom-properties/test/examples/example.preserve.expect.css rename to plugins/postcss-custom-properties/test/examples/example.preserve-false.expect.css From b9f7993f77cbd941e6da9d67a0af5e2c7f4cd80b Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 3 Sep 2022 14:25:52 +0200 Subject: [PATCH 06/11] more docs --- plugins/postcss-custom-properties/README.md | 2 +- plugins/postcss-custom-properties/docs/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/postcss-custom-properties/README.md b/plugins/postcss-custom-properties/README.md index 1b16082c61..af618d5576 100644 --- a/plugins/postcss-custom-properties/README.md +++ b/plugins/postcss-custom-properties/README.md @@ -55,7 +55,7 @@ the [PostCSS Custom Properties] specification. **Note:** This plugin only processes variables that are defined in the `:root` or `html` selector. -Locally defined custom properties will be used as fallbacks inly within the same rule. +Locally defined custom properties will be used as fallbacks inly within the same rule, but not elsewhere. ## Usage diff --git a/plugins/postcss-custom-properties/docs/README.md b/plugins/postcss-custom-properties/docs/README.md index e78f32eb9b..2b156de2d5 100644 --- a/plugins/postcss-custom-properties/docs/README.md +++ b/plugins/postcss-custom-properties/docs/README.md @@ -31,7 +31,7 @@ the [PostCSS Custom Properties] specification. **Note:** This plugin only processes variables that are defined in the `:root` or `html` selector. -Locally defined custom properties will be used as fallbacks inly within the same rule. +Locally defined custom properties will be used as fallbacks inly within the same rule, but not elsewhere. From 73c17a07141dd18f40937a96fe99cf1e9c7770f2 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 3 Sep 2022 14:44:28 +0200 Subject: [PATCH 07/11] fixes --- plugins/postcss-custom-properties/test/_import.mjs | 10 ---------- plugins/postcss-custom-properties/test/_require.cjs | 6 ------ 2 files changed, 16 deletions(-) diff --git a/plugins/postcss-custom-properties/test/_import.mjs b/plugins/postcss-custom-properties/test/_import.mjs index 98f8767664..1992cbec17 100644 --- a/plugins/postcss-custom-properties/test/_import.mjs +++ b/plugins/postcss-custom-properties/test/_import.mjs @@ -1,17 +1,7 @@ import assert from 'assert'; import plugin from 'postcss-custom-properties'; -import postcss from 'postcss'; -import fs from 'fs'; plugin(); assert.ok(plugin.postcss, 'should have "postcss flag"'); assert.equal(typeof plugin, 'function', 'should return a function'); - -postcss([plugin({ importFrom: 'test/import-properties.cjs' })]). - process(fs.readFileSync('test/basic.css', 'utf8'), {from: 'test/basic.css'}). - then(); - -postcss([plugin({ importFrom: 'test/import-properties.mjs' })]). - process(fs.readFileSync('test/basic.css', 'utf8'), {from: 'test/basic.css'}). - then(); diff --git a/plugins/postcss-custom-properties/test/_require.cjs b/plugins/postcss-custom-properties/test/_require.cjs index a9a3a08975..270bdc3e89 100644 --- a/plugins/postcss-custom-properties/test/_require.cjs +++ b/plugins/postcss-custom-properties/test/_require.cjs @@ -1,13 +1,7 @@ const assert = require('assert'); const plugin = require('postcss-custom-properties'); -const postcss = require('postcss'); -const fs = require('fs'); plugin(); assert.ok(plugin.postcss, 'should have "postcss flag"'); assert.equal(typeof plugin, 'function', 'should return a function'); - -postcss([plugin({ importFrom: 'test/import-properties.cjs' })]). - process(fs.readFileSync('test/basic.css', 'utf8'), {from: 'test/basic.css'}). - then(); From 995b56928ee635063d029ae5d1613c36e7bdf9c3 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 3 Sep 2022 14:50:16 +0200 Subject: [PATCH 08/11] fmt --- plugin-packs/postcss-preset-env/src/lib/shared-options.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs b/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs index 617e318ad6..fa46a98a55 100644 --- a/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs +++ b/plugin-packs/postcss-preset-env/src/lib/shared-options.mjs @@ -1,4 +1,3 @@ - export function initializeSharedOptions(opts) { if ('preserve' in opts) { const sharedOptions = {}; From b9e2288a2421e41c8ca5d0c0846231197d7cc9da Mon Sep 17 00:00:00 2001 From: romainmenke Date: Tue, 6 Sep 2022 10:40:11 +0200 Subject: [PATCH 09/11] cleanup --- .../test/basic.ch88-ff78-saf10.expect.css | 4 -- .../test/basic.ch88-ff78.expect.css | 4 -- .../basic.ch88-ff78.no-is-pseudo.expect.css | 4 -- .../test/basic.nesting.false.expect.css | 4 -- .../test/basic.op_mini.expect.css | 4 -- .../test/basic.stage0-ff49.expect.css | 4 -- .../test/basic.stage0-ff66.expect.css | 4 -- .../test/basic.stage0.expect.css | 4 -- .../test/layers-basic.expect.css | 10 ++--- .../src/custom-selectors-from-root.ts | 8 +++- plugins/postcss-custom-selectors/src/index.ts | 2 +- .../src/transform-rule.ts | 4 +- .../test/basic.expect.css | 41 ------------------- .../test/complex.expect.css | 6 --- .../test/examples/example.expect.css | 2 - .../test/safety.expect.css | 2 - 16 files changed, 13 insertions(+), 94 deletions(-) diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css index 7a5adba8ef..7fa0d90723 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78-saf10.expect.css @@ -91,8 +91,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -506,8 +504,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css index cd2a9b6654..ffe829c94b 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.expect.css @@ -91,8 +91,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -506,8 +504,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css index cd2a9b6654..ffe829c94b 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch88-ff78.no-is-pseudo.expect.css @@ -91,8 +91,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -506,8 +504,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css index ffce374455..0c8f976916 100644 --- a/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.nesting.false.expect.css @@ -85,8 +85,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -610,8 +608,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - .view { @nest :--view-m & { background: red; diff --git a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css index a29e7bbb17..d700b87203 100644 --- a/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.op_mini.expect.css @@ -91,8 +91,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -596,8 +594,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css index 2ebd08aa70..74d3fdc4a2 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff49.expect.css @@ -90,8 +90,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -508,8 +506,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css index 856f7491b1..232f2671d4 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0-ff66.expect.css @@ -82,8 +82,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -489,8 +487,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css index b8d33273fb..bd6b26d9d5 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css @@ -92,8 +92,6 @@ } } -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - h1.test-custom-selectors { order:12; } @@ -617,8 +615,6 @@ h6.test-custom-selectors { left: atan2(); } -@custom-selector :--view-m [data-view-size=m]; - [data-view-size=m] .view { background: red; } diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css index 76db6bc177..fa0c91e144 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -1,11 +1,11 @@ - @custom-selector :--heading h1, h2, h3, h4, h5, h6;:root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + :root:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; --order: 1; }.test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; --firebrick: rgb(179, 35, 35); - }@supports (color: color(display-p3 0 0 0)){ + }@supports (color: color(display-p3 0 0 0)) { .test-custom-property-fallbacks:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { --firebrick: color(display-p3 0.64331 0.19245 0.16771); } @@ -26,12 +26,12 @@ -moz-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; - }@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi){.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + }@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 192dpi) {.test-image-set-function:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { background-image: url(img/test-2x.png); } -}[dir="ltr"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ +}[dir="ltr"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { margin: 1px 4px 3px 2px; -}[dir="rtl"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){ +}[dir="rtl"] .test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { margin: 1px 2px 3px 4px; }.test-logical-properties-and-values:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { is-layer: C; diff --git a/plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts b/plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts index 7c89d063b3..5b088da83c 100644 --- a/plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts +++ b/plugins/postcss-custom-selectors/src/custom-selectors-from-root.ts @@ -3,13 +3,13 @@ import type { Root as SelectorRoot } from 'postcss-selector-parser'; import parser from 'postcss-selector-parser'; // return custom selectors from the css root, conditionally removing them -export default function getCustomSelectors(root: PostCSSRoot): Map { +export default function getCustomSelectors(root: PostCSSRoot, opts: { preserve?: boolean }): Map { // initialize custom selectors const customSelectors = new Map(); // for each custom selector atrule that is a child of the css root root.nodes.slice().forEach(node => { - if (node.type !== 'atrule' || node.name !== 'custom-selector') { + if (node.type !== 'atrule' || node.name.toLowerCase() !== 'custom-selector') { return; } @@ -29,6 +29,10 @@ export default function getCustomSelectors(root: PostCSSRoot): Map = (opts?: PluginOptions) => { return { Once: (root) => { - customSelectors = getCustomSelectors(root); + customSelectors = getCustomSelectors(root, { preserve: preserve }); }, Rule: (rule) => { if (!rule.selector.includes(':--')) { diff --git a/plugins/postcss-custom-selectors/src/transform-rule.ts b/plugins/postcss-custom-selectors/src/transform-rule.ts index f317f79dd3..d3b37f4d7f 100644 --- a/plugins/postcss-custom-selectors/src/transform-rule.ts +++ b/plugins/postcss-custom-selectors/src/transform-rule.ts @@ -2,7 +2,7 @@ import type { Root, Selector } from 'postcss-selector-parser'; import parser from 'postcss-selector-parser'; // transform custom pseudo selectors with custom selectors -export default (rule, customSelectors: Map, opts) => { +export default (rule, customSelectors: Map, opts: { preserve?: boolean }) => { const selector = parser(selectors => { selectors.walkPseudos((pseudo) => { if (!customSelectors.has(pseudo.value)) { @@ -19,8 +19,6 @@ export default (rule, customSelectors: Map, opts) => { isWrapper.append(node.clone({}) as Selector); }); - const parent = pseudo.parent; - pseudo.replaceWith(isWrapper); }); diff --git a/plugins/postcss-custom-selectors/test/basic.expect.css b/plugins/postcss-custom-selectors/test/basic.expect.css index cd57782c15..858b928a57 100644 --- a/plugins/postcss-custom-selectors/test/basic.expect.css +++ b/plugins/postcss-custom-selectors/test/basic.expect.css @@ -1,23 +1,9 @@ -@custom-selector :--foo .bar, .baz; - .foo:is(.foo) { margin-top: 16px; } -@custom-selector :--any-heading h1, h2, h3, h4, h5, h6; - :is(h1, h2, h3, h4, h5, h6) + p {} -@custom-selector :--foobar .foo, .bar; -@custom-selector :--baz .baz; -@custom-selector :--fizzbuzz .fizz, .buzz; -@custom-selector :--button-types - .btn-primary, - .btn-success, - .btn-info, - .btn-warning, - .btn-danger; - :is(.foo) > :is(.baz) {} :is(.fizz, .buzz) > :is(.foo) {} :is(.btn-primary, @@ -30,24 +16,15 @@ .btn-warning, .btn-danger):active {} -@custom-selector :--commented-foo - /* comment */ - .foo, - .bar > .baz; - :is(.foo, .bar > .baz) + p { display: block; } -@custom-selector :--pseudo ::before, ::after; - .foo > a:is(::before, ::after) img { display: block; } -@custom-selector :--foo .foo; - :is(.foo),:is(.foo).bar { color: white; } @@ -56,9 +33,6 @@ color: white; } -@custom-selector :--fo-----o h1, h2, h3; -@custom-selector :--ba-----r h4, h5, h6; - .fo--oo > :is(h1, h2, h3) { margin: auto; } @@ -73,10 +47,6 @@ article :--heading + p { margin-top: 0; } -@custom-selector :--multiline - .foo, - .bar > .baz; - :is(.foo, .bar > .baz) { display: block; @@ -84,13 +54,8 @@ article :--heading + p { /* should works with collapsed custom selectors */ -@custom-selector :--button button, .button; -@custom-selector :--enter :hover, :focus; - :is(button, .button):is(:hover, :focus) {} -@custom-selector :--any-foobar .foo, .bar; - :is(.foo, .bar) h1 { margin-top: 16px; } @@ -99,8 +64,6 @@ main :is(.foo) + p { margin-top: 16px; } -@custom-selector :--foobar .foo; - :is(.foo) { order: 1000; } @@ -111,8 +74,6 @@ b,:is(.foo) { order: 1002; } -@custom-selector :--foobaz .foo.baz; - :is(.foo.baz) { order: 1010; } @@ -123,8 +84,6 @@ b,:is(.foo.baz) { order: 1012; } -@custom-selector :--foobazz .foo .baz; - :is(.foo .baz) { order: 1020; } diff --git a/plugins/postcss-custom-selectors/test/complex.expect.css b/plugins/postcss-custom-selectors/test/complex.expect.css index ca0e573184..d5fa08a9ed 100644 --- a/plugins/postcss-custom-selectors/test/complex.expect.css +++ b/plugins/postcss-custom-selectors/test/complex.expect.css @@ -1,17 +1,11 @@ -@custom-selector :--3xl .xl3; - :is(.xl3) { order: 1; } -@custom-selector :--🧑🏾‍🎤 .singer; - :is(.singer) { order: 2; } -@custom-selector :------- .dash; - :is(.dash) { order: 3; } diff --git a/plugins/postcss-custom-selectors/test/examples/example.expect.css b/plugins/postcss-custom-selectors/test/examples/example.expect.css index 906075f2c8..857c8ee517 100644 --- a/plugins/postcss-custom-selectors/test/examples/example.expect.css +++ b/plugins/postcss-custom-selectors/test/examples/example.expect.css @@ -1,5 +1,3 @@ -@custom-selector :--heading h1, h2, h3; - article :is(h1, h2, h3) + p { margin-top: 0; } diff --git a/plugins/postcss-custom-selectors/test/safety.expect.css b/plugins/postcss-custom-selectors/test/safety.expect.css index b448103ffb..f90988ab93 100644 --- a/plugins/postcss-custom-selectors/test/safety.expect.css +++ b/plugins/postcss-custom-selectors/test/safety.expect.css @@ -1,5 +1,3 @@ -@custom-selector :--h1 h1; - .class:is(h1), #id:is(h1), ::before:is(h1), *:is(h1) { order: 1; } From d18623ffe18094d87ca1d2104807747d9fa5a39a Mon Sep 17 00:00:00 2001 From: romainmenke Date: Tue, 6 Sep 2022 10:46:31 +0200 Subject: [PATCH 10/11] docs --- plugins/postcss-custom-properties/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/postcss-custom-properties/README.md b/plugins/postcss-custom-properties/README.md index 8379b85222..be903271b0 100644 --- a/plugins/postcss-custom-properties/README.md +++ b/plugins/postcss-custom-properties/README.md @@ -3,7 +3,7 @@ [npm version][npm-url] [CSS Standard Status][css-url] [Build Status][cli-url] [Discord][discord] [PostCSS Custom Properties] lets you use Custom Properties in CSS, following -the [PostCSS Custom Properties] specification. +the [CSS Custom Properties] specification. [!['Can I use' table](https://caniuse.bitsofco.de/image/css-variables.png)](https://caniuse.com/#feat=css-variables) From dea9fcd926d6cad0919212931fcb1dc1355efb14 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Tue, 6 Sep 2022 10:49:24 +0200 Subject: [PATCH 11/11] npm install --- package-lock.json | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd1493f363..0417156dbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6970,8 +6970,8 @@ "dependencies": { "postcss-selector-parser": "^6.0.10" }, - "bin": { - "css-blank-pseudo": "dist/cli.cjs" + "devDependencies": { + "puppeteer": "^17.1.1" }, "engines": { "node": "^14 || ^16 || >=18" @@ -6992,8 +6992,9 @@ "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0" }, - "bin": { - "css-has-pseudo": "dist/cli.cjs" + "devDependencies": { + "@mrhenry/core-web": "^0.7.7", + "puppeteer": "^17.1.1" }, "engines": { "node": "^14 || ^16 || >=18" @@ -7009,8 +7010,8 @@ "plugins/css-prefers-color-scheme": { "version": "7.0.1", "license": "CC0-1.0", - "bin": { - "css-prefers-color-scheme": "dist/cli.cjs" + "devDependencies": { + "puppeteer": "^17.1.1" }, "engines": { "node": "^14 || ^16 || >=18" @@ -7306,6 +7307,9 @@ "dependencies": { "postcss-selector-parser": "^6.0.10" }, + "devDependencies": { + "puppeteer": "^17.1.1" + }, "engines": { "node": "^14 || ^16 || >=18" }, @@ -10052,18 +10056,25 @@ "css-blank-pseudo": { "version": "file:plugins/css-blank-pseudo", "requires": { - "postcss-selector-parser": "^6.0.10" + "postcss-selector-parser": "^6.0.10", + "puppeteer": "^17.1.1" } }, "css-has-pseudo": { "version": "file:plugins/css-has-pseudo", "requires": { - "postcss-selector-parser": "^6.0.10" + "@csstools/selector-specificity": "^2.0.1", + "@mrhenry/core-web": "^0.7.7", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "puppeteer": "^17.1.1" } }, "css-prefers-color-scheme": { "version": "file:plugins/css-prefers-color-scheme", - "requires": {} + "requires": { + "puppeteer": "^17.1.1" + } }, "cssdb": { "version": "7.0.1", @@ -11615,7 +11626,8 @@ "postcss-focus-visible": { "version": "file:plugins/postcss-focus-visible", "requires": { - "postcss-selector-parser": "^6.0.10" + "postcss-selector-parser": "^6.0.10", + "puppeteer": "^17.1.1" } }, "postcss-focus-within": {