From b70446e2ab22784446e321176e61c2834d0567e7 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sat, 2 Jul 2022 12:45:35 +0200
Subject: [PATCH 1/8] Starting focus-within plugin
---
package-lock.json | 34 ++++--
plugins/postcss-focus-within/.gitignore | 8 +-
plugins/postcss-focus-within/.tape.mjs | 24 ++++
plugins/postcss-focus-within/INSTALL.md | 34 +++---
plugins/postcss-focus-within/README.md | 103 ++++++------------
plugins/postcss-focus-within/docs/README.md | 60 ++++++++++
plugins/postcss-focus-within/package.json | 38 ++++++-
.../src/browser-global.js | 3 +
plugins/postcss-focus-within/src/browser.js | 75 +++++++++++++
plugins/postcss-focus-within/src/index.ts | 19 +++-
.../src/is-valid-replacement.mjs | 24 ++++
plugins/postcss-focus-within/test/browser.css | 0
.../test/browser.expect.css | 0
.../test/examples/example.css | 3 +
.../test/examples/example.expect.css | 7 ++
.../examples/example.preserve-true.expect.css | 8 ++
16 files changed, 328 insertions(+), 112 deletions(-)
create mode 100644 plugins/postcss-focus-within/docs/README.md
create mode 100644 plugins/postcss-focus-within/src/browser-global.js
create mode 100644 plugins/postcss-focus-within/src/browser.js
create mode 100644 plugins/postcss-focus-within/src/is-valid-replacement.mjs
create mode 100644 plugins/postcss-focus-within/test/browser.css
create mode 100644 plugins/postcss-focus-within/test/browser.expect.css
create mode 100644 plugins/postcss-focus-within/test/examples/example.css
create mode 100644 plugins/postcss-focus-within/test/examples/example.expect.css
create mode 100644 plugins/postcss-focus-within/test/examples/example.preserve-true.expect.css
diff --git a/package-lock.json b/package-lock.json
index 1a4a9509c..b0dd5aaac 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1806,6 +1806,10 @@
"resolved": "plugins/postcss-design-tokens",
"link": true
},
+ "node_modules/@csstools/postcss-focus-within": {
+ "resolved": "plugins/postcss-focus-within",
+ "link": true
+ },
"node_modules/@csstools/postcss-font-format-keywords": {
"resolved": "plugins/postcss-font-format-keywords",
"link": true
@@ -5377,8 +5381,18 @@
"link": true
},
"node_modules/postcss-focus-within": {
- "resolved": "plugins/postcss-focus-within",
- "link": true
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz",
+ "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.9"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
},
"node_modules/postcss-font-variant": {
"version": "5.0.0",
@@ -7104,11 +7118,9 @@
}
},
"plugins/postcss-focus-within": {
- "version": "5.0.4",
+ "name": "@csstools/postcss-focus-within",
+ "version": "1.0.0",
"license": "CC0-1.0",
- "dependencies": {
- "postcss-selector-parser": "^6.0.10"
- },
"engines": {
"node": "^12 || ^14 || >=16"
},
@@ -8714,6 +8726,10 @@
"style-dictionary-design-tokens-example": "^1.0.0"
}
},
+ "@csstools/postcss-focus-within": {
+ "version": "file:plugins/postcss-focus-within",
+ "requires": {}
+ },
"@csstools/postcss-font-format-keywords": {
"version": "file:plugins/postcss-font-format-keywords",
"requires": {
@@ -11384,9 +11400,11 @@
}
},
"postcss-focus-within": {
- "version": "file:plugins/postcss-focus-within",
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz",
+ "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==",
"requires": {
- "postcss-selector-parser": "^6.0.10"
+ "postcss-selector-parser": "^6.0.9"
}
},
"postcss-font-variant": {
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..079384881 100644
--- a/plugins/postcss-focus-within/.tape.mjs
+++ b/plugins/postcss-focus-within/.tape.mjs
@@ -24,4 +24,28 @@ postcssTape(plugin)({
preserve: false
}
},
+ 'examples/example': {
+ message: 'minimal example',
+ },
+ 'examples/example:preserve-false': {
+ message: 'minimal example',
+ options: {
+ preserve: false
+ }
+ },
+ 'examples/example:replacewith': {
+ message: 'minimal example',
+ options: {
+ replaceWith: '.css-blank'
+ }
+ },
+ 'browser': {
+ message: 'css for browser tests',
+ },
+ 'browser:replacewith': {
+ message: 'css for browser tests',
+ options: {
+ replaceWith: '.css-blank'
+ }
+ },
});
diff --git a/plugins/postcss-focus-within/INSTALL.md b/plugins/postcss-focus-within/INSTALL.md
index c8528ac02..e325a41dd 100644
--- a/plugins/postcss-focus-within/INSTALL.md
+++ b/plugins/postcss-focus-within/INSTALL.md
@@ -10,17 +10,17 @@
Add [PostCSS Focus Within] to your project:
```bash
-npm install postcss postcss-focus-within --save-dev
+npm install postcss @csstools/postcss-focus-within --save-dev
```
Use it as a [PostCSS] plugin:
```js
const postcss = require('postcss');
-const postcssFocusWithin = require('postcss-focus-within');
+const postcssBasePlugin = require('@csstools/postcss-focus-within');
postcss([
- postcssFocusWithin(/* pluginOptions */)
+ postcssBasePlugin(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
```
@@ -29,17 +29,17 @@ postcss([
Add [PostCSS CLI] to your project:
```bash
-npm install postcss-cli postcss-focus-within --save-dev
+npm install postcss-cli @csstools/postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your `postcss.config.js` configuration file:
```js
-const postcssFocusWithin = require('postcss-focus-within');
+const postcssBasePlugin = require('@csstools/postcss-focus-within');
module.exports = {
plugins: [
- postcssFocusWithin(/* pluginOptions */)
+ postcssBasePlugin(/* pluginOptions */)
]
}
```
@@ -51,7 +51,7 @@ _Webpack version 5_
Add [PostCSS Loader] to your project:
```bash
-npm install postcss-loader postcss-focus-within --save-dev
+npm install postcss-loader @csstools/postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your Webpack configuration:
@@ -74,7 +74,7 @@ module.exports = {
postcssOptions: {
plugins: [
[
- "postcss-focus-within",
+ "@csstools/postcss-focus-within",
{
// Options
},
@@ -95,7 +95,7 @@ module.exports = {
Add [React App Rewired] and [React App Rewire PostCSS] to your project:
```bash
-npm install react-app-rewired react-app-rewire-postcss postcss-focus-within --save-dev
+npm install react-app-rewired react-app-rewire-postcss @csstools/postcss-focus-within --save-dev
```
Use [React App Rewire PostCSS] and [PostCSS Focus Within] in your
@@ -103,11 +103,11 @@ Use [React App Rewire PostCSS] and [PostCSS Focus Within] in your
```js
const reactAppRewirePostcss = require('react-app-rewire-postcss');
-const postcssFocusWithin = require('postcss-focus-within');
+const postcssBasePlugin = require('@csstools/postcss-focus-within');
module.exports = config => reactAppRewirePostcss(config, {
plugins: () => [
- postcssFocusWithin(/* pluginOptions */)
+ postcssBasePlugin(/* pluginOptions */)
]
});
```
@@ -117,18 +117,18 @@ module.exports = config => reactAppRewirePostcss(config, {
Add [Gulp PostCSS] to your project:
```bash
-npm install gulp-postcss postcss-focus-within --save-dev
+npm install gulp-postcss @csstools/postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your Gulpfile:
```js
const postcss = require('gulp-postcss');
-const postcssFocusWithin = require('postcss-focus-within');
+const postcssBasePlugin = require('@csstools/postcss-focus-within');
gulp.task('css', function () {
var plugins = [
- postcssFocusWithin(/* pluginOptions */)
+ postcssBasePlugin(/* pluginOptions */)
];
return gulp.src('./src/*.css')
@@ -142,13 +142,13 @@ gulp.task('css', function () {
Add [Grunt PostCSS] to your project:
```bash
-npm install grunt-postcss postcss-focus-within --save-dev
+npm install grunt-postcss @csstools/postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your Gruntfile:
```js
-const postcssFocusWithin = require('postcss-focus-within');
+const postcssBasePlugin = require('@csstools/postcss-focus-within');
grunt.loadNpmTasks('grunt-postcss');
@@ -156,7 +156,7 @@ grunt.initConfig({
postcss: {
options: {
processors: [
- postcssFocusWithin(/* pluginOptions */)
+ postcssBasePlugin(/* pluginOptions */)
]
},
dist: {
diff --git a/plugins/postcss-focus-within/README.md b/plugins/postcss-focus-within/README.md
index 8fe6d8619..2f4e93e72 100644
--- a/plugins/postcss-focus-within/README.md
+++ b/plugins/postcss-focus-within/README.md
@@ -1,63 +1,45 @@
# PostCSS Focus Within [
][postcss]
-[
][npm-url]
-[
][css-url]
-[
][cli-url]
-[
][discord]
+[
][npm-url] [
][css-url] [
][cli-url] [
][discord]
-[PostCSS Focus Within] lets you use the `:focus-within` pseudo-class in CSS,
-following the [Selectors Level 4 specification].
+[PostCSS Focus Within] lets you easily create new plugins following some [CSS Specification].
-It is the companion to the [focus-within polyfill].
-
-[](https://caniuse.com/#feat=css-focus-within)
+```pcss
+.foo {
+ color: red;
+}
-```css
-.my-form-field:focus-within label {
- background-color: yellow;
+.baz {
+ color: green;
}
/* becomes */
-.my-form-field[focus-within] label {
- background-color: yellow;
+.foo {
+ color: blue;
}
-.my-form-field:focus-within label {
- background-color: yellow;
+.baz {
+ color: green;
}
```
-[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
-`replaceWith` option. Also, the preservation of the original `:focus-within`
-rule can be disabled using the `preserve` option.
-
## Usage
Add [PostCSS Focus Within] to your project:
```bash
-npm install postcss postcss-focus-within --save-dev
+npm install postcss @csstools/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');
+const postcssBasePlugin = require('@csstools/postcss-focus-within');
postcss([
- postcssFocusWithin(/* pluginOptions */)
+ postcssBasePlugin(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
```
@@ -71,59 +53,42 @@ 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 not preserved.
```js
-focusWithin({ preserve: false });
+postcssBasePlugin({ preserve: true })
```
-```css
-.my-form-field:focus-within label {
- background-color: yellow;
-}
-
-/* becomes */
-
-.my-form-field[focus-within] label {
- background-color: yellow;
+```pcss
+.foo {
+ color: red;
}
-```
-
-### replaceWith
-
-The `replaceWith` option defines the selector to replace `:focus-within`. By
-default, the replacement selector is `[focus-within]`.
-
-```js
-focusWithin({ replaceWith: '.focus-within' });
-```
-```css
-.my-form-field:focus-within label {
- background-color: yellow;
+.baz {
+ color: green;
}
/* becomes */
-.my-form-field.focus-within label {
- background-color: yellow;
+.foo {
+ color: blue;
+ color: red;
}
-.my-form-field:focus-within label {
- background-color: yellow;
+.baz {
+ color: green;
}
```
-[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
+[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
+[css-url]: https://cssdb.org/#TODO
[discord]: https://discord.gg/bUadyRwkJS
-[npm-url]: https://www.npmjs.com/package/postcss-focus-within
+[npm-url]: https://www.npmjs.com/package/@csstools/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
-[Selectors Level 4 specification]: https://www.w3.org/TR/selectors-4/#the-focus-within-pseudo
+[PostCSS Focus Within]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within
+[CSS Specification]: #TODO
diff --git a/plugins/postcss-focus-within/docs/README.md b/plugins/postcss-focus-within/docs/README.md
new file mode 100644
index 000000000..df6c74f1a
--- /dev/null
+++ b/plugins/postcss-focus-within/docs/README.md
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[] 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 not preserved.
+
+```js
+({ preserve: true })
+```
+
+```pcss
+
+
+/* becomes */
+
+
+```
+
+
+[Selectors Level 4 specification]:
diff --git a/plugins/postcss-focus-within/package.json b/plugins/postcss-focus-within/package.json
index f2c97d87e..ef0cc4e34 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,22 +58,22 @@
"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",
+ "stryker": "stryker run --logLevel error",
"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"
},
- "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within#readme",
"repository": {
"type": "git",
"url": "https://github.com/csstools/postcss-plugins.git",
"directory": "plugins/postcss-focus-within"
},
- "bugs": "https://github.com/csstools/postcss-plugins/issues",
"keywords": [
"a11y",
"accessibility",
@@ -67,10 +89,14 @@
"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"
- }
+ },
+ "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within#readme",
+ "bugs": "https://github.com/csstools/postcss-plugins/issues"
}
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..523e74144
--- /dev/null
+++ b/plugins/postcss-focus-within/src/browser.js
@@ -0,0 +1,75 @@
+/* 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 = Object.assign(
+ // Default options
+ {
+ force: false,
+ replaceWith: '[focus-within]',
+ },
+ // Provided options
+ opts,
+ );
+
+ 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..e4d0b4db9 100644
--- a/plugins/postcss-focus-within/src/index.ts
+++ b/plugins/postcss-focus-within/src/index.ts
@@ -1,10 +1,19 @@
import parser from 'postcss-selector-parser';
import type { PluginCreator } from 'postcss';
-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 creator: PluginCreator = (opts?: pluginOptions) => {
+ const options = Object.assign(
+ // Default options
+ {
+ preserve: false,
+ replaceWith: '[focus-within]',
+ },
+ // Provided options
+ opts,
+ );
+ const replacementAST = parser().astSync(options.replaceWith);
return {
postcssPlugin: 'postcss-focus-within',
@@ -46,7 +55,7 @@ const creator: PluginCreator<{ preserve?: boolean, replaceWith?: string }> = (op
const clone = rule.clone({ selector: modifiedSelector });
- if (preserve) {
+ if (options.preserve) {
rule.before(clone);
} else {
rule.replaceWith(clone);
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.css b/plugins/postcss-focus-within/test/browser.css
new file mode 100644
index 000000000..e69de29bb
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..e69de29bb
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..9d738d5ac
--- /dev/null
+++ b/plugins/postcss-focus-within/test/examples/example.expect.css
@@ -0,0 +1,7 @@
+.foo {
+ color: blue;
+}
+
+.baz {
+ color: green;
+}
diff --git a/plugins/postcss-focus-within/test/examples/example.preserve-true.expect.css b/plugins/postcss-focus-within/test/examples/example.preserve-true.expect.css
new file mode 100644
index 000000000..8b020470a
--- /dev/null
+++ b/plugins/postcss-focus-within/test/examples/example.preserve-true.expect.css
@@ -0,0 +1,8 @@
+.foo {
+ color: blue;
+ color: red;
+}
+
+.baz {
+ color: green;
+}
From 7bca8ef89fa26a3499483b4a6609261f7e53c92c Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sat, 2 Jul 2022 21:28:23 +0200
Subject: [PATCH 2/8] Finishing focus within
---
plugins/postcss-focus-visible/README.md | 22 +-
plugins/postcss-focus-visible/docs/README.md | 6 +-
plugins/postcss-focus-visible/src/index.ts | 8 +-
plugins/postcss-focus-visible/test/basic.css | 4 +
.../test/basic.expect.css | 4 +
.../test/basic.preserve.expect.css | 4 +
.../test/basic.replacewith.expect.css | 4 +
.../examples/example.preserve-true.expect.css | 8 -
plugins/postcss-focus-within/.tape.mjs | 24 +-
plugins/postcss-focus-within/INSTALL.md | 34 +-
plugins/postcss-focus-within/README.md | 120 +++--
plugins/postcss-focus-within/docs/README.md | 68 ++-
plugins/postcss-focus-within/src/index.ts | 117 +++--
.../postcss-focus-within/test/_browser.html | 43 ++
.../postcss-focus-within/test/_browser.mjs | 160 +++++++
.../test/_browser_replace.html | 43 ++
plugins/postcss-focus-within/test/basic.css | 4 +
.../test/basic.expect.css | 77 ++-
.../test/basic.preserve.expect.css | 53 ++-
.../test/basic.replacewith.expect.css | 77 ++-
plugins/postcss-focus-within/test/browser.css | 11 +
.../test/browser.expect.css | 11 +
.../test/browser.replacewith.expect.css | 11 +
.../test/examples/example.expect.css | 8 +-
.../example.preserve-false.expect.css | 3 +
.../examples/example.preserve-true.expect.css | 8 -
.../examples/example.replacewith.expect.css | 3 +
.../test/generated-selector-cases.expect.css | 442 +++++++++---------
28 files changed, 913 insertions(+), 464 deletions(-)
delete mode 100644 plugins/postcss-focus-visible/test/examples/example.preserve-true.expect.css
create mode 100644 plugins/postcss-focus-within/test/_browser.html
create mode 100644 plugins/postcss-focus-within/test/_browser.mjs
create mode 100644 plugins/postcss-focus-within/test/_browser_replace.html
create mode 100644 plugins/postcss-focus-within/test/browser.replacewith.expect.css
create mode 100644 plugins/postcss-focus-within/test/examples/example.preserve-false.expect.css
delete mode 100644 plugins/postcss-focus-within/test/examples/example.preserve-true.expect.css
create mode 100644 plugins/postcss-focus-within/test/examples/example.replacewith.expect.css
diff --git a/plugins/postcss-focus-visible/README.md b/plugins/postcss-focus-visible/README.md
index 6f1f2c3e5..4a70c1210 100644
--- a/plugins/postcss-focus-visible/README.md
+++ b/plugins/postcss-focus-visible/README.md
@@ -59,10 +59,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 +72,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 +93,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..e3d0a30b3 100644
--- a/plugins/postcss-focus-visible/test/basic.expect.css
+++ b/plugins/postcss-focus-visible/test/basic.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.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..8923428ad 100644
--- a/plugins/postcss-focus-visible/test/basic.replacewith.expect.css
+++ b/plugins/postcss-focus-visible/test/basic.replacewith.expect.css
@@ -94,3 +94,7 @@ html.js-focus-visible :not([data-focus-visible-added]), .js-focus-visible html :
.foo.js-focus-visible > [data-focus-visible-added], .js-focus-visible .foo > [data-focus-visible-added] {
order: 10.5;
}
+
+[data-focus-visible-added].js-focus-visible, .js-focus-visible [data-focus-visible-added] {
+ order: 11;
+}
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-within/.tape.mjs b/plugins/postcss-focus-within/.tape.mjs
index 079384881..3f9f2e1de 100644
--- a/plugins/postcss-focus-within/.tape.mjs
+++ b/plugins/postcss-focus-within/.tape.mjs
@@ -3,41 +3,35 @@ 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,
- options: {
- preserve: false
- }
},
'examples/example': {
message: 'minimal example',
},
'examples/example:preserve-false': {
message: 'minimal example',
- options: {
- preserve: false
- }
},
'examples/example:replacewith': {
message: 'minimal example',
options: {
- replaceWith: '.css-blank'
- }
+ replaceWith: '.focus-within',
+ },
},
'browser': {
message: 'css for browser tests',
@@ -45,7 +39,7 @@ postcssTape(plugin)({
'browser:replacewith': {
message: 'css for browser tests',
options: {
- replaceWith: '.css-blank'
- }
+ replaceWith: '.focus-within',
+ },
},
});
diff --git a/plugins/postcss-focus-within/INSTALL.md b/plugins/postcss-focus-within/INSTALL.md
index e325a41dd..c8528ac02 100644
--- a/plugins/postcss-focus-within/INSTALL.md
+++ b/plugins/postcss-focus-within/INSTALL.md
@@ -10,17 +10,17 @@
Add [PostCSS Focus Within] to your project:
```bash
-npm install postcss @csstools/postcss-focus-within --save-dev
+npm install postcss postcss-focus-within --save-dev
```
Use it as a [PostCSS] plugin:
```js
const postcss = require('postcss');
-const postcssBasePlugin = require('@csstools/postcss-focus-within');
+const postcssFocusWithin = require('postcss-focus-within');
postcss([
- postcssBasePlugin(/* pluginOptions */)
+ postcssFocusWithin(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
```
@@ -29,17 +29,17 @@ postcss([
Add [PostCSS CLI] to your project:
```bash
-npm install postcss-cli @csstools/postcss-focus-within --save-dev
+npm install postcss-cli postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your `postcss.config.js` configuration file:
```js
-const postcssBasePlugin = require('@csstools/postcss-focus-within');
+const postcssFocusWithin = require('postcss-focus-within');
module.exports = {
plugins: [
- postcssBasePlugin(/* pluginOptions */)
+ postcssFocusWithin(/* pluginOptions */)
]
}
```
@@ -51,7 +51,7 @@ _Webpack version 5_
Add [PostCSS Loader] to your project:
```bash
-npm install postcss-loader @csstools/postcss-focus-within --save-dev
+npm install postcss-loader postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your Webpack configuration:
@@ -74,7 +74,7 @@ module.exports = {
postcssOptions: {
plugins: [
[
- "@csstools/postcss-focus-within",
+ "postcss-focus-within",
{
// Options
},
@@ -95,7 +95,7 @@ module.exports = {
Add [React App Rewired] and [React App Rewire PostCSS] to your project:
```bash
-npm install react-app-rewired react-app-rewire-postcss @csstools/postcss-focus-within --save-dev
+npm install react-app-rewired react-app-rewire-postcss postcss-focus-within --save-dev
```
Use [React App Rewire PostCSS] and [PostCSS Focus Within] in your
@@ -103,11 +103,11 @@ Use [React App Rewire PostCSS] and [PostCSS Focus Within] in your
```js
const reactAppRewirePostcss = require('react-app-rewire-postcss');
-const postcssBasePlugin = require('@csstools/postcss-focus-within');
+const postcssFocusWithin = require('postcss-focus-within');
module.exports = config => reactAppRewirePostcss(config, {
plugins: () => [
- postcssBasePlugin(/* pluginOptions */)
+ postcssFocusWithin(/* pluginOptions */)
]
});
```
@@ -117,18 +117,18 @@ module.exports = config => reactAppRewirePostcss(config, {
Add [Gulp PostCSS] to your project:
```bash
-npm install gulp-postcss @csstools/postcss-focus-within --save-dev
+npm install gulp-postcss postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your Gulpfile:
```js
const postcss = require('gulp-postcss');
-const postcssBasePlugin = require('@csstools/postcss-focus-within');
+const postcssFocusWithin = require('postcss-focus-within');
gulp.task('css', function () {
var plugins = [
- postcssBasePlugin(/* pluginOptions */)
+ postcssFocusWithin(/* pluginOptions */)
];
return gulp.src('./src/*.css')
@@ -142,13 +142,13 @@ gulp.task('css', function () {
Add [Grunt PostCSS] to your project:
```bash
-npm install grunt-postcss @csstools/postcss-focus-within --save-dev
+npm install grunt-postcss postcss-focus-within --save-dev
```
Use [PostCSS Focus Within] in your Gruntfile:
```js
-const postcssBasePlugin = require('@csstools/postcss-focus-within');
+const postcssFocusWithin = require('postcss-focus-within');
grunt.loadNpmTasks('grunt-postcss');
@@ -156,7 +156,7 @@ grunt.initConfig({
postcss: {
options: {
processors: [
- postcssBasePlugin(/* pluginOptions */)
+ postcssFocusWithin(/* pluginOptions */)
]
},
dist: {
diff --git a/plugins/postcss-focus-within/README.md b/plugins/postcss-focus-within/README.md
index 2f4e93e72..6d57e8bb1 100644
--- a/plugins/postcss-focus-within/README.md
+++ b/plugins/postcss-focus-within/README.md
@@ -1,45 +1,44 @@
# PostCSS Focus Within [
][postcss]
-[
][npm-url] [
][css-url] [
][cli-url] [
][discord]
+[
][npm-url] [
][css-url] [
][cli-url] [
][discord]
-[PostCSS Focus Within] lets you easily create new plugins following some [CSS Specification].
+[PostCSS Focus Within] lets you use the `:focus-within` pseudo-class in CSS,
+following the [Selectors Level 4 specification].
```pcss
-.foo {
- color: red;
-}
-
-.baz {
- color: green;
+.my-form-field:focus-within label {
+ background-color: yellow;
}
/* becomes */
-.foo {
- color: blue;
-}
-
-.baz {
- color: green;
+.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label {
+ 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
+`replaceWith` option. Also, the preservation of the original `:focus-within`
+rule can be disabled using the `preserve` option.
+
## Usage
Add [PostCSS Focus Within] to your project:
```bash
-npm install postcss @csstools/postcss-focus-within --save-dev
+npm install postcss postcss-focus-within --save-dev
```
Use it as a [PostCSS] plugin:
```js
const postcss = require('postcss');
-const postcssBasePlugin = require('@csstools/postcss-focus-within');
+const postcssFocusWithin = require('postcss-focus-within');
postcss([
- postcssBasePlugin(/* pluginOptions */)
+ postcssFocusWithin(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
```
@@ -54,41 +53,98 @@ 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
-postcssBasePlugin({ preserve: true })
+postcssFocusWithin({ preserve: false })
```
```pcss
-.foo {
- color: red;
+.my-form-field:focus-within label {
+ background-color: yellow;
}
-.baz {
- color: green;
+/* becomes */
+
+.my-form-field[focus-within].js-focus-within label, .js-focus-within .my-form-field[focus-within] label {
+ background-color: yellow;
}
+```
-/* becomes */
+### replaceWith
+
+The `replaceWith` option defines the selector to replace `:focus-within`. By
+default, the replacement selector is `[focus-within]`.
-.foo {
- color: blue;
- color: red;
+```js
+postcssFocusWithin({ replaceWith: '.focus-within' });
+```
+
+```pcss
+.my-form-field:focus-within label {
+ background-color: yellow;
}
-.baz {
- color: green;
+/* becomes */
+
+.my-form-field.focus-within.js-focus-within label, .js-focus-within .my-form-field.focus-within label {
+ 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/#TODO
+[css-url]: https://cssdb.org/#focus-within-pseudo-class
[discord]: https://discord.gg/bUadyRwkJS
-[npm-url]: https://www.npmjs.com/package/@csstools/postcss-focus-within
+[npm-url]: https://www.npmjs.com/package/postcss-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 Loader]: https://github.com/postcss/postcss-loader
[PostCSS Focus Within]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within
-[CSS Specification]: #TODO
+[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
index df6c74f1a..cd8d22648 100644
--- a/plugins/postcss-focus-within/docs/README.md
+++ b/plugins/postcss-focus-within/docs/README.md
@@ -42,10 +42,10 @@ rule can be disabled using the `preserve` option.
### 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
@@ -53,8 +53,70 @@ is preserved. By default, it is not preserved.
/* 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/src/index.ts b/plugins/postcss-focus-within/src/index.ts
index e4d0b4db9..dd2bd03c4 100644
--- a/plugins/postcss-focus-within/src/index.ts
+++ b/plugins/postcss-focus-within/src/index.ts
@@ -1,64 +1,121 @@
import parser from 'postcss-selector-parser';
import type { PluginCreator } from 'postcss';
+import isValidReplacement from './is-valid-replacement.mjs';
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: false,
+ 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 (options.preserve) {
- rule.before(clone);
- } else {
- rule.replaceWith(clone);
+ if (!options.preserve) {
+ rule.remove();
}
},
};
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..034a0d288 100644
--- a/plugins/postcss-focus-within/test/basic.expect.css
+++ b/plugins/postcss-focus-within/test/basic.expect.css
@@ -1,41 +1,35 @@
-[focus-within] {
+[focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 1;
}
-: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 {
- order: 2;
-}
-
-: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,14 +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;
}
-.escaped\:focus-within,
-.escaped\:times\:two\:focus-within,
-.escaped\:focus-within: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.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..9d430a232 100644
--- a/plugins/postcss-focus-within/test/basic.replacewith.expect.css
+++ b/plugins/postcss-focus-within/test/basic.replacewith.expect.css
@@ -1,41 +1,35 @@
-.focus-within {
+.focus-within.js-focus-within, .js-focus-within .focus-within {
order: 1;
}
-: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 {
- order: 2;
-}
-
-: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,14 +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;
}
-.escaped\:focus-within,
-.escaped\:times\:two\:focus-within,
-.escaped\:focus-within: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/browser.css b/plugins/postcss-focus-within/test/browser.css
index e69de29bb..1860c200a 100644
--- a/plugins/postcss-focus-within/test/browser.css
+++ 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
index e69de29bb..16174b186 100644
--- a/plugins/postcss-focus-within/test/browser.expect.css
+++ b/plugins/postcss-focus-within/test/browser.expect.css
@@ -0,0 +1,11 @@
+div {
+ padding: 2em;
+}
+
+div[focus-within].js-focus-within, .js-focus-within 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);
+}
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..4b3410061
--- /dev/null
+++ b/plugins/postcss-focus-within/test/browser.replacewith.expect.css
@@ -0,0 +1,11 @@
+div {
+ padding: 2em;
+}
+
+div.focus-within.js-focus-within, .js-focus-within 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);
+}
diff --git a/plugins/postcss-focus-within/test/examples/example.expect.css b/plugins/postcss-focus-within/test/examples/example.expect.css
index 9d738d5ac..1188030bd 100644
--- a/plugins/postcss-focus-within/test/examples/example.expect.css
+++ b/plugins/postcss-focus-within/test/examples/example.expect.css
@@ -1,7 +1,3 @@
-.foo {
- color: blue;
-}
-
-.baz {
- color: green;
+.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.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.preserve-true.expect.css b/plugins/postcss-focus-within/test/examples/example.preserve-true.expect.css
deleted file mode 100644
index 8b020470a..000000000
--- a/plugins/postcss-focus-within/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-within/test/examples/example.replacewith.expect.css b/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css
new file mode 100644
index 000000000..5908cfe31
--- /dev/null
+++ b/plugins/postcss-focus-within/test/examples/example.replacewith.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/generated-selector-cases.expect.css b/plugins/postcss-focus-within/test/generated-selector-cases.expect.css
index 25299452c..0b1c1eae0 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,84 @@
-[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].js-focus-within, .js-focus-within [focus-within][focus-within] {
order: 1;
}
-[focus-within] [focus-within] {
+[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] {
order: 2;
}
-[focus-within] [focus-within] {
+[focus-within].js-focus-within [focus-within], .js-focus-within [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] {
+[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] {
order: 5;
}
-[focus-within]+[focus-within] {
+[focus-within].js-focus-within+[focus-within], .js-focus-within [focus-within]+[focus-within] {
order: 6;
}
-[focus-within]+[focus-within] {
+[focus-within].js-focus-within+[focus-within], .js-focus-within [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] {
+[focus-within].js-focus-within + [focus-within], .js-focus-within [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] {
+[focus-within].js-focus-within~[focus-within], .js-focus-within [focus-within]~[focus-within] {
order: 11;
}
-[focus-within] ~ [focus-within] {
+[focus-within].js-focus-within ~ [focus-within], .js-focus-within [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].js-focus-within>[focus-within], .js-focus-within [focus-within]>[focus-within] {
order: 14;
}
-[focus-within]>[focus-within] {
+[focus-within].js-focus-within>[focus-within], .js-focus-within [focus-within]>[focus-within] {
order: 15;
}
-[focus-within] > [focus-within] {
+[focus-within].js-focus-within > [focus-within], .js-focus-within [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].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].js-focus-within, .js-focus-within [focus-within], [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 19;
}
-button[focus-within] {
+button[focus-within].js-focus-within, .js-focus-within button[focus-within] {
order: 20;
}
@@ -86,319 +86,319 @@ button[focus-within] {
order: 21;
}
-button [focus-within] {
+button.js-focus-within [focus-within], .js-focus-within button [focus-within] {
order: 22;
}
-[focus-within] button {
+[focus-within].js-focus-within button, .js-focus-within [focus-within] button {
order: 23;
}
-button [focus-within] {
+button.js-focus-within [focus-within], .js-focus-within 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] {
+button.js-focus-within+[focus-within], .js-focus-within 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] {
+button.js-focus-within + [focus-within], .js-focus-within button + [focus-within] {
order: 28;
}
-[focus-within] + button {
+[focus-within].js-focus-within + button, .js-focus-within [focus-within] + button {
order: 29;
}
-button~[focus-within] {
+button.js-focus-within~[focus-within], .js-focus-within 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] {
+button.js-focus-within ~ [focus-within], .js-focus-within button ~ [focus-within] {
order: 32;
}
-[focus-within] ~ button {
+[focus-within].js-focus-within ~ button, .js-focus-within [focus-within] ~ button {
order: 33;
}
-button>[focus-within] {
+button.js-focus-within>[focus-within], .js-focus-within button>[focus-within] {
order: 34;
}
-[focus-within]>button {
+[focus-within].js-focus-within>button, .js-focus-within [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 {
+[focus-within].js-focus-within > button, .js-focus-within [focus-within] > button {
order: 37;
}
-button,[focus-within] {
+button, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 38;
}
-[focus-within], button {
+[focus-within].js-focus-within, .js-focus-within [focus-within], button {
order: 39;
}
-.🧑🏾🎤[focus-within] {
+.🧑🏾🎤[focus-within].js-focus-within, .js-focus-within .🧑🏾🎤[focus-within] {
order: 40;
}
-[focus-within].🧑🏾🎤 {
+[focus-within].🧑🏾🎤.js-focus-within, .js-focus-within [focus-within].🧑🏾🎤 {
order: 41;
}
-.🧑🏾🎤 [focus-within] {
+.🧑🏾🎤.js-focus-within [focus-within], .js-focus-within .🧑🏾🎤 [focus-within] {
order: 42;
}
-[focus-within] .🧑🏾🎤 {
+[focus-within].js-focus-within .🧑🏾🎤, .js-focus-within [focus-within] .🧑🏾🎤 {
order: 43;
}
-.🧑🏾🎤 [focus-within] {
+.🧑🏾🎤.js-focus-within [focus-within], .js-focus-within .🧑🏾🎤 [focus-within] {
order: 44;
}
-[focus-within] .🧑🏾🎤 {
+[focus-within].js-focus-within .🧑🏾🎤, .js-focus-within [focus-within] .🧑🏾🎤 {
order: 45;
}
-.🧑🏾🎤+[focus-within] {
+.🧑🏾🎤.js-focus-within+[focus-within], .js-focus-within .🧑🏾🎤+[focus-within] {
order: 46;
}
-[focus-within]+.🧑🏾🎤 {
+[focus-within].js-focus-within+.🧑🏾🎤, .js-focus-within [focus-within]+.🧑🏾🎤 {
order: 47;
}
-.🧑🏾🎤 + [focus-within] {
+.🧑🏾🎤.js-focus-within + [focus-within], .js-focus-within .🧑🏾🎤 + [focus-within] {
order: 48;
}
-[focus-within] + .🧑🏾🎤 {
+[focus-within].js-focus-within + .🧑🏾🎤, .js-focus-within [focus-within] + .🧑🏾🎤 {
order: 49;
}
-.🧑🏾🎤~[focus-within] {
+.🧑🏾🎤.js-focus-within~[focus-within], .js-focus-within .🧑🏾🎤~[focus-within] {
order: 50;
}
-[focus-within]~.🧑🏾🎤 {
+[focus-within].js-focus-within~.🧑🏾🎤, .js-focus-within [focus-within]~.🧑🏾🎤 {
order: 51;
}
-.🧑🏾🎤 ~ [focus-within] {
+.🧑🏾🎤.js-focus-within ~ [focus-within], .js-focus-within .🧑🏾🎤 ~ [focus-within] {
order: 52;
}
-[focus-within] ~ .🧑🏾🎤 {
+[focus-within].js-focus-within ~ .🧑🏾🎤, .js-focus-within [focus-within] ~ .🧑🏾🎤 {
order: 53;
}
-.🧑🏾🎤>[focus-within] {
+.🧑🏾🎤.js-focus-within>[focus-within], .js-focus-within .🧑🏾🎤>[focus-within] {
order: 54;
}
-[focus-within]>.🧑🏾🎤 {
+[focus-within].js-focus-within>.🧑🏾🎤, .js-focus-within [focus-within]>.🧑🏾🎤 {
order: 55;
}
-.🧑🏾🎤 > [focus-within] {
+.🧑🏾🎤.js-focus-within > [focus-within], .js-focus-within .🧑🏾🎤 > [focus-within] {
order: 56;
}
-[focus-within] > .🧑🏾🎤 {
+[focus-within].js-focus-within > .🧑🏾🎤, .js-focus-within [focus-within] > .🧑🏾🎤 {
order: 57;
}
-.🧑🏾🎤,[focus-within] {
+.🧑🏾🎤, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 58;
}
-[focus-within], .🧑🏾🎤 {
+[focus-within].js-focus-within, .js-focus-within [focus-within], .🧑🏾🎤 {
order: 59;
}
-.foo[focus-within] {
+.foo[focus-within].js-focus-within, .js-focus-within .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] {
+.foo.js-focus-within [focus-within], .js-focus-within .foo [focus-within] {
order: 62;
}
-[focus-within] .foo {
+[focus-within].js-focus-within .foo, .js-focus-within [focus-within] .foo {
order: 63;
}
-.foo [focus-within] {
+.foo.js-focus-within [focus-within], .js-focus-within .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] {
+.foo.js-focus-within+[focus-within], .js-focus-within .foo+[focus-within] {
order: 66;
}
-[focus-within]+.foo {
+[focus-within].js-focus-within+.foo, .js-focus-within [focus-within]+.foo {
order: 67;
}
-.foo + [focus-within] {
+.foo.js-focus-within + [focus-within], .js-focus-within .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] {
+.foo.js-focus-within~[focus-within], .js-focus-within .foo~[focus-within] {
order: 70;
}
-[focus-within]~.foo {
+[focus-within].js-focus-within~.foo, .js-focus-within [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 {
+[focus-within].js-focus-within ~ .foo, .js-focus-within [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 {
+[focus-within].js-focus-within>.foo, .js-focus-within [focus-within]>.foo {
order: 75;
}
-.foo > [focus-within] {
+.foo.js-focus-within > [focus-within], .js-focus-within .foo > [focus-within] {
order: 76;
}
-[focus-within] > .foo {
+[focus-within].js-focus-within > .foo, .js-focus-within [focus-within] > .foo {
order: 77;
}
-.foo,[focus-within] {
+.foo, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 78;
}
-[focus-within], .foo {
+[focus-within].js-focus-within, .js-focus-within [focus-within], .foo {
order: 79;
}
-#foo[focus-within] {
+#foo[focus-within].js-focus-within, .js-focus-within #foo[focus-within] {
order: 80;
}
-[focus-within]#foo {
+[focus-within]#foo.js-focus-within, .js-focus-within [focus-within]#foo {
order: 81;
}
-#foo [focus-within] {
+#foo.js-focus-within [focus-within], .js-focus-within #foo [focus-within] {
order: 82;
}
-[focus-within] #foo {
+[focus-within].js-focus-within #foo, .js-focus-within [focus-within] #foo {
order: 83;
}
-#foo [focus-within] {
+#foo.js-focus-within [focus-within], .js-focus-within #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] {
+#foo.js-focus-within+[focus-within], .js-focus-within #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] {
+#foo.js-focus-within + [focus-within], .js-focus-within #foo + [focus-within] {
order: 88;
}
-[focus-within] + #foo {
+[focus-within].js-focus-within + #foo, .js-focus-within [focus-within] + #foo {
order: 89;
}
-#foo~[focus-within] {
+#foo.js-focus-within~[focus-within], .js-focus-within #foo~[focus-within] {
order: 90;
}
-[focus-within]~#foo {
+[focus-within].js-focus-within~#foo, .js-focus-within [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 {
+[focus-within].js-focus-within ~ #foo, .js-focus-within [focus-within] ~ #foo {
order: 93;
}
-#foo>[focus-within] {
+#foo.js-focus-within>[focus-within], .js-focus-within #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] {
+#foo.js-focus-within > [focus-within], .js-focus-within #foo > [focus-within] {
order: 96;
}
-[focus-within] > #foo {
+[focus-within].js-focus-within > #foo, .js-focus-within [focus-within] > #foo {
order: 97;
}
-#foo,[focus-within] {
+#foo, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 98;
}
-[focus-within], #foo {
+[focus-within].js-focus-within, .js-focus-within [focus-within], #foo {
order: 99;
}
-__foo[focus-within] {
+__foo[focus-within].js-focus-within, .js-focus-within __foo[focus-within] {
order: 100;
}
@@ -406,475 +406,475 @@ __foo[focus-within] {
order: 101;
}
-__foo [focus-within] {
+__foo.js-focus-within [focus-within], .js-focus-within __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] {
+__foo.js-focus-within [focus-within], .js-focus-within __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] {
+__foo.js-focus-within+[focus-within], .js-focus-within __foo+[focus-within] {
order: 106;
}
-[focus-within]+__foo {
+[focus-within].js-focus-within+__foo, .js-focus-within [focus-within]+__foo {
order: 107;
}
-__foo + [focus-within] {
+__foo.js-focus-within + [focus-within], .js-focus-within __foo + [focus-within] {
order: 108;
}
-[focus-within] + __foo {
+[focus-within].js-focus-within + __foo, .js-focus-within [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 {
+[focus-within].js-focus-within~__foo, .js-focus-within [focus-within]~__foo {
order: 111;
}
-__foo ~ [focus-within] {
+__foo.js-focus-within ~ [focus-within], .js-focus-within __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] {
+__foo.js-focus-within>[focus-within], .js-focus-within __foo>[focus-within] {
order: 114;
}
-[focus-within]>__foo {
+[focus-within].js-focus-within>__foo, .js-focus-within [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 {
+[focus-within].js-focus-within > __foo, .js-focus-within [focus-within] > __foo {
order: 117;
}
-__foo,[focus-within] {
+__foo, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 118;
}
-[focus-within], __foo {
+[focus-within].js-focus-within, .js-focus-within [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 {
+[focus-within]:--foo.js-focus-within, .js-focus-within [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 {
+[focus-within].js-focus-within :--foo, .js-focus-within [focus-within] :--foo {
order: 123;
}
-:--foo [focus-within] {
+:--foo.js-focus-within [focus-within], .js-focus-within :--foo [focus-within] {
order: 124;
}
-[focus-within] :--foo {
+[focus-within].js-focus-within :--foo, .js-focus-within [focus-within] :--foo {
order: 125;
}
-:--foo+[focus-within] {
+:--foo.js-focus-within+[focus-within], .js-focus-within :--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] {
+:--foo.js-focus-within + [focus-within], .js-focus-within :--foo + [focus-within] {
order: 128;
}
-[focus-within] + :--foo {
+[focus-within].js-focus-within + :--foo, .js-focus-within [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 {
+[focus-within].js-focus-within~:--foo, .js-focus-within [focus-within]~:--foo {
order: 131;
}
-:--foo ~ [focus-within] {
+:--foo.js-focus-within ~ [focus-within], .js-focus-within :--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] {
+:--foo.js-focus-within>[focus-within], .js-focus-within :--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] {
+:--foo.js-focus-within > [focus-within], .js-focus-within :--foo > [focus-within] {
order: 136;
}
-[focus-within] > :--foo {
+[focus-within].js-focus-within > :--foo, .js-focus-within [focus-within] > :--foo {
order: 137;
}
-:--foo,[focus-within] {
+:--foo, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 138;
}
-[focus-within], :--foo {
+[focus-within].js-focus-within, .js-focus-within [focus-within], :--foo {
order: 139;
}
-[foo="baz"][focus-within] {
+[foo="baz"][focus-within].js-focus-within, .js-focus-within [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;
}
-[foo="baz"] [focus-within] {
+[foo="baz"].js-focus-within [focus-within], .js-focus-within [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] {
+[foo="baz"].js-focus-within [focus-within], .js-focus-within [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;
}
-[foo="baz"]+[focus-within] {
+[foo="baz"].js-focus-within+[focus-within], .js-focus-within [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] {
+[foo="baz"].js-focus-within + [focus-within], .js-focus-within [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;
}
-[foo="baz"]~[focus-within] {
+[foo="baz"].js-focus-within~[focus-within], .js-focus-within [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] {
+[foo="baz"].js-focus-within ~ [focus-within], .js-focus-within [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;
}
-[foo="baz"]>[focus-within] {
+[foo="baz"].js-focus-within>[focus-within], .js-focus-within [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] {
+[foo="baz"].js-focus-within > [focus-within], .js-focus-within [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;
}
-[foo="baz"],[focus-within] {
+[foo="baz"], [focus-within].js-focus-within, .js-focus-within [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].js-focus-within, .js-focus-within *[focus-within] {
order: 160;
}
-[focus-within]* {
+[focus-within]*.js-focus-within, .js-focus-within [focus-within]* {
order: 161;
}
-* [focus-within] {
+*.js-focus-within [focus-within], .js-focus-within * [focus-within] {
order: 162;
}
-[focus-within] * {
+[focus-within].js-focus-within *, .js-focus-within [focus-within] * {
order: 163;
}
-* [focus-within] {
+*.js-focus-within [focus-within], .js-focus-within * [focus-within] {
order: 164;
}
-[focus-within] * {
+[focus-within].js-focus-within *, .js-focus-within [focus-within] * {
order: 165;
}
-*+[focus-within] {
+*.js-focus-within+[focus-within], .js-focus-within *+[focus-within] {
order: 166;
}
-[focus-within]+* {
+[focus-within].js-focus-within+*, .js-focus-within [focus-within]+* {
order: 167;
}
-* + [focus-within] {
+*.js-focus-within + [focus-within], .js-focus-within * + [focus-within] {
order: 168;
}
-[focus-within] + * {
+[focus-within].js-focus-within + *, .js-focus-within [focus-within] + * {
order: 169;
}
-*~[focus-within] {
+*.js-focus-within~[focus-within], .js-focus-within *~[focus-within] {
order: 170;
}
-[focus-within]~* {
+[focus-within].js-focus-within~*, .js-focus-within [focus-within]~* {
order: 171;
}
-* ~ [focus-within] {
+*.js-focus-within ~ [focus-within], .js-focus-within * ~ [focus-within] {
order: 172;
}
-[focus-within] ~ * {
+[focus-within].js-focus-within ~ *, .js-focus-within [focus-within] ~ * {
order: 173;
}
-*>[focus-within] {
+*.js-focus-within>[focus-within], .js-focus-within *>[focus-within] {
order: 174;
}
-[focus-within]>* {
+[focus-within].js-focus-within>*, .js-focus-within [focus-within]>* {
order: 175;
}
-* > [focus-within] {
+*.js-focus-within > [focus-within], .js-focus-within * > [focus-within] {
order: 176;
}
-[focus-within] > * {
+[focus-within].js-focus-within > *, .js-focus-within [focus-within] > * {
order: 177;
}
-*,[focus-within] {
+*, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 178;
}
-[focus-within], * {
+[focus-within].js-focus-within, .js-focus-within [focus-within], * {
order: 179;
}
-:hover[focus-within] {
+:hover[focus-within].js-focus-within, .js-focus-within :hover[focus-within] {
order: 180;
}
-[focus-within]:hover {
+[focus-within]:hover.js-focus-within, .js-focus-within [focus-within]:hover {
order: 181;
}
-:hover [focus-within] {
+:hover.js-focus-within [focus-within], .js-focus-within :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] {
+:hover.js-focus-within [focus-within], .js-focus-within :hover [focus-within] {
order: 184;
}
-[focus-within] :hover {
+[focus-within].js-focus-within :hover, .js-focus-within [focus-within] :hover {
order: 185;
}
-:hover+[focus-within] {
+:hover.js-focus-within+[focus-within], .js-focus-within :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] {
+:hover.js-focus-within + [focus-within], .js-focus-within :hover + [focus-within] {
order: 188;
}
-[focus-within] + :hover {
+[focus-within].js-focus-within + :hover, .js-focus-within [focus-within] + :hover {
order: 189;
}
-:hover~[focus-within] {
+:hover.js-focus-within~[focus-within], .js-focus-within :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] {
+:hover.js-focus-within ~ [focus-within], .js-focus-within :hover ~ [focus-within] {
order: 192;
}
-[focus-within] ~ :hover {
+[focus-within].js-focus-within ~ :hover, .js-focus-within [focus-within] ~ :hover {
order: 193;
}
-:hover>[focus-within] {
+:hover.js-focus-within>[focus-within], .js-focus-within :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] {
+:hover.js-focus-within > [focus-within], .js-focus-within :hover > [focus-within] {
order: 196;
}
-[focus-within] > :hover {
+[focus-within].js-focus-within > :hover, .js-focus-within [focus-within] > :hover {
order: 197;
}
-:hover,[focus-within] {
+:hover, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 198;
}
-[focus-within], :hover {
+[focus-within].js-focus-within, .js-focus-within [focus-within], :hover {
order: 199;
}
-::before[focus-within] {
+.js-focus-within::before[focus-within], .js-focus-within ::before[focus-within] {
order: 200;
}
-[focus-within]::before {
+[focus-within].js-focus-within::before, .js-focus-within [focus-within]::before {
order: 201;
}
-::before [focus-within] {
+.js-focus-within::before [focus-within], .js-focus-within ::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] {
+.js-focus-within::before [focus-within], .js-focus-within ::before [focus-within] {
order: 204;
}
-[focus-within] ::before {
+[focus-within].js-focus-within ::before, .js-focus-within [focus-within] ::before {
order: 205;
}
-::before+[focus-within] {
+.js-focus-within::before+[focus-within], .js-focus-within ::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] {
+.js-focus-within::before + [focus-within], .js-focus-within ::before + [focus-within] {
order: 208;
}
-[focus-within] + ::before {
+[focus-within].js-focus-within + ::before, .js-focus-within [focus-within] + ::before {
order: 209;
}
-::before~[focus-within] {
+.js-focus-within::before~[focus-within], .js-focus-within ::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] {
+.js-focus-within::before ~ [focus-within], .js-focus-within ::before ~ [focus-within] {
order: 212;
}
-[focus-within] ~ ::before {
+[focus-within].js-focus-within ~ ::before, .js-focus-within [focus-within] ~ ::before {
order: 213;
}
-::before>[focus-within] {
+.js-focus-within::before>[focus-within], .js-focus-within ::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] {
+.js-focus-within::before > [focus-within], .js-focus-within ::before > [focus-within] {
order: 216;
}
-[focus-within] > ::before {
+[focus-within].js-focus-within > ::before, .js-focus-within [focus-within] > ::before {
order: 217;
}
-::before,[focus-within] {
+::before, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 218;
}
-[focus-within], ::before {
+[focus-within].js-focus-within, .js-focus-within [focus-within], ::before {
order: 219;
}
@@ -886,7 +886,7 @@ foo[baz=":focus-within"] {
order: 221;
}
-:not([focus-within]) {
+:not([focus-within]).js-focus-within, .js-focus-within :not([focus-within]) {
order: 222;
}
@@ -894,11 +894,11 @@ foo[baz=":focus-within"] {
order: 223;
}
-:--[focus-within] {
+:--[focus-within].js-focus-within, .js-focus-within :--[focus-within] {
order: 224;
}
-__[focus-within] {
+__[focus-within].js-focus-within, .js-focus-within __[focus-within] {
order: 225;
}
From b73ffad0f8fa1e9f3ff3310b3e4d587acfadcd9c Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sat, 2 Jul 2022 22:16:58 +0200
Subject: [PATCH 3/8] Updating tests
---
package-lock.json | 34 +++++--------------
.../test/basic.autoprefixer.expect.css | 4 +++
.../test/basic.autoprefixer.false.expect.css | 4 +++
.../test/basic.ch38.expect.css | 4 +++
.../test/basic.ch88-ff78-saf10.expect.css | 4 +++
.../test/basic.ch88-ff78.expect.css | 4 +++
.../basic.ch88-ff78.no-is-pseudo.expect.css | 4 +++
.../postcss-preset-env/test/basic.expect.css | 4 +++
.../test/basic.ff49.expect.css | 4 +++
.../test/basic.ff66.expect.css | 4 +++
.../test/basic.ie10.expect.css | 5 +++
.../test/basic.nesting.false.expect.css | 4 +++
.../test/basic.op_mini.expect.css | 4 +++
.../test/basic.safari15.expect.css | 4 +++
.../test/basic.stage0-ff49.expect.css | 4 +++
.../test/basic.stage0-ff66.expect.css | 4 +++
.../test/basic.stage0.expect.css | 4 +++
.../client-side-polyfills.stage-1.expect.css | 2 +-
.../client-side-polyfills.stage-2.expect.css | 2 +-
...-client-side-polyfills.disabled.expect.css | 2 +-
.../test/layers-basic.expect.css | 8 +++++
plugins/postcss-focus-within/package.json | 7 ++--
22 files changed, 87 insertions(+), 33 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index d4af5f33a..9acb1eb8b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1806,10 +1806,6 @@
"resolved": "plugins/postcss-design-tokens",
"link": true
},
- "node_modules/@csstools/postcss-focus-within": {
- "resolved": "plugins/postcss-focus-within",
- "link": true
- },
"node_modules/@csstools/postcss-font-format-keywords": {
"resolved": "plugins/postcss-font-format-keywords",
"link": true
@@ -5381,18 +5377,8 @@
"link": true
},
"node_modules/postcss-focus-within": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz",
- "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==",
- "dependencies": {
- "postcss-selector-parser": "^6.0.9"
- },
- "engines": {
- "node": "^12 || ^14 || >=16"
- },
- "peerDependencies": {
- "postcss": "^8.4"
- }
+ "resolved": "plugins/postcss-focus-within",
+ "link": true
},
"node_modules/postcss-font-variant": {
"version": "5.0.0",
@@ -7121,9 +7107,11 @@
}
},
"plugins/postcss-focus-within": {
- "name": "@csstools/postcss-focus-within",
- "version": "1.0.0",
+ "version": "5.0.4",
"license": "CC0-1.0",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
"engines": {
"node": "^12 || ^14 || >=16"
},
@@ -8732,10 +8720,6 @@
"style-dictionary-design-tokens-example": "^1.0.0"
}
},
- "@csstools/postcss-focus-within": {
- "version": "file:plugins/postcss-focus-within",
- "requires": {}
- },
"@csstools/postcss-font-format-keywords": {
"version": "file:plugins/postcss-font-format-keywords",
"requires": {
@@ -11407,11 +11391,9 @@
}
},
"postcss-focus-within": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz",
- "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==",
+ "version": "file:plugins/postcss-focus-within",
"requires": {
- "postcss-selector-parser": "^6.0.9"
+ "postcss-selector-parser": "^6.0.10"
}
},
"postcss-font-variant": {
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/postcss-focus-within/package.json b/plugins/postcss-focus-within/package.json
index ef0cc4e34..64224f596 100644
--- a/plugins/postcss-focus-within/package.json
+++ b/plugins/postcss-focus-within/package.json
@@ -63,17 +63,18 @@
"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",
- "stryker": "stryker run --logLevel error",
"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"
},
+ "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within#readme",
"repository": {
"type": "git",
"url": "https://github.com/csstools/postcss-plugins.git",
"directory": "plugins/postcss-focus-within"
},
+ "bugs": "https://github.com/csstools/postcss-plugins/issues",
"keywords": [
"a11y",
"accessibility",
@@ -96,7 +97,5 @@
},
"volta": {
"extends": "../../package.json"
- },
- "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-focus-within#readme",
- "bugs": "https://github.com/csstools/postcss-plugins/issues"
+ }
}
From 9196298835022d299f39173ec907ac2b654b3649 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sat, 2 Jul 2022 22:27:25 +0200
Subject: [PATCH 4/8] Fixed tests after swapping preserve
---
.../test/basic.expect.css | 73 +++++++++++++++++++
.../test/basic.replacewith.expect.css | 73 +++++++++++++++++++
.../test/browser.expect.css | 4 +
.../test/examples/example.expect.css | 3 +
.../examples/example.replacewith.expect.css | 3 +
5 files changed, 156 insertions(+)
diff --git a/plugins/postcss-focus-visible/test/basic.expect.css b/plugins/postcss-focus-visible/test/basic.expect.css
index e3d0a30b3..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,46 +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.replacewith.expect.css b/plugins/postcss-focus-visible/test/basic.replacewith.expect.css
index 8923428ad..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,46 +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.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;
+}
From 4f13a1e567ae70c83f39c99000fe8e858b8d4874 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sat, 2 Jul 2022 22:30:48 +0200
Subject: [PATCH 5/8] Adding CHANGELOG
---
plugins/postcss-focus-within/CHANGELOG.md | 6 ++++++
1 file changed, 6 insertions(+)
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
From 00ea745bc2ae1f264919bb2db5e557e8828d3727 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sat, 2 Jul 2022 22:46:24 +0200
Subject: [PATCH 6/8] Updating tests
---
plugins/postcss-focus-within/.tape.mjs | 3 +
.../test/basic.expect.css | 32 +
.../test/basic.replacewith.expect.css | 32 +
.../test/browser.expect.css | 8 +
.../test/browser.replacewith.expect.css | 8 +
.../test/examples/example.expect.css | 3 +
.../examples/example.replacewith.expect.css | 3 +
.../test/generated-selector-cases.expect.css | 886 +++++++++++++++++-
8 files changed, 974 insertions(+), 1 deletion(-)
diff --git a/plugins/postcss-focus-within/.tape.mjs b/plugins/postcss-focus-within/.tape.mjs
index 3f9f2e1de..91561fece 100644
--- a/plugins/postcss-focus-within/.tape.mjs
+++ b/plugins/postcss-focus-within/.tape.mjs
@@ -26,6 +26,9 @@ postcssTape(plugin)({
},
'examples/example:preserve-false': {
message: 'minimal example',
+ options: {
+ preserve: false,
+ },
},
'examples/example:replacewith': {
message: 'minimal example',
diff --git a/plugins/postcss-focus-within/test/basic.expect.css b/plugins/postcss-focus-within/test/basic.expect.css
index 034a0d288..e85b1630c 100644
--- a/plugins/postcss-focus-within/test/basic.expect.css
+++ b/plugins/postcss-focus-within/test/basic.expect.css
@@ -2,6 +2,10 @@
order: 1;
}
+:focus-within {
+ order: 1;
+}
+
[focus-within].js-focus-within,
.js-focus-within [focus-within],
[focus-within].js-focus-within test,
@@ -33,6 +37,23 @@ test.js-focus-within :matches(test [focus-within] [focus-within] test) test,
order: 2;
}
+: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 {
+ order: 2;
+}
+
:ignore-focus-within,
:focus-within-ignore,
:ignorefocus-within,
@@ -53,6 +74,17 @@ test.js-focus-within :matches(test [focus-within] [focus-within] test) test,
order: 5;
}
+.escaped\:focus-within,
+.escaped\:times\:two\:focus-within,
+.escaped\:focus-within:focus-within,
+.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.replacewith.expect.css b/plugins/postcss-focus-within/test/basic.replacewith.expect.css
index 9d430a232..5a7666a11 100644
--- a/plugins/postcss-focus-within/test/basic.replacewith.expect.css
+++ b/plugins/postcss-focus-within/test/basic.replacewith.expect.css
@@ -2,6 +2,10 @@
order: 1;
}
+:focus-within {
+ order: 1;
+}
+
.focus-within.js-focus-within,
.js-focus-within .focus-within,
.focus-within.js-focus-within test,
@@ -33,6 +37,23 @@ test.js-focus-within :matches(test .focus-within .focus-within test) test,
order: 2;
}
+: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 {
+ order: 2;
+}
+
:ignore-focus-within,
:focus-within-ignore,
:ignorefocus-within,
@@ -53,6 +74,17 @@ test.js-focus-within :matches(test .focus-within .focus-within test) test,
order: 5;
}
+.escaped\:focus-within,
+.escaped\:times\:two\:focus-within,
+.escaped\:focus-within:focus-within,
+.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.expect.css b/plugins/postcss-focus-within/test/browser.expect.css
index 16174b186..0d9156ca7 100644
--- a/plugins/postcss-focus-within/test/browser.expect.css
+++ b/plugins/postcss-focus-within/test/browser.expect.css
@@ -6,6 +6,14 @@ 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
index 4b3410061..5e2ad9944 100644
--- a/plugins/postcss-focus-within/test/browser.replacewith.expect.css
+++ b/plugins/postcss-focus-within/test/browser.replacewith.expect.css
@@ -6,6 +6,14 @@ 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.expect.css b/plugins/postcss-focus-within/test/examples/example.expect.css
index 1188030bd..fe6084d56 100644
--- a/plugins/postcss-focus-within/test/examples/example.expect.css
+++ b/plugins/postcss-focus-within/test/examples/example.expect.css
@@ -1,3 +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.replacewith.expect.css b/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css
index 5908cfe31..cab94c735 100644
--- a/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css
+++ b/plugins/postcss-focus-within/test/examples/example.replacewith.expect.css
@@ -1,3 +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 0b1c1eae0..b3fb1623e 100644
--- a/plugins/postcss-focus-within/test/generated-selector-cases.expect.css
+++ b/plugins/postcss-focus-within/test/generated-selector-cases.expect.css
@@ -2,86 +2,170 @@
order: 0;
}
+: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 {
+ order: 1;
+}
+
[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] {
order: 2;
}
+: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].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] {
order: 4;
}
+:focus-within :focus-within {
+ order: 4;
+}
+
[focus-within].js-focus-within [focus-within], .js-focus-within [focus-within] [focus-within] {
order: 5;
}
+: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 {
+ 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].js-focus-within + [focus-within], .js-focus-within [focus-within] + [focus-within] {
order: 8;
}
+:focus-within + :focus-within {
+ order: 8;
+}
+
[focus-within].js-focus-within + [focus-within], .js-focus-within [focus-within] + [focus-within] {
order: 9;
}
+:focus-within + :focus-within {
+ order: 9;
+}
+
[focus-within].js-focus-within~[focus-within], .js-focus-within [focus-within]~[focus-within] {
order: 10;
}
+:focus-within~:focus-within {
+ order: 10;
+}
+
[focus-within].js-focus-within~[focus-within], .js-focus-within [focus-within]~[focus-within] {
order: 11;
}
+: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].js-focus-within ~ [focus-within], .js-focus-within [focus-within] ~ [focus-within] {
order: 13;
}
+: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 {
+ order: 14;
+}
+
[focus-within].js-focus-within>[focus-within], .js-focus-within [focus-within]>[focus-within] {
order: 15;
}
+: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].js-focus-within > [focus-within], .js-focus-within [focus-within] > [focus-within] {
order: 17;
}
+: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 {
+ order: 18;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 19;
}
+: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;
+}
+
:focus-withinbutton {
order: 21;
}
@@ -90,318 +174,634 @@ button.js-focus-within [focus-within], .js-focus-within button [focus-within] {
order: 22;
}
+button :focus-within {
+ order: 22;
+}
+
[focus-within].js-focus-within button, .js-focus-within [focus-within] button {
order: 23;
}
+:focus-within button {
+ order: 23;
+}
+
button.js-focus-within [focus-within], .js-focus-within button [focus-within] {
order: 24;
}
+button :focus-within {
+ order: 24;
+}
+
[focus-within].js-focus-within button, .js-focus-within [focus-within] button {
order: 25;
}
+: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].js-focus-within+button, .js-focus-within [focus-within]+button {
order: 27;
}
+:focus-within+button {
+ order: 27;
+}
+
button.js-focus-within + [focus-within], .js-focus-within button + [focus-within] {
order: 28;
}
+button + :focus-within {
+ order: 28;
+}
+
[focus-within].js-focus-within + button, .js-focus-within [focus-within] + button {
order: 29;
}
+: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].js-focus-within~button, .js-focus-within [focus-within]~button {
order: 31;
}
+: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].js-focus-within ~ button, .js-focus-within [focus-within] ~ button {
order: 33;
}
+:focus-within ~ button {
+ order: 33;
+}
+
button.js-focus-within>[focus-within], .js-focus-within button>[focus-within] {
order: 34;
}
+button>:focus-within {
+ order: 34;
+}
+
[focus-within].js-focus-within>button, .js-focus-within [focus-within]>button {
order: 35;
}
+:focus-within>button {
+ order: 35;
+}
+
button.js-focus-within > [focus-within], .js-focus-within button > [focus-within] {
order: 36;
}
+button > :focus-within {
+ order: 36;
+}
+
[focus-within].js-focus-within > button, .js-focus-within [focus-within] > button {
order: 37;
}
+: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].js-focus-within, .js-focus-within [focus-within], button {
order: 39;
}
+:focus-within, button {
+ order: 39;
+}
+
.🧑🏾🎤[focus-within].js-focus-within, .js-focus-within .🧑🏾🎤[focus-within] {
order: 40;
}
+.🧑🏾🎤:focus-within {
+ order: 40;
+}
+
[focus-within].🧑🏾🎤.js-focus-within, .js-focus-within [focus-within].🧑🏾🎤 {
order: 41;
}
+:focus-within.🧑🏾🎤 {
+ order: 41;
+}
+
.🧑🏾🎤.js-focus-within [focus-within], .js-focus-within .🧑🏾🎤 [focus-within] {
order: 42;
}
+.🧑🏾🎤 :focus-within {
+ order: 42;
+}
+
[focus-within].js-focus-within .🧑🏾🎤, .js-focus-within [focus-within] .🧑🏾🎤 {
order: 43;
}
+:focus-within .🧑🏾🎤 {
+ order: 43;
+}
+
.🧑🏾🎤.js-focus-within [focus-within], .js-focus-within .🧑🏾🎤 [focus-within] {
order: 44;
}
+.🧑🏾🎤 :focus-within {
+ order: 44;
+}
+
[focus-within].js-focus-within .🧑🏾🎤, .js-focus-within [focus-within] .🧑🏾🎤 {
order: 45;
}
+:focus-within .🧑🏾🎤 {
+ order: 45;
+}
+
.🧑🏾🎤.js-focus-within+[focus-within], .js-focus-within .🧑🏾🎤+[focus-within] {
order: 46;
}
+.🧑🏾🎤+:focus-within {
+ order: 46;
+}
+
[focus-within].js-focus-within+.🧑🏾🎤, .js-focus-within [focus-within]+.🧑🏾🎤 {
order: 47;
}
+:focus-within+.🧑🏾🎤 {
+ order: 47;
+}
+
.🧑🏾🎤.js-focus-within + [focus-within], .js-focus-within .🧑🏾🎤 + [focus-within] {
order: 48;
}
+.🧑🏾🎤 + :focus-within {
+ order: 48;
+}
+
[focus-within].js-focus-within + .🧑🏾🎤, .js-focus-within [focus-within] + .🧑🏾🎤 {
order: 49;
}
+:focus-within + .🧑🏾🎤 {
+ order: 49;
+}
+
.🧑🏾🎤.js-focus-within~[focus-within], .js-focus-within .🧑🏾🎤~[focus-within] {
order: 50;
}
+.🧑🏾🎤~:focus-within {
+ order: 50;
+}
+
[focus-within].js-focus-within~.🧑🏾🎤, .js-focus-within [focus-within]~.🧑🏾🎤 {
order: 51;
}
+:focus-within~.🧑🏾🎤 {
+ order: 51;
+}
+
.🧑🏾🎤.js-focus-within ~ [focus-within], .js-focus-within .🧑🏾🎤 ~ [focus-within] {
order: 52;
}
+.🧑🏾🎤 ~ :focus-within {
+ order: 52;
+}
+
[focus-within].js-focus-within ~ .🧑🏾🎤, .js-focus-within [focus-within] ~ .🧑🏾🎤 {
order: 53;
}
+:focus-within ~ .🧑🏾🎤 {
+ order: 53;
+}
+
.🧑🏾🎤.js-focus-within>[focus-within], .js-focus-within .🧑🏾🎤>[focus-within] {
order: 54;
}
+.🧑🏾🎤>:focus-within {
+ order: 54;
+}
+
[focus-within].js-focus-within>.🧑🏾🎤, .js-focus-within [focus-within]>.🧑🏾🎤 {
order: 55;
}
+:focus-within>.🧑🏾🎤 {
+ order: 55;
+}
+
.🧑🏾🎤.js-focus-within > [focus-within], .js-focus-within .🧑🏾🎤 > [focus-within] {
order: 56;
}
+.🧑🏾🎤 > :focus-within {
+ order: 56;
+}
+
[focus-within].js-focus-within > .🧑🏾🎤, .js-focus-within [focus-within] > .🧑🏾🎤 {
order: 57;
}
+:focus-within > .🧑🏾🎤 {
+ order: 57;
+}
+
.🧑🏾🎤, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 58;
}
+.🧑🏾🎤, :focus-within {
+ order: 58;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], .🧑🏾🎤 {
order: 59;
}
+: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.js-focus-within, .js-focus-within [focus-within].foo {
order: 61;
}
+:focus-within.foo {
+ order: 61;
+}
+
.foo.js-focus-within [focus-within], .js-focus-within .foo [focus-within] {
order: 62;
}
+.foo :focus-within {
+ order: 62;
+}
+
[focus-within].js-focus-within .foo, .js-focus-within [focus-within] .foo {
order: 63;
}
+: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].js-focus-within .foo, .js-focus-within [focus-within] .foo {
order: 65;
}
+: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].js-focus-within+.foo, .js-focus-within [focus-within]+.foo {
order: 67;
}
+:focus-within+.foo {
+ order: 67;
+}
+
.foo.js-focus-within + [focus-within], .js-focus-within .foo + [focus-within] {
order: 68;
}
+.foo + :focus-within {
+ order: 68;
+}
+
[focus-within].js-focus-within + .foo, .js-focus-within [focus-within] + .foo {
order: 69;
}
+: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].js-focus-within~.foo, .js-focus-within [focus-within]~.foo {
order: 71;
}
+:focus-within~.foo {
+ order: 71;
+}
+
.foo.js-focus-within ~ [focus-within], .js-focus-within .foo ~ [focus-within] {
order: 72;
}
+.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.js-focus-within>[focus-within], .js-focus-within .foo>[focus-within] {
order: 74;
}
+.foo>:focus-within {
+ order: 74;
+}
+
[focus-within].js-focus-within>.foo, .js-focus-within [focus-within]>.foo {
order: 75;
}
+:focus-within>.foo {
+ order: 75;
+}
+
.foo.js-focus-within > [focus-within], .js-focus-within .foo > [focus-within] {
order: 76;
}
+.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].js-focus-within, .js-focus-within [focus-within] {
order: 78;
}
+.foo, :focus-within {
+ order: 78;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], .foo {
order: 79;
}
+:focus-within, .foo {
+ order: 79;
+}
+
#foo[focus-within].js-focus-within, .js-focus-within #foo[focus-within] {
order: 80;
}
+#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.js-focus-within [focus-within], .js-focus-within #foo [focus-within] {
order: 82;
}
+#foo :focus-within {
+ order: 82;
+}
+
[focus-within].js-focus-within #foo, .js-focus-within [focus-within] #foo {
order: 83;
}
+:focus-within #foo {
+ order: 83;
+}
+
#foo.js-focus-within [focus-within], .js-focus-within #foo [focus-within] {
order: 84;
}
+#foo :focus-within {
+ order: 84;
+}
+
[focus-within].js-focus-within #foo, .js-focus-within [focus-within] #foo {
order: 85;
}
+: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].js-focus-within+#foo, .js-focus-within [focus-within]+#foo {
order: 87;
}
+:focus-within+#foo {
+ order: 87;
+}
+
#foo.js-focus-within + [focus-within], .js-focus-within #foo + [focus-within] {
order: 88;
}
+#foo + :focus-within {
+ order: 88;
+}
+
[focus-within].js-focus-within + #foo, .js-focus-within [focus-within] + #foo {
order: 89;
}
+: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].js-focus-within~#foo, .js-focus-within [focus-within]~#foo {
order: 91;
}
+:focus-within~#foo {
+ order: 91;
+}
+
#foo.js-focus-within ~ [focus-within], .js-focus-within #foo ~ [focus-within] {
order: 92;
}
+#foo ~ :focus-within {
+ order: 92;
+}
+
[focus-within].js-focus-within ~ #foo, .js-focus-within [focus-within] ~ #foo {
order: 93;
}
+: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].js-focus-within>#foo, .js-focus-within [focus-within]>#foo {
order: 95;
}
+: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].js-focus-within > #foo, .js-focus-within [focus-within] > #foo {
order: 97;
}
+:focus-within > #foo {
+ order: 97;
+}
+
#foo, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 98;
}
+#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].js-focus-within, .js-focus-within __foo[focus-within] {
order: 100;
}
+__foo:focus-within {
+ order: 100;
+}
+
:focus-within__foo {
order: 101;
}
@@ -410,143 +810,287 @@ __foo.js-focus-within [focus-within], .js-focus-within __foo [focus-within] {
order: 102;
}
+__foo :focus-within {
+ order: 102;
+}
+
[focus-within].js-focus-within __foo, .js-focus-within [focus-within] __foo {
order: 103;
}
+: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].js-focus-within __foo, .js-focus-within [focus-within] __foo {
order: 105;
}
+:focus-within __foo {
+ order: 105;
+}
+
__foo.js-focus-within+[focus-within], .js-focus-within __foo+[focus-within] {
order: 106;
}
+__foo+:focus-within {
+ order: 106;
+}
+
[focus-within].js-focus-within+__foo, .js-focus-within [focus-within]+__foo {
order: 107;
}
+: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].js-focus-within + __foo, .js-focus-within [focus-within] + __foo {
order: 109;
}
+:focus-within + __foo {
+ order: 109;
+}
+
__foo.js-focus-within~[focus-within], .js-focus-within __foo~[focus-within] {
order: 110;
}
+__foo~:focus-within {
+ order: 110;
+}
+
[focus-within].js-focus-within~__foo, .js-focus-within [focus-within]~__foo {
order: 111;
}
+: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].js-focus-within ~ __foo, .js-focus-within [focus-within] ~ __foo {
order: 113;
}
+: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].js-focus-within>__foo, .js-focus-within [focus-within]>__foo {
order: 115;
}
+:focus-within>__foo {
+ order: 115;
+}
+
__foo.js-focus-within > [focus-within], .js-focus-within __foo > [focus-within] {
order: 116;
}
+__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].js-focus-within, .js-focus-within [focus-within] {
order: 118;
}
+__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].js-focus-within, .js-focus-within :--foo[focus-within] {
order: 120;
}
+:--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.js-focus-within [focus-within], .js-focus-within :--foo [focus-within] {
order: 122;
}
+:--foo :focus-within {
+ order: 122;
+}
+
[focus-within].js-focus-within :--foo, .js-focus-within [focus-within] :--foo {
order: 123;
}
+:focus-within :--foo {
+ order: 123;
+}
+
:--foo.js-focus-within [focus-within], .js-focus-within :--foo [focus-within] {
order: 124;
}
+:--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.js-focus-within+[focus-within], .js-focus-within :--foo+[focus-within] {
order: 126;
}
+:--foo+:focus-within {
+ order: 126;
+}
+
[focus-within].js-focus-within+:--foo, .js-focus-within [focus-within]+:--foo {
order: 127;
}
+:focus-within+:--foo {
+ order: 127;
+}
+
:--foo.js-focus-within + [focus-within], .js-focus-within :--foo + [focus-within] {
order: 128;
}
+:--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.js-focus-within~[focus-within], .js-focus-within :--foo~[focus-within] {
order: 130;
}
+:--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.js-focus-within ~ [focus-within], .js-focus-within :--foo ~ [focus-within] {
order: 132;
}
+:--foo ~ :focus-within {
+ order: 132;
+}
+
[focus-within].js-focus-within ~ :--foo, .js-focus-within [focus-within] ~ :--foo {
order: 133;
}
+: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].js-focus-within>:--foo, .js-focus-within [focus-within]>:--foo {
order: 135;
}
+:focus-within>:--foo {
+ order: 135;
+}
+
:--foo.js-focus-within > [focus-within], .js-focus-within :--foo > [focus-within] {
order: 136;
}
-[focus-within].js-focus-within > :--foo, .js-focus-within [focus-within] > :--foo {
+:--foo > :focus-within {
+ order: 136;
+}
+
+[focus-within].js-focus-within > :--foo, .js-focus-within [focus-within] > :--foo {
+ order: 137;
+}
+
+:focus-within > :--foo {
order: 137;
}
@@ -554,330 +1098,658 @@ __foo, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 138;
}
+:--foo, :focus-within {
+ order: 138;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], :--foo {
order: 139;
}
+: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"].js-focus-within, .js-focus-within [focus-within][foo="baz"] {
order: 141;
}
+:focus-within[foo="baz"] {
+ order: 141;
+}
+
[foo="baz"].js-focus-within [focus-within], .js-focus-within [foo="baz"] [focus-within] {
order: 142;
}
+[foo="baz"] :focus-within {
+ order: 142;
+}
+
[focus-within].js-focus-within [foo="baz"], .js-focus-within [focus-within] [foo="baz"] {
order: 143;
}
+: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].js-focus-within [foo="baz"], .js-focus-within [focus-within] [foo="baz"] {
order: 145;
}
+:focus-within [foo="baz"] {
+ order: 145;
+}
+
[foo="baz"].js-focus-within+[focus-within], .js-focus-within [foo="baz"]+[focus-within] {
order: 146;
}
+[foo="baz"]+:focus-within {
+ order: 146;
+}
+
[focus-within].js-focus-within+[foo="baz"], .js-focus-within [focus-within]+[foo="baz"] {
order: 147;
}
+: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].js-focus-within + [foo="baz"], .js-focus-within [focus-within] + [foo="baz"] {
order: 149;
}
+:focus-within + [foo="baz"] {
+ order: 149;
+}
+
[foo="baz"].js-focus-within~[focus-within], .js-focus-within [foo="baz"]~[focus-within] {
order: 150;
}
+[foo="baz"]~:focus-within {
+ order: 150;
+}
+
[focus-within].js-focus-within~[foo="baz"], .js-focus-within [focus-within]~[foo="baz"] {
order: 151;
}
+: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].js-focus-within ~ [foo="baz"], .js-focus-within [focus-within] ~ [foo="baz"] {
order: 153;
}
+:focus-within ~ [foo="baz"] {
+ order: 153;
+}
+
[foo="baz"].js-focus-within>[focus-within], .js-focus-within [foo="baz"]>[focus-within] {
order: 154;
}
+[foo="baz"]>:focus-within {
+ order: 154;
+}
+
[focus-within].js-focus-within>[foo="baz"], .js-focus-within [focus-within]>[foo="baz"] {
order: 155;
}
+: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].js-focus-within > [foo="baz"], .js-focus-within [focus-within] > [foo="baz"] {
order: 157;
}
+:focus-within > [foo="baz"] {
+ order: 157;
+}
+
[foo="baz"], [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 158;
}
+[foo="baz"], :focus-within {
+ order: 158;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], [foo="baz"] {
order: 159;
}
+:focus-within, [foo="baz"] {
+ order: 159;
+}
+
*[focus-within].js-focus-within, .js-focus-within *[focus-within] {
order: 160;
}
+*:focus-within {
+ order: 160;
+}
+
[focus-within]*.js-focus-within, .js-focus-within [focus-within]* {
order: 161;
}
+:focus-within* {
+ order: 161;
+}
+
*.js-focus-within [focus-within], .js-focus-within * [focus-within] {
order: 162;
}
+* :focus-within {
+ order: 162;
+}
+
[focus-within].js-focus-within *, .js-focus-within [focus-within] * {
order: 163;
}
+:focus-within * {
+ order: 163;
+}
+
*.js-focus-within [focus-within], .js-focus-within * [focus-within] {
order: 164;
}
+* :focus-within {
+ order: 164;
+}
+
[focus-within].js-focus-within *, .js-focus-within [focus-within] * {
order: 165;
}
+:focus-within * {
+ order: 165;
+}
+
*.js-focus-within+[focus-within], .js-focus-within *+[focus-within] {
order: 166;
}
+*+:focus-within {
+ order: 166;
+}
+
[focus-within].js-focus-within+*, .js-focus-within [focus-within]+* {
order: 167;
}
+:focus-within+* {
+ order: 167;
+}
+
*.js-focus-within + [focus-within], .js-focus-within * + [focus-within] {
order: 168;
}
+* + :focus-within {
+ order: 168;
+}
+
[focus-within].js-focus-within + *, .js-focus-within [focus-within] + * {
order: 169;
}
+:focus-within + * {
+ order: 169;
+}
+
*.js-focus-within~[focus-within], .js-focus-within *~[focus-within] {
order: 170;
}
+*~:focus-within {
+ order: 170;
+}
+
[focus-within].js-focus-within~*, .js-focus-within [focus-within]~* {
order: 171;
}
+:focus-within~* {
+ order: 171;
+}
+
*.js-focus-within ~ [focus-within], .js-focus-within * ~ [focus-within] {
order: 172;
}
+* ~ :focus-within {
+ order: 172;
+}
+
[focus-within].js-focus-within ~ *, .js-focus-within [focus-within] ~ * {
order: 173;
}
+:focus-within ~ * {
+ order: 173;
+}
+
*.js-focus-within>[focus-within], .js-focus-within *>[focus-within] {
order: 174;
}
+*>:focus-within {
+ order: 174;
+}
+
[focus-within].js-focus-within>*, .js-focus-within [focus-within]>* {
order: 175;
}
+:focus-within>* {
+ order: 175;
+}
+
*.js-focus-within > [focus-within], .js-focus-within * > [focus-within] {
order: 176;
}
+* > :focus-within {
+ order: 176;
+}
+
[focus-within].js-focus-within > *, .js-focus-within [focus-within] > * {
order: 177;
}
+:focus-within > * {
+ order: 177;
+}
+
*, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 178;
}
+*, :focus-within {
+ order: 178;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], * {
order: 179;
}
+: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.js-focus-within, .js-focus-within [focus-within]:hover {
order: 181;
}
+:focus-within:hover {
+ order: 181;
+}
+
:hover.js-focus-within [focus-within], .js-focus-within :hover [focus-within] {
order: 182;
}
+:hover :focus-within {
+ order: 182;
+}
+
[focus-within].js-focus-within :hover, .js-focus-within [focus-within] :hover {
order: 183;
}
+: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].js-focus-within :hover, .js-focus-within [focus-within] :hover {
order: 185;
}
+:focus-within :hover {
+ order: 185;
+}
+
:hover.js-focus-within+[focus-within], .js-focus-within :hover+[focus-within] {
order: 186;
}
+:hover+:focus-within {
+ order: 186;
+}
+
[focus-within].js-focus-within+:hover, .js-focus-within [focus-within]+:hover {
order: 187;
}
+: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].js-focus-within + :hover, .js-focus-within [focus-within] + :hover {
order: 189;
}
+:focus-within + :hover {
+ order: 189;
+}
+
:hover.js-focus-within~[focus-within], .js-focus-within :hover~[focus-within] {
order: 190;
}
+:hover~:focus-within {
+ order: 190;
+}
+
[focus-within].js-focus-within~:hover, .js-focus-within [focus-within]~:hover {
order: 191;
}
+: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].js-focus-within ~ :hover, .js-focus-within [focus-within] ~ :hover {
order: 193;
}
+:focus-within ~ :hover {
+ order: 193;
+}
+
:hover.js-focus-within>[focus-within], .js-focus-within :hover>[focus-within] {
order: 194;
}
+:hover>:focus-within {
+ order: 194;
+}
+
[focus-within].js-focus-within>:hover, .js-focus-within [focus-within]>:hover {
order: 195;
}
+: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].js-focus-within > :hover, .js-focus-within [focus-within] > :hover {
order: 197;
}
+:focus-within > :hover {
+ order: 197;
+}
+
:hover, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 198;
}
+:hover, :focus-within {
+ order: 198;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], :hover {
order: 199;
}
+: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].js-focus-within::before, .js-focus-within [focus-within]::before {
order: 201;
}
+:focus-within::before {
+ order: 201;
+}
+
.js-focus-within::before [focus-within], .js-focus-within ::before [focus-within] {
order: 202;
}
+::before :focus-within {
+ order: 202;
+}
+
[focus-within].js-focus-within ::before, .js-focus-within [focus-within] ::before {
order: 203;
}
+: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].js-focus-within ::before, .js-focus-within [focus-within] ::before {
order: 205;
}
+:focus-within ::before {
+ order: 205;
+}
+
.js-focus-within::before+[focus-within], .js-focus-within ::before+[focus-within] {
order: 206;
}
+::before+:focus-within {
+ order: 206;
+}
+
[focus-within].js-focus-within+::before, .js-focus-within [focus-within]+::before {
order: 207;
}
+: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].js-focus-within + ::before, .js-focus-within [focus-within] + ::before {
order: 209;
}
+:focus-within + ::before {
+ order: 209;
+}
+
.js-focus-within::before~[focus-within], .js-focus-within ::before~[focus-within] {
order: 210;
}
+::before~:focus-within {
+ order: 210;
+}
+
[focus-within].js-focus-within~::before, .js-focus-within [focus-within]~::before {
order: 211;
}
+: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].js-focus-within ~ ::before, .js-focus-within [focus-within] ~ ::before {
order: 213;
}
+:focus-within ~ ::before {
+ order: 213;
+}
+
.js-focus-within::before>[focus-within], .js-focus-within ::before>[focus-within] {
order: 214;
}
+::before>:focus-within {
+ order: 214;
+}
+
[focus-within].js-focus-within>::before, .js-focus-within [focus-within]>::before {
order: 215;
}
+: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].js-focus-within > ::before, .js-focus-within [focus-within] > ::before {
order: 217;
}
+:focus-within > ::before {
+ order: 217;
+}
+
::before, [focus-within].js-focus-within, .js-focus-within [focus-within] {
order: 218;
}
+::before, :focus-within {
+ order: 218;
+}
+
[focus-within].js-focus-within, .js-focus-within [focus-within], ::before {
order: 219;
}
+:focus-within, ::before {
+ order: 219;
+}
+
foo[:focus-within] {
order: 220;
}
@@ -890,6 +1762,10 @@ foo[baz=":focus-within"] {
order: 222;
}
+:not(:focus-within) {
+ order: 222;
+}
+
::focus-within {
order: 223;
}
@@ -898,8 +1774,16 @@ foo[baz=":focus-within"] {
order: 224;
}
+:--:focus-within {
+ order: 224;
+}
+
__[focus-within].js-focus-within, .js-focus-within __[focus-within] {
order: 225;
}
+__:focus-within {
+ order: 225;
+}
+
/* :focus-within */
From dda9f901f4b585166bdd4a0799d7e9ebe4695541 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sun, 3 Jul 2022 11:46:42 +0200
Subject: [PATCH 7/8] Generating docs
---
plugins/postcss-focus-visible/README.md | 3 +++
plugins/postcss-focus-within/README.md | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/plugins/postcss-focus-visible/README.md b/plugins/postcss-focus-visible/README.md
index 4a70c1210..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
diff --git a/plugins/postcss-focus-within/README.md b/plugins/postcss-focus-within/README.md
index 6d57e8bb1..a38a13ed6 100644
--- a/plugins/postcss-focus-within/README.md
+++ b/plugins/postcss-focus-within/README.md
@@ -15,6 +15,9 @@ following the [Selectors Level 4 specification].
.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;
+}
```
[PostCSS Focus Within] duplicates rules using the `:focus-within` pseudo-class
@@ -90,6 +93,9 @@ postcssFocusWithin({ replaceWith: '.focus-within' });
.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;
+}
```
Note that changing this option implies that it needs to be passed to the
From a0d7a6f263607d155d3ae12799dfec3ed2690d32 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Sun, 3 Jul 2022 11:58:26 +0200
Subject: [PATCH 8/8] Better options for older browsers
---
plugins/css-blank-pseudo/src/browser.js | 21 ++++++++++++---------
plugins/postcss-focus-within/src/browser.js | 21 ++++++++++++---------
2 files changed, 24 insertions(+), 18 deletions(-)
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-within/src/browser.js b/plugins/postcss-focus-within/src/browser.js
index 523e74144..6a225a7bd 100644
--- a/plugins/postcss-focus-within/src/browser.js
+++ b/plugins/postcss-focus-within/src/browser.js
@@ -37,15 +37,18 @@ function generateHandler(replaceWith) {
export default function focusWithin(opts) {
// configuration
- const options = Object.assign(
- // Default options
- {
- force: false,
- replaceWith: '[focus-within]',
- },
- // Provided options
- opts,
- );
+ 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.`);