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 f2d0f311e..6a8ea282f 100644 --- a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css @@ -252,6 +252,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 f2d0f311e..6a8ea282f 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 @@ -252,6 +252,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 1529b3338..d5e80bf15 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css @@ -172,6 +172,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 e2e988048..0df0a119f 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 @@ -171,6 +171,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 1bacd82cf..c1ba4a360 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 @@ -164,6 +164,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 f952bd095..f4fbf57c8 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 @@ -164,6 +164,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); diff --git a/plugin-packs/postcss-preset-env/test/basic.expect.css b/plugin-packs/postcss-preset-env/test/basic.expect.css index 27d1e48a8..3a2b5e9b6 100644 --- a/plugin-packs/postcss-preset-env/test/basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.expect.css @@ -275,6 +275,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 ffefaebfe..fd1f48df0 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css @@ -168,6 +168,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 750ac0a92..6f93d7f18 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css @@ -156,6 +156,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 ced1a2c08..62bcc0c68 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css @@ -283,6 +283,11 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + -ms-flex-order: 26; + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 b83301214..6e1f87b3a 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 @@ -273,6 +273,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 b6e11ed52..1e56d5067 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 @@ -259,6 +259,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 34fb267d8..a214545b5 100644 --- a/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css @@ -141,6 +141,10 @@ order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } 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 819fa1807..d646ebd31 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 @@ -173,6 +173,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 6c3310c42..de89ffbc6 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 @@ -161,6 +161,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); 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 26000e9bd..a9bd25c7a 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css @@ -280,6 +280,10 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te order: 26; } +.test-focus-visible-pseudo-class:focus-visible { + order: 26; +} + .test-double-position-gradients { background-image: conic-gradient(yellowgreen 40%, gold 0deg,gold 75%, #f06 0deg); background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); diff --git a/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-1.expect.css b/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-1.expect.css index eb3e1fa8a..2cdadb7a2 100644 --- a/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-1.expect.css +++ b/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-1.expect.css @@ -6,7 +6,7 @@ order: 2; } -[focus-within] { +[focus-within].js-focus-within, .js-focus-within [focus-within] { order: 3; } diff --git a/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-2.expect.css b/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-2.expect.css index 557e9e2a1..b0b16a92d 100644 --- a/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-2.expect.css +++ b/plugin-packs/postcss-preset-env/test/client-side-polyfills.stage-2.expect.css @@ -6,7 +6,7 @@ order: 2; } -[focus-within] { +[focus-within].js-focus-within, .js-focus-within [focus-within] { order: 3; } diff --git a/plugin-packs/postcss-preset-env/test/disable-client-side-polyfills.disabled.expect.css b/plugin-packs/postcss-preset-env/test/disable-client-side-polyfills.disabled.expect.css index 1e7ff7369..cd2b2b435 100644 --- a/plugin-packs/postcss-preset-env/test/disable-client-side-polyfills.disabled.expect.css +++ b/plugin-packs/postcss-preset-env/test/disable-client-side-polyfills.disabled.expect.css @@ -26,7 +26,7 @@ a:has(> img) { } } -.my-form-field[focus-within] label { +.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label { order: 4; } 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 dfbe31fde..9ac9a6736 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -453,6 +453,14 @@ h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n order: 26; } +.test-focus-visible-pseudo-class:focus-visible:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + -webkit-box-ordinal-group: 27; + -webkit-order: 26; + -moz-box-ordinal-group: 27; + -ms-flex-order: 26; + order: 26; +} + .test-double-position-gradients:not(#\#):not(#\#):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); diff --git a/plugins/css-blank-pseudo/src/browser.js b/plugins/css-blank-pseudo/src/browser.js index 5706d8713..691ce89b7 100644 --- a/plugins/css-blank-pseudo/src/browser.js +++ b/plugins/css-blank-pseudo/src/browser.js @@ -84,15 +84,18 @@ function observeValueOfHTMLElement(HTMLElement, handler) { export default function cssBlankPseudoInit(opts) { // configuration - const options = Object.assign( - // Default options - { - force: false, - replaceWith: '[blank]', - }, - // Provided options - opts, - ); + const options = { + force: false, + replaceWith: '[blank]', + }; + + if (typeof opts !== 'undefined' && 'force' in opts) { + options.force = opts.force; + } + + if (typeof opts !== 'undefined' && 'replaceWith' in opts) { + options.replaceWith = opts.replaceWith; + } if (!isValidReplacement(options.replaceWith)) { throw new Error(`${options.replaceWith} is not a valid replacement since it can't be applied to single elements.`); diff --git a/plugins/postcss-focus-visible/README.md b/plugins/postcss-focus-visible/README.md index 6f1f2c3e5..b218c1458 100644 --- a/plugins/postcss-focus-visible/README.md +++ b/plugins/postcss-focus-visible/README.md @@ -23,6 +23,9 @@ the browser's polyfill as well. :focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) { outline: none; } +:focus:not(:focus-visible) { + outline: none; +} ``` [PostCSS Focus Visible] duplicates rules using the `:focus-visible` pseudo-class @@ -59,10 +62,10 @@ instructions for: ### preserve The `preserve` option determines whether the original notation -is preserved. By default, it is not preserved. +is preserved. By default, it is preserved. ```js -postcssFocusVisible({ preserve: true }) +postcssFocusVisible({ preserve: false }) ``` ```pcss @@ -72,13 +75,8 @@ postcssFocusVisible({ preserve: true }) /* becomes */ -.foo { - color: blue; - color: red; -} - -.baz { - color: green; +:focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) { + outline: none; } ``` @@ -98,14 +96,7 @@ postcssFocusVisible({ replaceWith: '[data-focus-visible-added]' }) /* becomes */ -.foo { - color: blue; - color: red; -} - -.baz { - color: green; -} + ``` Note that if you want to keep using [focus-visible polyfill], the only diff --git a/plugins/postcss-focus-visible/docs/README.md b/plugins/postcss-focus-visible/docs/README.md index def195d90..9b8f4e205 100644 --- a/plugins/postcss-focus-visible/docs/README.md +++ b/plugins/postcss-focus-visible/docs/README.md @@ -48,10 +48,10 @@ with a `.focus-visible` class selector, the same selector used by the ### preserve The `preserve` option determines whether the original notation -is preserved. By default, it is not preserved. +is preserved. By default, it is preserved. ```js -({ preserve: true }) +({ preserve: false }) ``` ```pcss @@ -59,7 +59,7 @@ is preserved. By default, it is not preserved. /* becomes */ - + ``` ### replaceWith diff --git a/plugins/postcss-focus-visible/src/index.ts b/plugins/postcss-focus-visible/src/index.ts index 6b7151141..7589d55cc 100644 --- a/plugins/postcss-focus-visible/src/index.ts +++ b/plugins/postcss-focus-visible/src/index.ts @@ -10,7 +10,7 @@ const creator: PluginCreator = (opts?: pluginOptions) => { const options = Object.assign( // Default options { - preserve: false, + preserve: true, replaceWith: '.focus-visible', }, // Provided options @@ -22,12 +22,12 @@ const creator: PluginCreator = (opts?: pluginOptions) => { return { postcssPlugin: 'postcss-focus-visible', Rule(rule, { result }) { - if (!rule.selector.includes(PSEUDO)) { + if (!rule.selector.toLowerCase().includes(PSEUDO)) { return; } const selectors = rule.selectors.flatMap((selector) => { - if (!selector.includes(PSEUDO)) { + if (!selector.toLowerCase().includes(PSEUDO)) { return [selector]; } @@ -46,7 +46,7 @@ const creator: PluginCreator = (opts?: pluginOptions) => { let containsPseudo = false; selectorAST.walkPseudos((pseudo) => { - if (pseudo.value !== PSEUDO) { + if (pseudo.value.toLowerCase() !== PSEUDO) { return; } diff --git a/plugins/postcss-focus-visible/test/basic.css b/plugins/postcss-focus-visible/test/basic.css index a2ac10d1a..fa0cf5461 100644 --- a/plugins/postcss-focus-visible/test/basic.css +++ b/plugins/postcss-focus-visible/test/basic.css @@ -77,3 +77,7 @@ html :not(:focus-visible) { .foo > :focus-visible { order: 10.5; } + +:FocuS-VisiblE { + order: 11; +} diff --git a/plugins/postcss-focus-visible/test/basic.expect.css b/plugins/postcss-focus-visible/test/basic.expect.css index 3fed12a64..0beb9479d 100644 --- a/plugins/postcss-focus-visible/test/basic.expect.css +++ b/plugins/postcss-focus-visible/test/basic.expect.css @@ -2,6 +2,10 @@ order: 1; } +:focus-visible { + order: 1; +} + .focus-visible.js-focus-visible, .js-focus-visible .focus-visible, .focus-visible.js-focus-visible test, @@ -35,6 +39,24 @@ test.js-focus-visible :matches(test .focus-visible .focus-visible test) test, order: 2; } +:focus-visible, +:focus-visible test, +test :focus-visible, +test test:focus-visible, +html[dir="rtl"] :focus-visible, +test :focus-visible test, +test test:focus-visible test, +test :focus-visible :focus-visible test, +test :matches(:focus-visible) test, +test :matches(:focus-visible test) test, +test :matches(test :focus-visible) test, +test :matches(test test:focus-visible) test, +test :matches(test :focus-visible test) test, +test :matches(test test:focus-visible test) test, +test :matches(test :focus-visible :focus-visible test) test { + order: 2; +} + :ignore-focus-visible, :focus-visible-ignore, :ignorefocus-visible, @@ -55,42 +77,97 @@ test.js-focus-visible :matches(test .focus-visible .focus-visible test) test, order: 5; } +.escaped\:focus-visible, +.escaped\:times\:two\:focus-visible, +.escaped\:focus-visible:focus-visible, +.escaped\:times\:two:focus-visible { + order: 5; +} + html.js-focus-visible .focus-visible, .js-focus-visible html .focus-visible { order: 6; } +html :focus-visible { + order: 6; +} + html.focus-visible.js-focus-visible, .js-focus-visible html.focus-visible { order: 6.1; } +html:focus-visible { + order: 6.1; +} + :not(.focus-visible).js-focus-visible, .js-focus-visible :not(.focus-visible) { order: 7; } +:not(:focus-visible) { + order: 7; +} + html.js-focus-visible :not(.focus-visible), .js-focus-visible html :not(.focus-visible) { order: 8; } +html :not(:focus-visible) { + order: 8; +} + .focus-visible.js-focus-visible::before, .js-focus-visible .focus-visible::before { order: 10.0; } +:focus-visible::before { + order: 10.0; +} + .focus-visible.js-focus-visible .foo, .js-focus-visible .focus-visible .foo { order: 10.1; } +:focus-visible .foo { + order: 10.1; +} + .focus-visible.js-focus-visible > .foo, .js-focus-visible .focus-visible > .foo { order: 10.2; } +:focus-visible > .foo { + order: 10.2; +} + .js-focus-visible::before.focus-visible, .js-focus-visible ::before.focus-visible { order: 10.3; } +::before:focus-visible { + order: 10.3; +} + .foo.js-focus-visible .focus-visible, .js-focus-visible .foo .focus-visible { order: 10.4; } +.foo :focus-visible { + order: 10.4; +} + .foo.js-focus-visible > .focus-visible, .js-focus-visible .foo > .focus-visible { order: 10.5; } + +.foo > :focus-visible { + order: 10.5; +} + +.focus-visible.js-focus-visible, .js-focus-visible .focus-visible { + order: 11; +} + +:FocuS-VisiblE { + order: 11; +} diff --git a/plugins/postcss-focus-visible/test/basic.preserve.expect.css b/plugins/postcss-focus-visible/test/basic.preserve.expect.css index 3fed12a64..e3d0a30b3 100644 --- a/plugins/postcss-focus-visible/test/basic.preserve.expect.css +++ b/plugins/postcss-focus-visible/test/basic.preserve.expect.css @@ -94,3 +94,7 @@ html.js-focus-visible :not(.focus-visible), .js-focus-visible html :not(.focus-v .foo.js-focus-visible > .focus-visible, .js-focus-visible .foo > .focus-visible { order: 10.5; } + +.focus-visible.js-focus-visible, .js-focus-visible .focus-visible { + order: 11; +} diff --git a/plugins/postcss-focus-visible/test/basic.replacewith.expect.css b/plugins/postcss-focus-visible/test/basic.replacewith.expect.css index a5162561f..5964e5c41 100644 --- a/plugins/postcss-focus-visible/test/basic.replacewith.expect.css +++ b/plugins/postcss-focus-visible/test/basic.replacewith.expect.css @@ -2,6 +2,10 @@ order: 1; } +:focus-visible { + order: 1; +} + [data-focus-visible-added].js-focus-visible, .js-focus-visible [data-focus-visible-added], [data-focus-visible-added].js-focus-visible test, @@ -35,6 +39,24 @@ test.js-focus-visible :matches(test [data-focus-visible-added] [data-focus-visib order: 2; } +:focus-visible, +:focus-visible test, +test :focus-visible, +test test:focus-visible, +html[dir="rtl"] :focus-visible, +test :focus-visible test, +test test:focus-visible test, +test :focus-visible :focus-visible test, +test :matches(:focus-visible) test, +test :matches(:focus-visible test) test, +test :matches(test :focus-visible) test, +test :matches(test test:focus-visible) test, +test :matches(test :focus-visible test) test, +test :matches(test test:focus-visible test) test, +test :matches(test :focus-visible :focus-visible test) test { + order: 2; +} + :ignore-focus-visible, :focus-visible-ignore, :ignorefocus-visible, @@ -55,42 +77,97 @@ test.js-focus-visible :matches(test [data-focus-visible-added] [data-focus-visib order: 5; } +.escaped\:focus-visible, +.escaped\:times\:two\:focus-visible, +.escaped\:focus-visible:focus-visible, +.escaped\:times\:two:focus-visible { + order: 5; +} + html.js-focus-visible [data-focus-visible-added], .js-focus-visible html [data-focus-visible-added] { order: 6; } +html :focus-visible { + order: 6; +} + html[data-focus-visible-added].js-focus-visible, .js-focus-visible html[data-focus-visible-added] { order: 6.1; } +html:focus-visible { + order: 6.1; +} + :not([data-focus-visible-added]).js-focus-visible, .js-focus-visible :not([data-focus-visible-added]) { order: 7; } +:not(:focus-visible) { + order: 7; +} + html.js-focus-visible :not([data-focus-visible-added]), .js-focus-visible html :not([data-focus-visible-added]) { order: 8; } +html :not(:focus-visible) { + order: 8; +} + [data-focus-visible-added].js-focus-visible::before, .js-focus-visible [data-focus-visible-added]::before { order: 10.0; } +:focus-visible::before { + order: 10.0; +} + [data-focus-visible-added].js-focus-visible .foo, .js-focus-visible [data-focus-visible-added] .foo { order: 10.1; } +:focus-visible .foo { + order: 10.1; +} + [data-focus-visible-added].js-focus-visible > .foo, .js-focus-visible [data-focus-visible-added] > .foo { order: 10.2; } +:focus-visible > .foo { + order: 10.2; +} + .js-focus-visible::before[data-focus-visible-added], .js-focus-visible ::before[data-focus-visible-added] { order: 10.3; } +::before:focus-visible { + order: 10.3; +} + .foo.js-focus-visible [data-focus-visible-added], .js-focus-visible .foo [data-focus-visible-added] { order: 10.4; } +.foo :focus-visible { + order: 10.4; +} + .foo.js-focus-visible > [data-focus-visible-added], .js-focus-visible .foo > [data-focus-visible-added] { order: 10.5; } + +.foo > :focus-visible { + order: 10.5; +} + +[data-focus-visible-added].js-focus-visible, .js-focus-visible [data-focus-visible-added] { + order: 11; +} + +:FocuS-VisiblE { + order: 11; +} diff --git a/plugins/postcss-focus-visible/test/browser.expect.css b/plugins/postcss-focus-visible/test/browser.expect.css index cf0e52c08..767265c01 100644 --- a/plugins/postcss-focus-visible/test/browser.expect.css +++ b/plugins/postcss-focus-visible/test/browser.expect.css @@ -7,3 +7,7 @@ textarea { .focus-visible.js-focus-visible, .js-focus-visible .focus-visible { background-color: rgb(128, 0, 128); } + +:focus-visible { + background-color: rgb(128, 0, 128); +} diff --git a/plugins/postcss-focus-visible/test/examples/example.expect.css b/plugins/postcss-focus-visible/test/examples/example.expect.css index d2288c25d..18a648288 100644 --- a/plugins/postcss-focus-visible/test/examples/example.expect.css +++ b/plugins/postcss-focus-visible/test/examples/example.expect.css @@ -1,3 +1,6 @@ :focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) { outline: none; } +:focus:not(:focus-visible) { + outline: none; +} diff --git a/plugins/postcss-focus-visible/test/examples/example.preserve-true.expect.css b/plugins/postcss-focus-visible/test/examples/example.preserve-true.expect.css deleted file mode 100644 index 8b020470a..000000000 --- a/plugins/postcss-focus-visible/test/examples/example.preserve-true.expect.css +++ /dev/null @@ -1,8 +0,0 @@ -.foo { - color: blue; - color: red; -} - -.baz { - color: green; -} diff --git a/plugins/postcss-focus-visible/test/examples/example.replacewith.expect.css b/plugins/postcss-focus-visible/test/examples/example.replacewith.expect.css index 9e6327e76..ef000b459 100644 --- a/plugins/postcss-focus-visible/test/examples/example.replacewith.expect.css +++ b/plugins/postcss-focus-visible/test/examples/example.replacewith.expect.css @@ -1,3 +1,6 @@ :focus:not([focus-visible]).js-focus-visible, .js-focus-visible :focus:not([focus-visible]) { outline: none; } +:focus:not(:focus-visible) { + outline: none; +} diff --git a/plugins/postcss-focus-within/.gitignore b/plugins/postcss-focus-within/.gitignore index 17847a362..7172b04f1 100644 --- a/plugins/postcss-focus-within/.gitignore +++ b/plugins/postcss-focus-within/.gitignore @@ -1,12 +1,6 @@ node_modules -dist package-lock.json yarn.lock -*.log* *.result.css *.result.css.map -!.editorconfig -!.gitignore -!.rollup.js -!.tape.js -!.travis.yml +dist/* diff --git a/plugins/postcss-focus-within/.tape.mjs b/plugins/postcss-focus-within/.tape.mjs index 35acb5355..91561fece 100644 --- a/plugins/postcss-focus-within/.tape.mjs +++ b/plugins/postcss-focus-within/.tape.mjs @@ -3,25 +3,46 @@ import plugin from 'postcss-focus-within'; postcssTape(plugin)({ 'basic': { - message: 'supports basic usage' + message: 'supports basic usage', }, 'basic:replacewith': { message: 'supports { replaceWith: ".focus-within" } usage', options: { - replaceWith: '.focus-within' - } + replaceWith: '.focus-within', + }, }, 'basic:preserve': { message: 'supports { preserve: false } usage', options: { - preserve: false - } + preserve: false, + }, }, 'generated-selector-cases': { message: 'correctly handles generated cases', warnings: 1, + }, + 'examples/example': { + message: 'minimal example', + }, + 'examples/example:preserve-false': { + message: 'minimal example', + options: { + preserve: false, + }, + }, + 'examples/example:replacewith': { + message: 'minimal example', + options: { + replaceWith: '.focus-within', + }, + }, + 'browser': { + message: 'css for browser tests', + }, + 'browser:replacewith': { + message: 'css for browser tests', options: { - preserve: false - } + replaceWith: '.focus-within', + }, }, }); diff --git a/plugins/postcss-focus-within/CHANGELOG.md b/plugins/postcss-focus-within/CHANGELOG.md index 5f4507b5d..7c40529c9 100644 --- a/plugins/postcss-focus-within/CHANGELOG.md +++ b/plugins/postcss-focus-within/CHANGELOG.md @@ -1,5 +1,11 @@ # Changes to PostCSS Focus Within +### Unreleased (major) + +- Breaking: Changed generated classes so it prepends `.js-focus-within` to the +generated class so CSS is applied when the polyfill is known to be running. +- Added: Now bundling browser polyfill. + ### 5.0.4 (February 5, 2022) - Improved `es module` and `commonjs` compatibility diff --git a/plugins/postcss-focus-within/README.md b/plugins/postcss-focus-within/README.md index 8fe6d8619..a38a13ed6 100644 --- a/plugins/postcss-focus-within/README.md +++ b/plugins/postcss-focus-within/README.md @@ -1,36 +1,28 @@ # PostCSS Focus Within [PostCSS Logo][postcss] -[npm version][npm-url] -[CSS Standard Status][css-url] -[Build Status][cli-url] -[Discord][discord] +[npm version][npm-url] [CSS Standard Status][css-url] [Build Status][cli-url] [Discord][discord] -[PostCSS Focus Within] lets you use the `:focus-within` pseudo-class in CSS, +[PostCSS Focus Within] lets you use the `:focus-within` pseudo-class in CSS, following the [Selectors Level 4 specification]. -It is the companion to the [focus-within polyfill]. - -[!['Can I use' table](https://caniuse.bitsofco.de/image/css-focus-within.png)](https://caniuse.com/#feat=css-focus-within) - -```css +```pcss .my-form-field:focus-within label { - background-color: yellow; + background-color: yellow; } /* becomes */ -.my-form-field[focus-within] label { - background-color: yellow; +.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label { + background-color: yellow; } - .my-form-field:focus-within label { - background-color: yellow; + background-color: yellow; } ``` [PostCSS Focus Within] duplicates rules using the `:focus-within` pseudo-class with a `[focus-within]` attribute selector, the same selector used by the -[focus-within polyfill]. This replacement selector can be changed using the +focus-within polyfill. This replacement selector can be changed using the `replaceWith` option. Also, the preservation of the original `:focus-within` rule can be disabled using the `preserve` option. @@ -42,22 +34,14 @@ Add [PostCSS Focus Within] to your project: npm install postcss postcss-focus-within --save-dev ``` -Use [PostCSS Focus Within] to process your CSS: - -```js -const postcssFocusWithin = require('postcss-focus-within'); - -postcssFocusWithin.process(YOUR_CSS /*, processOptions, pluginOptions */); -``` - -Or use it as a [PostCSS] plugin: +Use it as a [PostCSS] plugin: ```js const postcss = require('postcss'); const postcssFocusWithin = require('postcss-focus-within'); postcss([ - postcssFocusWithin(/* pluginOptions */) + postcssFocusWithin(/* pluginOptions */) ]).process(YOUR_CSS /*, processOptions */); ``` @@ -71,22 +55,22 @@ instructions for: ### preserve -The `preserve` option defines whether the original selector should remain. By -default, the original selector is preserved. +The `preserve` option determines whether the original notation +is preserved. By default, it is preserved. ```js -focusWithin({ preserve: false }); +postcssFocusWithin({ preserve: false }) ``` -```css +```pcss .my-form-field:focus-within label { - background-color: yellow; + background-color: yellow; } /* becomes */ -.my-form-field[focus-within] label { - background-color: yellow; +.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label { + background-color: yellow; } ``` @@ -96,34 +80,77 @@ The `replaceWith` option defines the selector to replace `:focus-within`. By default, the replacement selector is `[focus-within]`. ```js -focusWithin({ replaceWith: '.focus-within' }); +postcssFocusWithin({ replaceWith: '.focus-within' }); ``` -```css +```pcss .my-form-field:focus-within label { - background-color: yellow; + background-color: yellow; } /* becomes */ -.my-form-field.focus-within label { - background-color: yellow; +.my-form-field.focus-within.js-focus-within label, .js-focus-within .my-form-field.focus-within label { + background-color: yellow; } - .my-form-field:focus-within label { - background-color: yellow; + background-color: yellow; } ``` +Note that changing this option implies that it needs to be passed to the +browser polyfill as well. + +## Browser + +```js +import focusWithinInit from 'postcss-focus-within/browser'; + +focusWithinInit(); +``` + +or + +```html + + + +``` + +[PostCSS Focus Within] works in all major browsers, including Safari 6+ and +Internet Explorer 9+ without any additional polyfills. + +### Browser Usage + +#### force + +The `force` option determines whether the library runs even if the browser +supports the selector or not. By default, it won't run if the browser does +support the selector. + +```js +focusWithinInit({ force: true }); +``` + +#### replaceWith + +Similar to the option for the PostCSS Plugin, `replaceWith` determines the +attribute or class to apply to an element when it's considered to be `:focus-within`. + +```js +focusWithinInit({ replaceWith: '.focus-within }); +``` + +This option should be used if it was changed at PostCSS configuration level. + +[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test [css-url]: https://cssdb.org/#focus-within-pseudo-class -[cli-url]: https://github.com/csstools/postcss-plugins/tree/main/postcss-focus-within/actions/workflows/test.yml?query=workflow/test [discord]: https://discord.gg/bUadyRwkJS [npm-url]: https://www.npmjs.com/package/postcss-focus-within -[focus-within polyfill]: https://github.com/jsxtools/focus-within [Gulp PostCSS]: https://github.com/postcss/gulp-postcss [Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss [PostCSS]: https://github.com/postcss/postcss -[PostCSS Focus Within]: https://github.com/csstools/postcss-plugins/tree/main/postcss-focus-within [PostCSS Loader]: https://github.com/postcss/postcss-loader +[PostCSS Focus Within]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within [Selectors Level 4 specification]: https://www.w3.org/TR/selectors-4/#the-focus-within-pseudo diff --git a/plugins/postcss-focus-within/docs/README.md b/plugins/postcss-focus-within/docs/README.md new file mode 100644 index 000000000..cd8d22648 --- /dev/null +++ b/plugins/postcss-focus-within/docs/README.md @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + +
+ +[] lets you use the `:focus-within` pseudo-class in CSS, +following the [Selectors Level 4 specification]. + +```pcss + + +/* becomes */ + + +``` + +[] duplicates rules using the `:focus-within` pseudo-class +with a `[focus-within]` attribute selector, the same selector used by the +focus-within polyfill. This replacement selector can be changed using the +`replaceWith` option. Also, the preservation of the original `:focus-within` +rule can be disabled using the `preserve` option. + + + + + +## Options + +### preserve + +The `preserve` option determines whether the original notation +is preserved. By default, it is preserved. + +```js +({ preserve: false }) +``` + +```pcss + + +/* becomes */ + + +``` + +### replaceWith + +The `replaceWith` option defines the selector to replace `:focus-within`. By +default, the replacement selector is `[focus-within]`. + +```js +({ replaceWith: '.focus-within' }); +``` + +```pcss + + +/* becomes */ + + +``` + +Note that changing this option implies that it needs to be passed to the +browser polyfill as well. + +## Browser + +```js +import focusWithinInit from 'postcss-focus-within/browser'; + +focusWithinInit(); +``` + +or + +```html + + + +``` + +[] works in all major browsers, including Safari 6+ and +Internet Explorer 9+ without any additional polyfills. + +### Browser Usage + +#### force + +The `force` option determines whether the library runs even if the browser +supports the selector or not. By default, it won't run if the browser does +support the selector. + +```js +focusWithinInit({ force: true }); +``` + +#### replaceWith + +Similar to the option for the PostCSS Plugin, `replaceWith` determines the +attribute or class to apply to an element when it's considered to be `:focus-within`. + +```js +focusWithinInit({ replaceWith: '.focus-within }); +``` + +This option should be used if it was changed at PostCSS configuration level. + + +[Selectors Level 4 specification]: diff --git a/plugins/postcss-focus-within/package.json b/plugins/postcss-focus-within/package.json index f2c97d87e..64224f596 100644 --- a/plugins/postcss-focus-within/package.json +++ b/plugins/postcss-focus-within/package.json @@ -2,7 +2,21 @@ "name": "postcss-focus-within", "description": "Use the :focus-within pseudo-selector in CSS", "version": "5.0.4", - "author": "Jonathan Neal ", + "contributors": [ + { + "name": "Antonio Laguna", + "email": "antonio@laguna.es", + "url": "https://antonio.laguna.es" + }, + { + "name": "Romain Menke", + "email": "romainmenke@gmail.com" + }, + { + "name": "Jonathan Neal", + "email": "jonathantneal@hotmail.com" + } + ], "license": "CC0-1.0", "funding": { "type": "opencollective", @@ -19,6 +33,14 @@ "import": "./dist/index.mjs", "require": "./dist/index.cjs", "default": "./dist/index.mjs" + }, + "./browser": { + "import": "./dist/browser.mjs", + "require": "./dist/browser.cjs", + "default": "./dist/browser.mjs" + }, + "./browser-global": { + "default": "./dist/browser-global.js" } }, "files": [ @@ -36,12 +58,13 @@ "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", "prepublishOnly": "npm run clean && npm run build && npm run test", "test": "node .tape.mjs && npm run test:exports", + "test:browser": "node ./test/_browser.mjs", "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs", "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs" }, @@ -67,8 +90,10 @@ "within" ], "csstools": { + "cssdbId": "focus-within-pseudo-class", "exportName": "postcssFocusWithin", - "humanReadableName": "PostCSS Focus Within" + "humanReadableName": "PostCSS Focus Within", + "specUrl": "https://www.w3.org/TR/selectors-4/#the-focus-within-pseudo" }, "volta": { "extends": "../../package.json" diff --git a/plugins/postcss-focus-within/src/browser-global.js b/plugins/postcss-focus-within/src/browser-global.js new file mode 100644 index 000000000..7c6d41bd7 --- /dev/null +++ b/plugins/postcss-focus-within/src/browser-global.js @@ -0,0 +1,3 @@ +/* global self */ +import { default as focusWithinInit } from './browser'; +self.focusWithinInit = focusWithinInit; diff --git a/plugins/postcss-focus-within/src/browser.js b/plugins/postcss-focus-within/src/browser.js new file mode 100644 index 000000000..6a225a7bd --- /dev/null +++ b/plugins/postcss-focus-within/src/browser.js @@ -0,0 +1,78 @@ +/* global document */ +import isValidReplacement from './is-valid-replacement.mjs'; +function generateHandler(replaceWith) { + let selector; + let remove; + let add; + const lastElements = []; + + if (replaceWith[0] === '.') { + selector = replaceWith.slice(1); + remove = (el) => el.classList.remove(selector); + add = (el) => el.classList.add(selector); + } else { + // A bit naive + selector = replaceWith.slice(1, -1); + remove = (el) => el.removeAttribute(selector, ''); + add = (el) => el.setAttribute(selector, ''); + } + + return function handleFocusChange() { + lastElements.forEach(lastElement => remove(lastElement)); + lastElements.length = 0; + + let activeElement = document.activeElement; + + // only add focus if it has not been added and is not the document element + if (!/^(#document|HTML|BODY)$/.test(Object(activeElement).nodeName)) { + while (activeElement && activeElement.nodeType === 1) { + add(activeElement); + lastElements.push(activeElement); + + activeElement = activeElement.parentNode; + } + } + }; +} + +export default function focusWithin(opts) { + // configuration + const options = { + force: false, + replaceWith: '[focus-within]', + }; + + if (typeof opts !== 'undefined' && 'force' in opts) { + options.force = opts.force; + } + + if (typeof opts !== 'undefined' && 'replaceWith' in opts) { + options.replaceWith = opts.replaceWith; + } + + if (!isValidReplacement(options.replaceWith)) { + throw new Error(`${options.replaceWith} is not a valid replacement since it can't be applied to single elements.`); + } + + try { + document.querySelector(':focus-within'); + + if (!options.force) { + return; + } + } catch (ignoredError) { /* do nothing and continue */ } + + const handleFocusChange = generateHandler(options.replaceWith); + + const initialize = function initializeEventListeners() { + document.documentElement.classList.add('js-focus-within'); + document.addEventListener('focus', handleFocusChange, true); + document.addEventListener('blur', handleFocusChange, true); + }; + + if (document.readyState === 'complete') { + initialize(); + } else { + document.addEventListener('DOMContentLoaded', initialize); + } +} diff --git a/plugins/postcss-focus-within/src/index.ts b/plugins/postcss-focus-within/src/index.ts index d523eac34..dd2bd03c4 100644 --- a/plugins/postcss-focus-within/src/index.ts +++ b/plugins/postcss-focus-within/src/index.ts @@ -1,55 +1,121 @@ import parser from 'postcss-selector-parser'; import type { PluginCreator } from 'postcss'; +import isValidReplacement from './is-valid-replacement.mjs'; -const creator: PluginCreator<{ preserve?: boolean, replaceWith?: string }> = (opts?: { preserve?: boolean, replaceWith?: string }) => { - const replaceWith = String(Object(opts).replaceWith || '[focus-within]'); - const preserve = Boolean('preserve' in Object(opts) ? opts.preserve : true); - const replacementAST = parser().astSync(replaceWith); +type pluginOptions = { preserve?: boolean, replaceWith?: string }; + +const POLYFILL_READY_CLASSNAME = 'js-focus-within'; +const PSEUDO = ':focus-within'; + +const creator: PluginCreator = (opts?: pluginOptions) => { + const options = Object.assign( + // Default options + { + preserve: true, + replaceWith: '[focus-within]', + }, + // Provided options + opts, + ); + + const replacementAST = parser().astSync(options.replaceWith); + if (!isValidReplacement(options.replaceWith)) { + return { + postcssPlugin: 'postcss-focus-within', + Once: (root, { result }) => { + root.warn( + result, + `${options.replaceWith} is not a valid replacement since it can't be applied to single elements.`, + ); + }, + }; + } return { postcssPlugin: 'postcss-focus-within', - Rule: (rule, { result })=> { - if (!rule.selector.includes(':focus-within')) { + Rule(rule, { result }) { + if (!rule.selector.toLowerCase().includes(PSEUDO)) { return; } - let modifiedSelector; + const selectors = rule.selectors.flatMap((selector) => { + if (!selector.toLowerCase().includes(PSEUDO)) { + return [selector]; + } - try { - const modifiedSelectorAST = parser((selectors) => { - selectors.walkPseudos((pseudo) => { - if (pseudo.value !== ':focus-within') { - return; - } + let selectorAST; - if (pseudo.nodes && pseudo.nodes.length) { - return; - } + try { + selectorAST = parser().astSync(selector); + } catch (_) { + rule.warn(result, `Failed to parse selector : ${selector}`); + return selector; + } - pseudo.replaceWith(replacementAST.clone({})); - }); - }).processSync(rule.selector); + if (typeof selectorAST === 'undefined') { + return [selector]; + } - modifiedSelector = String(modifiedSelectorAST); - } catch (_) { - rule.warn(result, `Failed to parse selector : ${rule.selector}`); - return; - } + let containsPseudo = false; + selectorAST.walkPseudos((pseudo) => { + if (pseudo.value.toLowerCase() !== PSEUDO) { + return; + } - if (typeof modifiedSelector === 'undefined') { - return; - } + if (pseudo.nodes && pseudo.nodes.length) { + return; + } + + containsPseudo = true; + pseudo.replaceWith(replacementAST.clone({})); + }); + + if (!containsPseudo) { + return [selector]; + } + + const selectorASTClone = selectorAST.clone(); + + // html > .foo:focus-within + // becomes: + // html.js-focus-within > .foo:focus-within, + // .js-focus-within html > .foo:focus-within + { + if (selectorAST.nodes?.[0]?.nodes?.length) { + for (let i = 0; i < selectorAST.nodes[0].nodes.length; i++) { + const node = selectorAST.nodes[0].nodes[i]; + if (node.type === 'combinator' || parser.isPseudoElement(node)) { + // Insert the class before the first combinator or pseudo element. + selectorAST.nodes[0].insertBefore(node, parser.className({ value: POLYFILL_READY_CLASSNAME })); + break; + } + + if (i === selectorAST.nodes[0].nodes.length - 1) { + // Append the class to the end of the selector if not combinator or pseudo element was found. + selectorAST.nodes[0].append(parser.className({ value: POLYFILL_READY_CLASSNAME })); + break; + } + } + } + + if (selectorAST.nodes?.[0]?.nodes) { + // Prepend a space combinator and the class to the beginning of the selector. + selectorASTClone.nodes[0].prepend(parser.combinator({ value: ' ' })); + selectorASTClone.nodes[0].prepend(parser.className({ value: POLYFILL_READY_CLASSNAME })); + } + } + + return [selectorAST.toString(), selectorASTClone.toString()]; + }); - if (modifiedSelector === rule.selector) { + if (selectors.join(',') === rule.selectors.join(',')) { return; } - const clone = rule.clone({ selector: modifiedSelector }); + rule.cloneBefore({ selectors: selectors }); - if (preserve) { - rule.before(clone); - } else { - rule.replaceWith(clone); + if (!options.preserve) { + rule.remove(); } }, }; diff --git a/plugins/postcss-focus-within/src/is-valid-replacement.mjs b/plugins/postcss-focus-within/src/is-valid-replacement.mjs new file mode 100644 index 000000000..ebcf65a12 --- /dev/null +++ b/plugins/postcss-focus-within/src/is-valid-replacement.mjs @@ -0,0 +1,24 @@ +const INVALID_SELECTOR_CHAR = [ + ' ', // Can't use child selector + '>', // Can't use direct child selector + '~', // Can't use sibling selector + ':', // Can't use pseudo selector + '+', // Can't use adjacent selector + '@', // Can't use at + '#', // Can't use id selector + '(', // Can't use parenthesis + ')', // Can't use parenthesis +]; + +export default function isValidReplacement(selector) { + let isValid = true; + + // Purposely archaic so it's interoperable in old browsers + for (let i = 0, length = INVALID_SELECTOR_CHAR.length; i < length && isValid; i++) { + if (selector.indexOf(INVALID_SELECTOR_CHAR[i]) > -1) { + isValid = false; + } + } + + return isValid; +} diff --git a/plugins/postcss-focus-within/test/_browser.html b/plugins/postcss-focus-within/test/_browser.html new file mode 100644 index 000000000..c18455734 --- /dev/null +++ b/plugins/postcss-focus-within/test/_browser.html @@ -0,0 +1,43 @@ + + + + + + + + + + + +
+ + +
+ + +
+ +
+
+
+ + + + diff --git a/plugins/postcss-focus-within/test/_browser.mjs b/plugins/postcss-focus-within/test/_browser.mjs new file mode 100644 index 000000000..3a2c9c5cb --- /dev/null +++ b/plugins/postcss-focus-within/test/_browser.mjs @@ -0,0 +1,160 @@ +/* global window */ +import puppeteer from 'puppeteer'; +import http from 'http'; +import { promises as fsp } from 'fs'; + +(async () => { + const requestListener = async function (req, res) { + + const parsedUrl = new URL(req.url, 'http://localhost:8080'); + const pathname = parsedUrl.pathname; + + switch (pathname) { + case '': + case '/': + res.setHeader('Content-type', 'text/html'); + res.writeHead(200); + res.end(await fsp.readFile('test/_browser.html', 'utf8')); + break; + case '/test/browser.expect.css': + res.setHeader('Content-type', 'text/css'); + res.writeHead(200); + res.end(await fsp.readFile('test/browser.expect.css', 'utf8')); + break; + case '/dist/browser-global.js': + res.setHeader('Content-type', 'text/javascript'); + res.writeHead(200); + res.end(await fsp.readFile('dist/browser-global.js', 'utf8')); + break; + case '/replace-with': + res.setHeader('Content-type', 'text/html'); + res.writeHead(200); + res.end(await fsp.readFile('test/_browser_replace.html', 'utf8')); + break; + case '/test/browser.replacewith.expect.css': + res.setHeader('Content-type', 'text/css'); + res.writeHead(200); + res.end(await fsp.readFile('test/browser.replacewith.expect.css', 'utf8')); + break; + default: + res.setHeader('Content-type', 'text/plain' ); + res.writeHead(404); + res.end('Not found'); + break; + } + }; + + // Use different servers for HTML/CSS/JS to trigger CORS + const server = http.createServer(requestListener); + server.listen(8080); + + if (!process.env.DEBUG) { + const browser = await puppeteer.launch({ + headless: true, + }); + + const page = await browser.newPage(); + page.on('pageerror', (msg) => { + throw msg; + }); + + // Default + { + await page.goto('http://localhost:8080'); + + await page.evaluate(async () => window._focusWithinInit({ force: true })); + + // None of the elements should have styles + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + + await page.click('#a-grand-parent-input'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', true)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + + await page.click('#a-parent-input'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', true)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + + await page.click('#a-child-input'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', true)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', true)); + + await page.keyboard.press('Tab'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + } + + // Replace with + { + await page.goto('http://localhost:8080/replace-with'); + + await page.evaluate(async () => window._focusWithinInit({ force: true, replaceWith: '.focus-within' })); + + // None of the elements should have styles + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + + await page.click('#a-grand-parent-input'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', true)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + + await page.click('#a-parent-input'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', true)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + + await page.click('#a-child-input'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', true)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', true)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', true)); + + await page.keyboard.press('Tab'); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-grand-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent', false)); + await page.evaluate(async () => window.checkElement('default', 'a-parent-input', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child', false)); + await page.evaluate(async () => window.checkElement('default', 'a-child-input', false)); + } + + await browser.close(); + await server.close(); + } else { + console.log('visit : http://localhost:8080'); + } +})(); diff --git a/plugins/postcss-focus-within/test/_browser_replace.html b/plugins/postcss-focus-within/test/_browser_replace.html new file mode 100644 index 000000000..5cc5b1eaf --- /dev/null +++ b/plugins/postcss-focus-within/test/_browser_replace.html @@ -0,0 +1,43 @@ + + + + + + + + + + + +
+ + +
+ + +
+ +
+
+
+ + + + diff --git a/plugins/postcss-focus-within/test/basic.css b/plugins/postcss-focus-within/test/basic.css index f41cae99d..003162925 100644 --- a/plugins/postcss-focus-within/test/basic.css +++ b/plugins/postcss-focus-within/test/basic.css @@ -36,3 +36,7 @@ test :matches(test :focus-within :focus-within test) test { .escaped\:times\:two:focus-within { order: 5; } + +:FocuS-WithiN { + order: 6; +} diff --git a/plugins/postcss-focus-within/test/basic.expect.css b/plugins/postcss-focus-within/test/basic.expect.css index 36e0cb295..e85b1630c 100644 --- a/plugins/postcss-focus-within/test/basic.expect.css +++ b/plugins/postcss-focus-within/test/basic.expect.css @@ -1,4 +1,4 @@ -[focus-within] { +[focus-within].js-focus-within, .js-focus-within [focus-within] { order: 1; } @@ -6,19 +6,34 @@ order: 1; } -[focus-within],[focus-within] test, -test [focus-within], -test test[focus-within], -test [focus-within] test, -test test[focus-within] test, -test [focus-within] [focus-within] test, -test :matches([focus-within]) test, -test :matches([focus-within] test) test, -test :matches(test [focus-within]) test, -test :matches(test test[focus-within]) test, -test :matches(test [focus-within] test) test, -test :matches(test test[focus-within] test) test, -test :matches(test [focus-within] [focus-within] test) test { +[focus-within].js-focus-within, +.js-focus-within [focus-within], +[focus-within].js-focus-within test, +.js-focus-within [focus-within] test, +test.js-focus-within [focus-within], +.js-focus-within test [focus-within], +test.js-focus-within test[focus-within], +.js-focus-within test test[focus-within], +test.js-focus-within [focus-within] test, +.js-focus-within test [focus-within] test, +test.js-focus-within test[focus-within] test, +.js-focus-within test test[focus-within] test, +test.js-focus-within [focus-within] [focus-within] test, +.js-focus-within test [focus-within] [focus-within] test, +test.js-focus-within :matches([focus-within]) test, +.js-focus-within test :matches([focus-within]) test, +test.js-focus-within :matches([focus-within] test) test, +.js-focus-within test :matches([focus-within] test) test, +test.js-focus-within :matches(test [focus-within]) test, +.js-focus-within test :matches(test [focus-within]) test, +test.js-focus-within :matches(test test[focus-within]) test, +.js-focus-within test :matches(test test[focus-within]) test, +test.js-focus-within :matches(test [focus-within] test) test, +.js-focus-within test :matches(test [focus-within] test) test, +test.js-focus-within :matches(test test[focus-within] test) test, +.js-focus-within test :matches(test test[focus-within] test) test, +test.js-focus-within :matches(test [focus-within] [focus-within] test) test, +.js-focus-within test :matches(test [focus-within] [focus-within] test) test { order: 2; } @@ -52,8 +67,10 @@ test :matches(test :focus-within :focus-within test) test { .escaped\:focus-within, .escaped\:times\:two\:focus-within, -.escaped\:focus-within[focus-within], -.escaped\:times\:two[focus-within] { +.escaped\:focus-within[focus-within].js-focus-within, +.js-focus-within .escaped\:focus-within[focus-within], +.escaped\:times\:two[focus-within].js-focus-within, +.js-focus-within .escaped\:times\:two[focus-within] { order: 5; } @@ -63,3 +80,11 @@ test :matches(test :focus-within :focus-within test) test { .escaped\:times\:two:focus-within { order: 5; } + +[focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 6; +} + +:FocuS-WithiN { + order: 6; +} diff --git a/plugins/postcss-focus-within/test/basic.preserve.expect.css b/plugins/postcss-focus-within/test/basic.preserve.expect.css index 1fba9c4a0..034a0d288 100644 --- a/plugins/postcss-focus-within/test/basic.preserve.expect.css +++ b/plugins/postcss-focus-within/test/basic.preserve.expect.css @@ -1,20 +1,35 @@ -[focus-within] { +[focus-within].js-focus-within, .js-focus-within [focus-within] { order: 1; } -[focus-within],[focus-within] test, -test [focus-within], -test test[focus-within], -test [focus-within] test, -test test[focus-within] test, -test [focus-within] [focus-within] test, -test :matches([focus-within]) test, -test :matches([focus-within] test) test, -test :matches(test [focus-within]) test, -test :matches(test test[focus-within]) test, -test :matches(test [focus-within] test) test, -test :matches(test test[focus-within] test) test, -test :matches(test [focus-within] [focus-within] test) test { +[focus-within].js-focus-within, +.js-focus-within [focus-within], +[focus-within].js-focus-within test, +.js-focus-within [focus-within] test, +test.js-focus-within [focus-within], +.js-focus-within test [focus-within], +test.js-focus-within test[focus-within], +.js-focus-within test test[focus-within], +test.js-focus-within [focus-within] test, +.js-focus-within test [focus-within] test, +test.js-focus-within test[focus-within] test, +.js-focus-within test test[focus-within] test, +test.js-focus-within [focus-within] [focus-within] test, +.js-focus-within test [focus-within] [focus-within] test, +test.js-focus-within :matches([focus-within]) test, +.js-focus-within test :matches([focus-within]) test, +test.js-focus-within :matches([focus-within] test) test, +.js-focus-within test :matches([focus-within] test) test, +test.js-focus-within :matches(test [focus-within]) test, +.js-focus-within test :matches(test [focus-within]) test, +test.js-focus-within :matches(test test[focus-within]) test, +.js-focus-within test :matches(test test[focus-within]) test, +test.js-focus-within :matches(test [focus-within] test) test, +.js-focus-within test :matches(test [focus-within] test) test, +test.js-focus-within :matches(test test[focus-within] test) test, +.js-focus-within test :matches(test test[focus-within] test) test, +test.js-focus-within :matches(test [focus-within] [focus-within] test) test, +.js-focus-within test :matches(test [focus-within] [focus-within] test) test { order: 2; } @@ -31,7 +46,13 @@ test :matches(test [focus-within] [focus-within] test) test { .escaped\:focus-within, .escaped\:times\:two\:focus-within, -.escaped\:focus-within[focus-within], -.escaped\:times\:two[focus-within] { +.escaped\:focus-within[focus-within].js-focus-within, +.js-focus-within .escaped\:focus-within[focus-within], +.escaped\:times\:two[focus-within].js-focus-within, +.js-focus-within .escaped\:times\:two[focus-within] { order: 5; } + +[focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 6; +} diff --git a/plugins/postcss-focus-within/test/basic.replacewith.expect.css b/plugins/postcss-focus-within/test/basic.replacewith.expect.css index f2856487d..5a7666a11 100644 --- a/plugins/postcss-focus-within/test/basic.replacewith.expect.css +++ b/plugins/postcss-focus-within/test/basic.replacewith.expect.css @@ -1,4 +1,4 @@ -.focus-within { +.focus-within.js-focus-within, .js-focus-within .focus-within { order: 1; } @@ -6,19 +6,34 @@ order: 1; } -.focus-within,.focus-within test, -test .focus-within, -test test.focus-within, -test .focus-within test, -test test.focus-within test, -test .focus-within .focus-within test, -test :matches(.focus-within) test, -test :matches(.focus-within test) test, -test :matches(test .focus-within) test, -test :matches(test test.focus-within) test, -test :matches(test .focus-within test) test, -test :matches(test test.focus-within test) test, -test :matches(test .focus-within .focus-within test) test { +.focus-within.js-focus-within, +.js-focus-within .focus-within, +.focus-within.js-focus-within test, +.js-focus-within .focus-within test, +test.js-focus-within .focus-within, +.js-focus-within test .focus-within, +test.js-focus-within test.focus-within, +.js-focus-within test test.focus-within, +test.js-focus-within .focus-within test, +.js-focus-within test .focus-within test, +test.js-focus-within test.focus-within test, +.js-focus-within test test.focus-within test, +test.js-focus-within .focus-within .focus-within test, +.js-focus-within test .focus-within .focus-within test, +test.js-focus-within :matches(.focus-within) test, +.js-focus-within test :matches(.focus-within) test, +test.js-focus-within :matches(.focus-within test) test, +.js-focus-within test :matches(.focus-within test) test, +test.js-focus-within :matches(test .focus-within) test, +.js-focus-within test :matches(test .focus-within) test, +test.js-focus-within :matches(test test.focus-within) test, +.js-focus-within test :matches(test test.focus-within) test, +test.js-focus-within :matches(test .focus-within test) test, +.js-focus-within test :matches(test .focus-within test) test, +test.js-focus-within :matches(test test.focus-within test) test, +.js-focus-within test :matches(test test.focus-within test) test, +test.js-focus-within :matches(test .focus-within .focus-within test) test, +.js-focus-within test :matches(test .focus-within .focus-within test) test { order: 2; } @@ -52,8 +67,10 @@ test :matches(test :focus-within :focus-within test) test { .escaped\:focus-within, .escaped\:times\:two\:focus-within, -.escaped\:focus-within.focus-within, -.escaped\:times\:two.focus-within { +.escaped\:focus-within.focus-within.js-focus-within, +.js-focus-within .escaped\:focus-within.focus-within, +.escaped\:times\:two.focus-within.js-focus-within, +.js-focus-within .escaped\:times\:two.focus-within { order: 5; } @@ -63,3 +80,11 @@ test :matches(test :focus-within :focus-within test) test { .escaped\:times\:two:focus-within { order: 5; } + +.focus-within.js-focus-within, .js-focus-within .focus-within { + order: 6; +} + +:FocuS-WithiN { + order: 6; +} diff --git a/plugins/postcss-focus-within/test/browser.css b/plugins/postcss-focus-within/test/browser.css new file mode 100644 index 000000000..1860c200a --- /dev/null +++ b/plugins/postcss-focus-within/test/browser.css @@ -0,0 +1,11 @@ +div { + padding: 2em; +} + +div:focus-within { + background-color: rgb(128, 0, 128); +} + +input:focus-within { + background-color: rgb(0, 128, 0); +} diff --git a/plugins/postcss-focus-within/test/browser.expect.css b/plugins/postcss-focus-within/test/browser.expect.css new file mode 100644 index 000000000..0d9156ca7 --- /dev/null +++ b/plugins/postcss-focus-within/test/browser.expect.css @@ -0,0 +1,19 @@ +div { + padding: 2em; +} + +div[focus-within].js-focus-within, .js-focus-within div[focus-within] { + background-color: rgb(128, 0, 128); +} + +div:focus-within { + background-color: rgb(128, 0, 128); +} + +input[focus-within].js-focus-within, .js-focus-within input[focus-within] { + background-color: rgb(0, 128, 0); +} + +input:focus-within { + background-color: rgb(0, 128, 0); +} diff --git a/plugins/postcss-focus-within/test/browser.replacewith.expect.css b/plugins/postcss-focus-within/test/browser.replacewith.expect.css new file mode 100644 index 000000000..5e2ad9944 --- /dev/null +++ b/plugins/postcss-focus-within/test/browser.replacewith.expect.css @@ -0,0 +1,19 @@ +div { + padding: 2em; +} + +div.focus-within.js-focus-within, .js-focus-within div.focus-within { + background-color: rgb(128, 0, 128); +} + +div:focus-within { + background-color: rgb(128, 0, 128); +} + +input.focus-within.js-focus-within, .js-focus-within input.focus-within { + background-color: rgb(0, 128, 0); +} + +input:focus-within { + background-color: rgb(0, 128, 0); +} diff --git a/plugins/postcss-focus-within/test/examples/example.css b/plugins/postcss-focus-within/test/examples/example.css new file mode 100644 index 000000000..c3c728c3b --- /dev/null +++ b/plugins/postcss-focus-within/test/examples/example.css @@ -0,0 +1,3 @@ +.my-form-field:focus-within label { + background-color: yellow; +} diff --git a/plugins/postcss-focus-within/test/examples/example.expect.css b/plugins/postcss-focus-within/test/examples/example.expect.css new file mode 100644 index 000000000..fe6084d56 --- /dev/null +++ b/plugins/postcss-focus-within/test/examples/example.expect.css @@ -0,0 +1,6 @@ +.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label { + background-color: yellow; +} +.my-form-field:focus-within label { + background-color: yellow; +} diff --git a/plugins/postcss-focus-within/test/examples/example.preserve-false.expect.css b/plugins/postcss-focus-within/test/examples/example.preserve-false.expect.css new file mode 100644 index 000000000..1188030bd --- /dev/null +++ b/plugins/postcss-focus-within/test/examples/example.preserve-false.expect.css @@ -0,0 +1,3 @@ +.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label { + background-color: yellow; +} diff --git a/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css b/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css new file mode 100644 index 000000000..cab94c735 --- /dev/null +++ b/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css @@ -0,0 +1,6 @@ +.my-form-field.focus-within.js-focus-within label, .js-focus-within .my-form-field.focus-within label { + background-color: yellow; +} +.my-form-field:focus-within label { + background-color: yellow; +} diff --git a/plugins/postcss-focus-within/test/generated-selector-cases.expect.css b/plugins/postcss-focus-within/test/generated-selector-cases.expect.css index 25299452c..b3fb1623e 100644 --- a/plugins/postcss-focus-within/test/generated-selector-cases.expect.css +++ b/plugins/postcss-focus-within/test/generated-selector-cases.expect.css @@ -1,84 +1,168 @@ -[focus-within][focus-within] { +[focus-within][focus-within].js-focus-within, .js-focus-within [focus-within][focus-within] { order: 0; } -[focus-within][focus-within] { +:focus-within:focus-within { + order: 0; +} + +[focus-within][focus-within].js-focus-within, .js-focus-within [focus-within][focus-within] { order: 1; } -[focus-within] [focus-within] { +:focus-within:focus-within { + order: 1; +} + +[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] { order: 2; } -[focus-within] [focus-within] { +:focus-within :focus-within { + order: 2; +} + +[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] { + order: 3; +} + +:focus-within :focus-within { order: 3; } -[focus-within] [focus-within] { +[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] { + order: 4; +} + +:focus-within :focus-within { order: 4; } -[focus-within] [focus-within] { +[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] { order: 5; } -[focus-within]+[focus-within] { +:focus-within :focus-within { + order: 5; +} + +[focus-within].js-focus-within+[focus-within], .js-focus-within [focus-within]+[focus-within] { order: 6; } -[focus-within]+[focus-within] { +:focus-within+:focus-within { + order: 6; +} + +[focus-within].js-focus-within+[focus-within], .js-focus-within [focus-within]+[focus-within] { + order: 7; +} + +:focus-within+:focus-within { order: 7; } -[focus-within] + [focus-within] { +[focus-within].js-focus-within + [focus-within], .js-focus-within [focus-within] + [focus-within] { + order: 8; +} + +:focus-within + :focus-within { order: 8; } -[focus-within] + [focus-within] { +[focus-within].js-focus-within + [focus-within], .js-focus-within [focus-within] + [focus-within] { + order: 9; +} + +:focus-within + :focus-within { order: 9; } -[focus-within]~[focus-within] { +[focus-within].js-focus-within~[focus-within], .js-focus-within [focus-within]~[focus-within] { + order: 10; +} + +:focus-within~:focus-within { order: 10; } -[focus-within]~[focus-within] { +[focus-within].js-focus-within~[focus-within], .js-focus-within [focus-within]~[focus-within] { order: 11; } -[focus-within] ~ [focus-within] { +:focus-within~:focus-within { + order: 11; +} + +[focus-within].js-focus-within ~ [focus-within], .js-focus-within [focus-within] ~ [focus-within] { + order: 12; +} + +:focus-within ~ :focus-within { order: 12; } -[focus-within] ~ [focus-within] { +[focus-within].js-focus-within ~ [focus-within], .js-focus-within [focus-within] ~ [focus-within] { order: 13; } -[focus-within]>[focus-within] { +:focus-within ~ :focus-within { + order: 13; +} + +[focus-within].js-focus-within>[focus-within], .js-focus-within [focus-within]>[focus-within] { order: 14; } -[focus-within]>[focus-within] { +:focus-within>:focus-within { + order: 14; +} + +[focus-within].js-focus-within>[focus-within], .js-focus-within [focus-within]>[focus-within] { order: 15; } -[focus-within] > [focus-within] { +:focus-within>:focus-within { + order: 15; +} + +[focus-within].js-focus-within > [focus-within], .js-focus-within [focus-within] > [focus-within] { + order: 16; +} + +:focus-within > :focus-within { order: 16; } -[focus-within] > [focus-within] { +[focus-within].js-focus-within > [focus-within], .js-focus-within [focus-within] > [focus-within] { order: 17; } -[focus-within],[focus-within] { +:focus-within > :focus-within { + order: 17; +} + +[focus-within].js-focus-within, .js-focus-within [focus-within], [focus-within].js-focus-within, .js-focus-within [focus-within] { order: 18; } -[focus-within],[focus-within] { +:focus-within, :focus-within { + order: 18; +} + +[focus-within].js-focus-within, .js-focus-within [focus-within], [focus-within].js-focus-within, .js-focus-within [focus-within] { order: 19; } -button[focus-within] { +:focus-within, :focus-within { + order: 19; +} + +button[focus-within].js-focus-within, .js-focus-within button[focus-within] { + order: 20; +} + +button:focus-within { order: 20; } @@ -86,319 +170,635 @@ button[focus-within] { order: 21; } -button [focus-within] { +button.js-focus-within [focus-within], .js-focus-within button [focus-within] { + order: 22; +} + +button :focus-within { order: 22; } -[focus-within] button { +[focus-within].js-focus-within button, .js-focus-within [focus-within] button { + order: 23; +} + +:focus-within button { order: 23; } -button [focus-within] { +button.js-focus-within [focus-within], .js-focus-within button [focus-within] { + order: 24; +} + +button :focus-within { order: 24; } -[focus-within] button { +[focus-within].js-focus-within button, .js-focus-within [focus-within] button { order: 25; } -button+[focus-within] { +:focus-within button { + order: 25; +} + +button.js-focus-within+[focus-within], .js-focus-within button+[focus-within] { + order: 26; +} + +button+:focus-within { order: 26; } -[focus-within]+button { +[focus-within].js-focus-within+button, .js-focus-within [focus-within]+button { order: 27; } -button + [focus-within] { +:focus-within+button { + order: 27; +} + +button.js-focus-within + [focus-within], .js-focus-within button + [focus-within] { order: 28; } -[focus-within] + button { +button + :focus-within { + order: 28; +} + +[focus-within].js-focus-within + button, .js-focus-within [focus-within] + button { order: 29; } -button~[focus-within] { +:focus-within + button { + order: 29; +} + +button.js-focus-within~[focus-within], .js-focus-within button~[focus-within] { + order: 30; +} + +button~:focus-within { order: 30; } -[focus-within]~button { +[focus-within].js-focus-within~button, .js-focus-within [focus-within]~button { order: 31; } -button ~ [focus-within] { +:focus-within~button { + order: 31; +} + +button.js-focus-within ~ [focus-within], .js-focus-within button ~ [focus-within] { + order: 32; +} + +button ~ :focus-within { order: 32; } -[focus-within] ~ button { +[focus-within].js-focus-within ~ button, .js-focus-within [focus-within] ~ button { + order: 33; +} + +:focus-within ~ button { order: 33; } -button>[focus-within] { +button.js-focus-within>[focus-within], .js-focus-within button>[focus-within] { + order: 34; +} + +button>:focus-within { order: 34; } -[focus-within]>button { +[focus-within].js-focus-within>button, .js-focus-within [focus-within]>button { + order: 35; +} + +:focus-within>button { order: 35; } -button > [focus-within] { +button.js-focus-within > [focus-within], .js-focus-within button > [focus-within] { order: 36; } -[focus-within] > button { +button > :focus-within { + order: 36; +} + +[focus-within].js-focus-within > button, .js-focus-within [focus-within] > button { order: 37; } -button,[focus-within] { +:focus-within > button { + order: 37; +} + +button, [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 38; +} + +button, :focus-within { order: 38; } -[focus-within], button { +[focus-within].js-focus-within, .js-focus-within [focus-within], button { + order: 39; +} + +:focus-within, button { order: 39; } -.🧑🏾‍🎤[focus-within] { +.🧑🏾‍🎤[focus-within].js-focus-within, .js-focus-within .🧑🏾‍🎤[focus-within] { + order: 40; +} + +.🧑🏾‍🎤:focus-within { order: 40; } -[focus-within].🧑🏾‍🎤 { +[focus-within].🧑🏾‍🎤.js-focus-within, .js-focus-within [focus-within].🧑🏾‍🎤 { + order: 41; +} + +:focus-within.🧑🏾‍🎤 { order: 41; } -.🧑🏾‍🎤 [focus-within] { +.🧑🏾‍🎤.js-focus-within [focus-within], .js-focus-within .🧑🏾‍🎤 [focus-within] { order: 42; } -[focus-within] .🧑🏾‍🎤 { +.🧑🏾‍🎤 :focus-within { + order: 42; +} + +[focus-within].js-focus-within .🧑🏾‍🎤, .js-focus-within [focus-within] .🧑🏾‍🎤 { + order: 43; +} + +:focus-within .🧑🏾‍🎤 { order: 43; } -.🧑🏾‍🎤 [focus-within] { +.🧑🏾‍🎤.js-focus-within [focus-within], .js-focus-within .🧑🏾‍🎤 [focus-within] { order: 44; } -[focus-within] .🧑🏾‍🎤 { +.🧑🏾‍🎤 :focus-within { + order: 44; +} + +[focus-within].js-focus-within .🧑🏾‍🎤, .js-focus-within [focus-within] .🧑🏾‍🎤 { order: 45; } -.🧑🏾‍🎤+[focus-within] { +:focus-within .🧑🏾‍🎤 { + order: 45; +} + +.🧑🏾‍🎤.js-focus-within+[focus-within], .js-focus-within .🧑🏾‍🎤+[focus-within] { order: 46; } -[focus-within]+.🧑🏾‍🎤 { +.🧑🏾‍🎤+:focus-within { + order: 46; +} + +[focus-within].js-focus-within+.🧑🏾‍🎤, .js-focus-within [focus-within]+.🧑🏾‍🎤 { + order: 47; +} + +:focus-within+.🧑🏾‍🎤 { order: 47; } -.🧑🏾‍🎤 + [focus-within] { +.🧑🏾‍🎤.js-focus-within + [focus-within], .js-focus-within .🧑🏾‍🎤 + [focus-within] { + order: 48; +} + +.🧑🏾‍🎤 + :focus-within { order: 48; } -[focus-within] + .🧑🏾‍🎤 { +[focus-within].js-focus-within + .🧑🏾‍🎤, .js-focus-within [focus-within] + .🧑🏾‍🎤 { order: 49; } -.🧑🏾‍🎤~[focus-within] { +:focus-within + .🧑🏾‍🎤 { + order: 49; +} + +.🧑🏾‍🎤.js-focus-within~[focus-within], .js-focus-within .🧑🏾‍🎤~[focus-within] { order: 50; } -[focus-within]~.🧑🏾‍🎤 { +.🧑🏾‍🎤~:focus-within { + order: 50; +} + +[focus-within].js-focus-within~.🧑🏾‍🎤, .js-focus-within [focus-within]~.🧑🏾‍🎤 { + order: 51; +} + +:focus-within~.🧑🏾‍🎤 { order: 51; } -.🧑🏾‍🎤 ~ [focus-within] { +.🧑🏾‍🎤.js-focus-within ~ [focus-within], .js-focus-within .🧑🏾‍🎤 ~ [focus-within] { order: 52; } -[focus-within] ~ .🧑🏾‍🎤 { +.🧑🏾‍🎤 ~ :focus-within { + order: 52; +} + +[focus-within].js-focus-within ~ .🧑🏾‍🎤, .js-focus-within [focus-within] ~ .🧑🏾‍🎤 { + order: 53; +} + +:focus-within ~ .🧑🏾‍🎤 { order: 53; } -.🧑🏾‍🎤>[focus-within] { +.🧑🏾‍🎤.js-focus-within>[focus-within], .js-focus-within .🧑🏾‍🎤>[focus-within] { + order: 54; +} + +.🧑🏾‍🎤>:focus-within { order: 54; } -[focus-within]>.🧑🏾‍🎤 { +[focus-within].js-focus-within>.🧑🏾‍🎤, .js-focus-within [focus-within]>.🧑🏾‍🎤 { order: 55; } -.🧑🏾‍🎤 > [focus-within] { +:focus-within>.🧑🏾‍🎤 { + order: 55; +} + +.🧑🏾‍🎤.js-focus-within > [focus-within], .js-focus-within .🧑🏾‍🎤 > [focus-within] { + order: 56; +} + +.🧑🏾‍🎤 > :focus-within { order: 56; } -[focus-within] > .🧑🏾‍🎤 { +[focus-within].js-focus-within > .🧑🏾‍🎤, .js-focus-within [focus-within] > .🧑🏾‍🎤 { order: 57; } -.🧑🏾‍🎤,[focus-within] { +:focus-within > .🧑🏾‍🎤 { + order: 57; +} + +.🧑🏾‍🎤, [focus-within].js-focus-within, .js-focus-within [focus-within] { order: 58; } -[focus-within], .🧑🏾‍🎤 { +.🧑🏾‍🎤, :focus-within { + order: 58; +} + +[focus-within].js-focus-within, .js-focus-within [focus-within], .🧑🏾‍🎤 { order: 59; } -.foo[focus-within] { +:focus-within, .🧑🏾‍🎤 { + order: 59; +} + +.foo[focus-within].js-focus-within, .js-focus-within .foo[focus-within] { + order: 60; +} + +.foo:focus-within { order: 60; } -[focus-within].foo { +[focus-within].foo.js-focus-within, .js-focus-within [focus-within].foo { order: 61; } -.foo [focus-within] { +:focus-within.foo { + order: 61; +} + +.foo.js-focus-within [focus-within], .js-focus-within .foo [focus-within] { order: 62; } -[focus-within] .foo { +.foo :focus-within { + order: 62; +} + +[focus-within].js-focus-within .foo, .js-focus-within [focus-within] .foo { order: 63; } -.foo [focus-within] { +:focus-within .foo { + order: 63; +} + +.foo.js-focus-within [focus-within], .js-focus-within .foo [focus-within] { + order: 64; +} + +.foo :focus-within { order: 64; } -[focus-within] .foo { +[focus-within].js-focus-within .foo, .js-focus-within [focus-within] .foo { order: 65; } -.foo+[focus-within] { +:focus-within .foo { + order: 65; +} + +.foo.js-focus-within+[focus-within], .js-focus-within .foo+[focus-within] { + order: 66; +} + +.foo+:focus-within { order: 66; } -[focus-within]+.foo { +[focus-within].js-focus-within+.foo, .js-focus-within [focus-within]+.foo { + order: 67; +} + +:focus-within+.foo { order: 67; } -.foo + [focus-within] { +.foo.js-focus-within + [focus-within], .js-focus-within .foo + [focus-within] { + order: 68; +} + +.foo + :focus-within { order: 68; } -[focus-within] + .foo { +[focus-within].js-focus-within + .foo, .js-focus-within [focus-within] + .foo { order: 69; } -.foo~[focus-within] { +:focus-within + .foo { + order: 69; +} + +.foo.js-focus-within~[focus-within], .js-focus-within .foo~[focus-within] { + order: 70; +} + +.foo~:focus-within { order: 70; } -[focus-within]~.foo { +[focus-within].js-focus-within~.foo, .js-focus-within [focus-within]~.foo { + order: 71; +} + +:focus-within~.foo { order: 71; } -.foo ~ [focus-within] { +.foo.js-focus-within ~ [focus-within], .js-focus-within .foo ~ [focus-within] { order: 72; } -[focus-within] ~ .foo { +.foo ~ :focus-within { + order: 72; +} + +[focus-within].js-focus-within ~ .foo, .js-focus-within [focus-within] ~ .foo { + order: 73; +} + +:focus-within ~ .foo { order: 73; } -.foo>[focus-within] { +.foo.js-focus-within>[focus-within], .js-focus-within .foo>[focus-within] { order: 74; } -[focus-within]>.foo { +.foo>:focus-within { + order: 74; +} + +[focus-within].js-focus-within>.foo, .js-focus-within [focus-within]>.foo { order: 75; } -.foo > [focus-within] { +:focus-within>.foo { + order: 75; +} + +.foo.js-focus-within > [focus-within], .js-focus-within .foo > [focus-within] { order: 76; } -[focus-within] > .foo { +.foo > :focus-within { + order: 76; +} + +[focus-within].js-focus-within > .foo, .js-focus-within [focus-within] > .foo { + order: 77; +} + +:focus-within > .foo { order: 77; } -.foo,[focus-within] { +.foo, [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 78; +} + +.foo, :focus-within { order: 78; } -[focus-within], .foo { +[focus-within].js-focus-within, .js-focus-within [focus-within], .foo { order: 79; } -#foo[focus-within] { +:focus-within, .foo { + order: 79; +} + +#foo[focus-within].js-focus-within, .js-focus-within #foo[focus-within] { order: 80; } -[focus-within]#foo { +#foo:focus-within { + order: 80; +} + +[focus-within]#foo.js-focus-within, .js-focus-within [focus-within]#foo { + order: 81; +} + +:focus-within#foo { order: 81; } -#foo [focus-within] { +#foo.js-focus-within [focus-within], .js-focus-within #foo [focus-within] { + order: 82; +} + +#foo :focus-within { order: 82; } -[focus-within] #foo { +[focus-within].js-focus-within #foo, .js-focus-within [focus-within] #foo { + order: 83; +} + +:focus-within #foo { order: 83; } -#foo [focus-within] { +#foo.js-focus-within [focus-within], .js-focus-within #foo [focus-within] { + order: 84; +} + +#foo :focus-within { order: 84; } -[focus-within] #foo { +[focus-within].js-focus-within #foo, .js-focus-within [focus-within] #foo { order: 85; } -#foo+[focus-within] { +:focus-within #foo { + order: 85; +} + +#foo.js-focus-within+[focus-within], .js-focus-within #foo+[focus-within] { + order: 86; +} + +#foo+:focus-within { order: 86; } -[focus-within]+#foo { +[focus-within].js-focus-within+#foo, .js-focus-within [focus-within]+#foo { order: 87; } -#foo + [focus-within] { +:focus-within+#foo { + order: 87; +} + +#foo.js-focus-within + [focus-within], .js-focus-within #foo + [focus-within] { order: 88; } -[focus-within] + #foo { +#foo + :focus-within { + order: 88; +} + +[focus-within].js-focus-within + #foo, .js-focus-within [focus-within] + #foo { order: 89; } -#foo~[focus-within] { +:focus-within + #foo { + order: 89; +} + +#foo.js-focus-within~[focus-within], .js-focus-within #foo~[focus-within] { + order: 90; +} + +#foo~:focus-within { order: 90; } -[focus-within]~#foo { +[focus-within].js-focus-within~#foo, .js-focus-within [focus-within]~#foo { + order: 91; +} + +:focus-within~#foo { order: 91; } -#foo ~ [focus-within] { +#foo.js-focus-within ~ [focus-within], .js-focus-within #foo ~ [focus-within] { order: 92; } -[focus-within] ~ #foo { +#foo ~ :focus-within { + order: 92; +} + +[focus-within].js-focus-within ~ #foo, .js-focus-within [focus-within] ~ #foo { order: 93; } -#foo>[focus-within] { +:focus-within ~ #foo { + order: 93; +} + +#foo.js-focus-within>[focus-within], .js-focus-within #foo>[focus-within] { + order: 94; +} + +#foo>:focus-within { order: 94; } -[focus-within]>#foo { +[focus-within].js-focus-within>#foo, .js-focus-within [focus-within]>#foo { order: 95; } -#foo > [focus-within] { +:focus-within>#foo { + order: 95; +} + +#foo.js-focus-within > [focus-within], .js-focus-within #foo > [focus-within] { + order: 96; +} + +#foo > :focus-within { order: 96; } -[focus-within] > #foo { +[focus-within].js-focus-within > #foo, .js-focus-within [focus-within] > #foo { + order: 97; +} + +:focus-within > #foo { order: 97; } -#foo,[focus-within] { +#foo, [focus-within].js-focus-within, .js-focus-within [focus-within] { order: 98; } -[focus-within], #foo { +#foo, :focus-within { + order: 98; +} + +[focus-within].js-focus-within, .js-focus-within [focus-within], #foo { + order: 99; +} + +:focus-within, #foo { order: 99; } -__foo[focus-within] { +__foo[focus-within].js-focus-within, .js-focus-within __foo[focus-within] { + order: 100; +} + +__foo:focus-within { order: 100; } @@ -406,475 +806,947 @@ __foo[focus-within] { order: 101; } -__foo [focus-within] { +__foo.js-focus-within [focus-within], .js-focus-within __foo [focus-within] { + order: 102; +} + +__foo :focus-within { order: 102; } -[focus-within] __foo { +[focus-within].js-focus-within __foo, .js-focus-within [focus-within] __foo { order: 103; } -__foo [focus-within] { +:focus-within __foo { + order: 103; +} + +__foo.js-focus-within [focus-within], .js-focus-within __foo [focus-within] { + order: 104; +} + +__foo :focus-within { order: 104; } -[focus-within] __foo { +[focus-within].js-focus-within __foo, .js-focus-within [focus-within] __foo { order: 105; } -__foo+[focus-within] { +:focus-within __foo { + order: 105; +} + +__foo.js-focus-within+[focus-within], .js-focus-within __foo+[focus-within] { order: 106; } -[focus-within]+__foo { +__foo+:focus-within { + order: 106; +} + +[focus-within].js-focus-within+__foo, .js-focus-within [focus-within]+__foo { order: 107; } -__foo + [focus-within] { +:focus-within+__foo { + order: 107; +} + +__foo.js-focus-within + [focus-within], .js-focus-within __foo + [focus-within] { + order: 108; +} + +__foo + :focus-within { order: 108; } -[focus-within] + __foo { +[focus-within].js-focus-within + __foo, .js-focus-within [focus-within] + __foo { + order: 109; +} + +:focus-within + __foo { order: 109; } -__foo~[focus-within] { +__foo.js-focus-within~[focus-within], .js-focus-within __foo~[focus-within] { order: 110; } -[focus-within]~__foo { +__foo~:focus-within { + order: 110; +} + +[focus-within].js-focus-within~__foo, .js-focus-within [focus-within]~__foo { order: 111; } -__foo ~ [focus-within] { +:focus-within~__foo { + order: 111; +} + +__foo.js-focus-within ~ [focus-within], .js-focus-within __foo ~ [focus-within] { + order: 112; +} + +__foo ~ :focus-within { order: 112; } -[focus-within] ~ __foo { +[focus-within].js-focus-within ~ __foo, .js-focus-within [focus-within] ~ __foo { order: 113; } -__foo>[focus-within] { +:focus-within ~ __foo { + order: 113; +} + +__foo.js-focus-within>[focus-within], .js-focus-within __foo>[focus-within] { + order: 114; +} + +__foo>:focus-within { order: 114; } -[focus-within]>__foo { +[focus-within].js-focus-within>__foo, .js-focus-within [focus-within]>__foo { + order: 115; +} + +:focus-within>__foo { order: 115; } -__foo > [focus-within] { +__foo.js-focus-within > [focus-within], .js-focus-within __foo > [focus-within] { order: 116; } -[focus-within] > __foo { +__foo > :focus-within { + order: 116; +} + +[focus-within].js-focus-within > __foo, .js-focus-within [focus-within] > __foo { + order: 117; +} + +:focus-within > __foo { order: 117; } -__foo,[focus-within] { +__foo, [focus-within].js-focus-within, .js-focus-within [focus-within] { order: 118; } -[focus-within], __foo { +__foo, :focus-within { + order: 118; +} + +[focus-within].js-focus-within, .js-focus-within [focus-within], __foo { + order: 119; +} + +:focus-within, __foo { order: 119; } -:--foo[focus-within] { +:--foo[focus-within].js-focus-within, .js-focus-within :--foo[focus-within] { order: 120; } -[focus-within]:--foo { +:--foo:focus-within { + order: 120; +} + +[focus-within]:--foo.js-focus-within, .js-focus-within [focus-within]:--foo { + order: 121; +} + +:focus-within:--foo { order: 121; } -:--foo [focus-within] { +:--foo.js-focus-within [focus-within], .js-focus-within :--foo [focus-within] { order: 122; } -[focus-within] :--foo { +:--foo :focus-within { + order: 122; +} + +[focus-within].js-focus-within :--foo, .js-focus-within [focus-within] :--foo { order: 123; } -:--foo [focus-within] { +:focus-within :--foo { + order: 123; +} + +:--foo.js-focus-within [focus-within], .js-focus-within :--foo [focus-within] { order: 124; } -[focus-within] :--foo { +:--foo :focus-within { + order: 124; +} + +[focus-within].js-focus-within :--foo, .js-focus-within [focus-within] :--foo { + order: 125; +} + +:focus-within :--foo { order: 125; } -:--foo+[focus-within] { +:--foo.js-focus-within+[focus-within], .js-focus-within :--foo+[focus-within] { + order: 126; +} + +:--foo+:focus-within { order: 126; } -[focus-within]+:--foo { +[focus-within].js-focus-within+:--foo, .js-focus-within [focus-within]+:--foo { order: 127; } -:--foo + [focus-within] { +:focus-within+:--foo { + order: 127; +} + +:--foo.js-focus-within + [focus-within], .js-focus-within :--foo + [focus-within] { order: 128; } -[focus-within] + :--foo { +:--foo + :focus-within { + order: 128; +} + +[focus-within].js-focus-within + :--foo, .js-focus-within [focus-within] + :--foo { + order: 129; +} + +:focus-within + :--foo { order: 129; } -:--foo~[focus-within] { +:--foo.js-focus-within~[focus-within], .js-focus-within :--foo~[focus-within] { order: 130; } -[focus-within]~:--foo { +:--foo~:focus-within { + order: 130; +} + +[focus-within].js-focus-within~:--foo, .js-focus-within [focus-within]~:--foo { + order: 131; +} + +:focus-within~:--foo { order: 131; } -:--foo ~ [focus-within] { +:--foo.js-focus-within ~ [focus-within], .js-focus-within :--foo ~ [focus-within] { + order: 132; +} + +:--foo ~ :focus-within { order: 132; } -[focus-within] ~ :--foo { +[focus-within].js-focus-within ~ :--foo, .js-focus-within [focus-within] ~ :--foo { order: 133; } -:--foo>[focus-within] { +:focus-within ~ :--foo { + order: 133; +} + +:--foo.js-focus-within>[focus-within], .js-focus-within :--foo>[focus-within] { + order: 134; +} + +:--foo>:focus-within { order: 134; } -[focus-within]>:--foo { +[focus-within].js-focus-within>:--foo, .js-focus-within [focus-within]>:--foo { order: 135; } -:--foo > [focus-within] { - order: 136; +:focus-within>:--foo { + order: 135; +} + +:--foo.js-focus-within > [focus-within], .js-focus-within :--foo > [focus-within] { + order: 136; +} + +:--foo > :focus-within { + order: 136; +} + +[focus-within].js-focus-within > :--foo, .js-focus-within [focus-within] > :--foo { + order: 137; +} + +:focus-within > :--foo { + order: 137; } -[focus-within] > :--foo { - order: 137; +:--foo, [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 138; } -:--foo,[focus-within] { +:--foo, :focus-within { order: 138; } -[focus-within], :--foo { +[focus-within].js-focus-within, .js-focus-within [focus-within], :--foo { order: 139; } -[foo="baz"][focus-within] { +:focus-within, :--foo { + order: 139; +} + +[foo="baz"][focus-within].js-focus-within, .js-focus-within [foo="baz"][focus-within] { + order: 140; +} + +[foo="baz"]:focus-within { order: 140; } -[focus-within][foo="baz"] { +[focus-within][foo="baz"].js-focus-within, .js-focus-within [focus-within][foo="baz"] { + order: 141; +} + +:focus-within[foo="baz"] { order: 141; } -[foo="baz"] [focus-within] { +[foo="baz"].js-focus-within [focus-within], .js-focus-within [foo="baz"] [focus-within] { + order: 142; +} + +[foo="baz"] :focus-within { order: 142; } -[focus-within] [foo="baz"] { +[focus-within].js-focus-within [foo="baz"], .js-focus-within [focus-within] [foo="baz"] { order: 143; } -[foo="baz"] [focus-within] { +:focus-within [foo="baz"] { + order: 143; +} + +[foo="baz"].js-focus-within [focus-within], .js-focus-within [foo="baz"] [focus-within] { + order: 144; +} + +[foo="baz"] :focus-within { order: 144; } -[focus-within] [foo="baz"] { +[focus-within].js-focus-within [foo="baz"], .js-focus-within [focus-within] [foo="baz"] { + order: 145; +} + +:focus-within [foo="baz"] { order: 145; } -[foo="baz"]+[focus-within] { +[foo="baz"].js-focus-within+[focus-within], .js-focus-within [foo="baz"]+[focus-within] { + order: 146; +} + +[foo="baz"]+:focus-within { order: 146; } -[focus-within]+[foo="baz"] { +[focus-within].js-focus-within+[foo="baz"], .js-focus-within [focus-within]+[foo="baz"] { order: 147; } -[foo="baz"] + [focus-within] { +:focus-within+[foo="baz"] { + order: 147; +} + +[foo="baz"].js-focus-within + [focus-within], .js-focus-within [foo="baz"] + [focus-within] { + order: 148; +} + +[foo="baz"] + :focus-within { order: 148; } -[focus-within] + [foo="baz"] { +[focus-within].js-focus-within + [foo="baz"], .js-focus-within [focus-within] + [foo="baz"] { + order: 149; +} + +:focus-within + [foo="baz"] { order: 149; } -[foo="baz"]~[focus-within] { +[foo="baz"].js-focus-within~[focus-within], .js-focus-within [foo="baz"]~[focus-within] { + order: 150; +} + +[foo="baz"]~:focus-within { order: 150; } -[focus-within]~[foo="baz"] { +[focus-within].js-focus-within~[foo="baz"], .js-focus-within [focus-within]~[foo="baz"] { order: 151; } -[foo="baz"] ~ [focus-within] { +:focus-within~[foo="baz"] { + order: 151; +} + +[foo="baz"].js-focus-within ~ [focus-within], .js-focus-within [foo="baz"] ~ [focus-within] { + order: 152; +} + +[foo="baz"] ~ :focus-within { order: 152; } -[focus-within] ~ [foo="baz"] { +[focus-within].js-focus-within ~ [foo="baz"], .js-focus-within [focus-within] ~ [foo="baz"] { + order: 153; +} + +:focus-within ~ [foo="baz"] { order: 153; } -[foo="baz"]>[focus-within] { +[foo="baz"].js-focus-within>[focus-within], .js-focus-within [foo="baz"]>[focus-within] { + order: 154; +} + +[foo="baz"]>:focus-within { order: 154; } -[focus-within]>[foo="baz"] { +[focus-within].js-focus-within>[foo="baz"], .js-focus-within [focus-within]>[foo="baz"] { order: 155; } -[foo="baz"] > [focus-within] { +:focus-within>[foo="baz"] { + order: 155; +} + +[foo="baz"].js-focus-within > [focus-within], .js-focus-within [foo="baz"] > [focus-within] { + order: 156; +} + +[foo="baz"] > :focus-within { order: 156; } -[focus-within] > [foo="baz"] { +[focus-within].js-focus-within > [foo="baz"], .js-focus-within [focus-within] > [foo="baz"] { + order: 157; +} + +:focus-within > [foo="baz"] { order: 157; } -[foo="baz"],[focus-within] { +[foo="baz"], [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 158; +} + +[foo="baz"], :focus-within { order: 158; } -[focus-within], [foo="baz"] { +[focus-within].js-focus-within, .js-focus-within [focus-within], [foo="baz"] { order: 159; } -*[focus-within] { +:focus-within, [foo="baz"] { + order: 159; +} + +*[focus-within].js-focus-within, .js-focus-within *[focus-within] { + order: 160; +} + +*:focus-within { order: 160; } -[focus-within]* { +[focus-within]*.js-focus-within, .js-focus-within [focus-within]* { + order: 161; +} + +:focus-within* { order: 161; } -* [focus-within] { +*.js-focus-within [focus-within], .js-focus-within * [focus-within] { + order: 162; +} + +* :focus-within { order: 162; } -[focus-within] * { +[focus-within].js-focus-within *, .js-focus-within [focus-within] * { order: 163; } -* [focus-within] { +:focus-within * { + order: 163; +} + +*.js-focus-within [focus-within], .js-focus-within * [focus-within] { + order: 164; +} + +* :focus-within { order: 164; } -[focus-within] * { +[focus-within].js-focus-within *, .js-focus-within [focus-within] * { + order: 165; +} + +:focus-within * { order: 165; } -*+[focus-within] { +*.js-focus-within+[focus-within], .js-focus-within *+[focus-within] { + order: 166; +} + +*+:focus-within { order: 166; } -[focus-within]+* { +[focus-within].js-focus-within+*, .js-focus-within [focus-within]+* { order: 167; } -* + [focus-within] { +:focus-within+* { + order: 167; +} + +*.js-focus-within + [focus-within], .js-focus-within * + [focus-within] { + order: 168; +} + +* + :focus-within { order: 168; } -[focus-within] + * { +[focus-within].js-focus-within + *, .js-focus-within [focus-within] + * { + order: 169; +} + +:focus-within + * { order: 169; } -*~[focus-within] { +*.js-focus-within~[focus-within], .js-focus-within *~[focus-within] { + order: 170; +} + +*~:focus-within { order: 170; } -[focus-within]~* { +[focus-within].js-focus-within~*, .js-focus-within [focus-within]~* { order: 171; } -* ~ [focus-within] { +:focus-within~* { + order: 171; +} + +*.js-focus-within ~ [focus-within], .js-focus-within * ~ [focus-within] { + order: 172; +} + +* ~ :focus-within { order: 172; } -[focus-within] ~ * { +[focus-within].js-focus-within ~ *, .js-focus-within [focus-within] ~ * { + order: 173; +} + +:focus-within ~ * { order: 173; } -*>[focus-within] { +*.js-focus-within>[focus-within], .js-focus-within *>[focus-within] { + order: 174; +} + +*>:focus-within { order: 174; } -[focus-within]>* { +[focus-within].js-focus-within>*, .js-focus-within [focus-within]>* { order: 175; } -* > [focus-within] { +:focus-within>* { + order: 175; +} + +*.js-focus-within > [focus-within], .js-focus-within * > [focus-within] { + order: 176; +} + +* > :focus-within { order: 176; } -[focus-within] > * { +[focus-within].js-focus-within > *, .js-focus-within [focus-within] > * { + order: 177; +} + +:focus-within > * { order: 177; } -*,[focus-within] { +*, [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 178; +} + +*, :focus-within { order: 178; } -[focus-within], * { +[focus-within].js-focus-within, .js-focus-within [focus-within], * { order: 179; } -:hover[focus-within] { +:focus-within, * { + order: 179; +} + +:hover[focus-within].js-focus-within, .js-focus-within :hover[focus-within] { + order: 180; +} + +:hover:focus-within { order: 180; } -[focus-within]:hover { +[focus-within]:hover.js-focus-within, .js-focus-within [focus-within]:hover { + order: 181; +} + +:focus-within:hover { order: 181; } -:hover [focus-within] { +:hover.js-focus-within [focus-within], .js-focus-within :hover [focus-within] { + order: 182; +} + +:hover :focus-within { order: 182; } -[focus-within] :hover { +[focus-within].js-focus-within :hover, .js-focus-within [focus-within] :hover { order: 183; } -:hover [focus-within] { +:focus-within :hover { + order: 183; +} + +:hover.js-focus-within [focus-within], .js-focus-within :hover [focus-within] { + order: 184; +} + +:hover :focus-within { order: 184; } -[focus-within] :hover { +[focus-within].js-focus-within :hover, .js-focus-within [focus-within] :hover { + order: 185; +} + +:focus-within :hover { order: 185; } -:hover+[focus-within] { +:hover.js-focus-within+[focus-within], .js-focus-within :hover+[focus-within] { + order: 186; +} + +:hover+:focus-within { order: 186; } -[focus-within]+:hover { +[focus-within].js-focus-within+:hover, .js-focus-within [focus-within]+:hover { order: 187; } -:hover + [focus-within] { +:focus-within+:hover { + order: 187; +} + +:hover.js-focus-within + [focus-within], .js-focus-within :hover + [focus-within] { + order: 188; +} + +:hover + :focus-within { order: 188; } -[focus-within] + :hover { +[focus-within].js-focus-within + :hover, .js-focus-within [focus-within] + :hover { + order: 189; +} + +:focus-within + :hover { order: 189; } -:hover~[focus-within] { +:hover.js-focus-within~[focus-within], .js-focus-within :hover~[focus-within] { + order: 190; +} + +:hover~:focus-within { order: 190; } -[focus-within]~:hover { +[focus-within].js-focus-within~:hover, .js-focus-within [focus-within]~:hover { order: 191; } -:hover ~ [focus-within] { +:focus-within~:hover { + order: 191; +} + +:hover.js-focus-within ~ [focus-within], .js-focus-within :hover ~ [focus-within] { + order: 192; +} + +:hover ~ :focus-within { order: 192; } -[focus-within] ~ :hover { +[focus-within].js-focus-within ~ :hover, .js-focus-within [focus-within] ~ :hover { + order: 193; +} + +:focus-within ~ :hover { order: 193; } -:hover>[focus-within] { +:hover.js-focus-within>[focus-within], .js-focus-within :hover>[focus-within] { + order: 194; +} + +:hover>:focus-within { order: 194; } -[focus-within]>:hover { +[focus-within].js-focus-within>:hover, .js-focus-within [focus-within]>:hover { order: 195; } -:hover > [focus-within] { +:focus-within>:hover { + order: 195; +} + +:hover.js-focus-within > [focus-within], .js-focus-within :hover > [focus-within] { + order: 196; +} + +:hover > :focus-within { order: 196; } -[focus-within] > :hover { +[focus-within].js-focus-within > :hover, .js-focus-within [focus-within] > :hover { + order: 197; +} + +:focus-within > :hover { order: 197; } -:hover,[focus-within] { +:hover, [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 198; +} + +:hover, :focus-within { order: 198; } -[focus-within], :hover { +[focus-within].js-focus-within, .js-focus-within [focus-within], :hover { order: 199; } -::before[focus-within] { +:focus-within, :hover { + order: 199; +} + +.js-focus-within::before[focus-within], .js-focus-within ::before[focus-within] { + order: 200; +} + +::before:focus-within { order: 200; } -[focus-within]::before { +[focus-within].js-focus-within::before, .js-focus-within [focus-within]::before { + order: 201; +} + +:focus-within::before { order: 201; } -::before [focus-within] { +.js-focus-within::before [focus-within], .js-focus-within ::before [focus-within] { + order: 202; +} + +::before :focus-within { order: 202; } -[focus-within] ::before { +[focus-within].js-focus-within ::before, .js-focus-within [focus-within] ::before { order: 203; } -::before [focus-within] { +:focus-within ::before { + order: 203; +} + +.js-focus-within::before [focus-within], .js-focus-within ::before [focus-within] { + order: 204; +} + +::before :focus-within { order: 204; } -[focus-within] ::before { +[focus-within].js-focus-within ::before, .js-focus-within [focus-within] ::before { + order: 205; +} + +:focus-within ::before { order: 205; } -::before+[focus-within] { +.js-focus-within::before+[focus-within], .js-focus-within ::before+[focus-within] { + order: 206; +} + +::before+:focus-within { order: 206; } -[focus-within]+::before { +[focus-within].js-focus-within+::before, .js-focus-within [focus-within]+::before { order: 207; } -::before + [focus-within] { +:focus-within+::before { + order: 207; +} + +.js-focus-within::before + [focus-within], .js-focus-within ::before + [focus-within] { + order: 208; +} + +::before + :focus-within { order: 208; } -[focus-within] + ::before { +[focus-within].js-focus-within + ::before, .js-focus-within [focus-within] + ::before { + order: 209; +} + +:focus-within + ::before { order: 209; } -::before~[focus-within] { +.js-focus-within::before~[focus-within], .js-focus-within ::before~[focus-within] { + order: 210; +} + +::before~:focus-within { order: 210; } -[focus-within]~::before { +[focus-within].js-focus-within~::before, .js-focus-within [focus-within]~::before { order: 211; } -::before ~ [focus-within] { +:focus-within~::before { + order: 211; +} + +.js-focus-within::before ~ [focus-within], .js-focus-within ::before ~ [focus-within] { + order: 212; +} + +::before ~ :focus-within { order: 212; } -[focus-within] ~ ::before { +[focus-within].js-focus-within ~ ::before, .js-focus-within [focus-within] ~ ::before { + order: 213; +} + +:focus-within ~ ::before { order: 213; } -::before>[focus-within] { +.js-focus-within::before>[focus-within], .js-focus-within ::before>[focus-within] { + order: 214; +} + +::before>:focus-within { order: 214; } -[focus-within]>::before { +[focus-within].js-focus-within>::before, .js-focus-within [focus-within]>::before { order: 215; } -::before > [focus-within] { +:focus-within>::before { + order: 215; +} + +.js-focus-within::before > [focus-within], .js-focus-within ::before > [focus-within] { + order: 216; +} + +::before > :focus-within { order: 216; } -[focus-within] > ::before { +[focus-within].js-focus-within > ::before, .js-focus-within [focus-within] > ::before { + order: 217; +} + +:focus-within > ::before { order: 217; } -::before,[focus-within] { +::before, [focus-within].js-focus-within, .js-focus-within [focus-within] { + order: 218; +} + +::before, :focus-within { order: 218; } -[focus-within], ::before { +[focus-within].js-focus-within, .js-focus-within [focus-within], ::before { + order: 219; +} + +:focus-within, ::before { order: 219; } @@ -886,7 +1758,11 @@ foo[baz=":focus-within"] { order: 221; } -:not([focus-within]) { +:not([focus-within]).js-focus-within, .js-focus-within :not([focus-within]) { + order: 222; +} + +:not(:focus-within) { order: 222; } @@ -894,11 +1770,19 @@ foo[baz=":focus-within"] { order: 223; } -:--[focus-within] { +:--[focus-within].js-focus-within, .js-focus-within :--[focus-within] { + order: 224; +} + +:--:focus-within { order: 224; } -__[focus-within] { +__[focus-within].js-focus-within, .js-focus-within __[focus-within] { + order: 225; +} + +__:focus-within { order: 225; }