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 6a8ea282f..df2e849b7 100644 --- a/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.autoprefixer.expect.css @@ -261,7 +261,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 6a8ea282f..df2e849b7 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 @@ -261,7 +261,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 d5e80bf15..2e884a904 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ch38.expect.css @@ -181,7 +181,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 0df0a119f..14a3536cc 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 @@ -180,7 +180,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 c1ba4a360..9c8b1ddce 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 @@ -173,7 +173,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 f4fbf57c8..5c6131ecb 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 @@ -173,7 +173,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } diff --git a/plugin-packs/postcss-preset-env/test/basic.expect.css b/plugin-packs/postcss-preset-env/test/basic.expect.css index 3a2b5e9b6..62e0e957d 100644 --- a/plugin-packs/postcss-preset-env/test/basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.expect.css @@ -284,7 +284,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 fd1f48df0..6bea06f27 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff49.expect.css @@ -177,7 +177,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 6f93d7f18..276166755 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ff66.expect.css @@ -165,7 +165,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 62bcc0c68..e475ca11e 100644 --- a/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.ie10.expect.css @@ -293,7 +293,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 6e1f87b3a..76d385880 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 @@ -282,7 +282,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 1e56d5067..9b89b3b49 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 @@ -268,7 +268,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } diff --git a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css index 39447cc3b..6d71291f0 100644 --- a/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.preserve.true.expect.css @@ -516,7 +516,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 a214545b5..d8f82604b 100644 --- a/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.safari15.expect.css @@ -149,7 +149,7 @@ background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 d646ebd31..cc04ea10a 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 @@ -182,7 +182,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 de89ffbc6..a3f082c8d 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 @@ -170,7 +170,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 a9bd25c7a..432db8789 100644 --- a/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css +++ b/plugin-packs/postcss-preset-env/test/basic.stage0.expect.css @@ -289,7 +289,7 @@ h1.test-custom-selectors,h2.test-custom-selectors,h3.test-custom-selectors,h4.te background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank] { +.test-blank-pseudo-class[blank].js-blank-pseudo, .js-blank-pseudo .test-blank-pseudo-class[blank] { background-color: yellow; } 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 2cdadb7a2..fc8aa501a 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 @@ -1,4 +1,4 @@ -[blank] { +[blank].js-blank-pseudo, .js-blank-pseudo [blank] { order: 1; } 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 cd2b2b435..f6292a76f 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 @@ -1,4 +1,4 @@ -input[blank] { +input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] { order: 1; } 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 9ac9a6736..5e75036d8 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.expect.css @@ -466,7 +466,7 @@ h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-blank-pseudo-class[blank].js-blank-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), .js-blank-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-blank-pseudo-class[blank] { background-color: yellow; } diff --git a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css index 89d963211..8ec136827 100644 --- a/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css +++ b/plugin-packs/postcss-preset-env/test/layers-basic.preserve.true.expect.css @@ -527,7 +527,7 @@ h1.test-custom-selectors:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):n background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg); } -.test-blank-pseudo-class[blank]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { +.test-blank-pseudo-class[blank].js-blank-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#), .js-blank-pseudo:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) .test-blank-pseudo-class[blank] { background-color: yellow; } diff --git a/plugins/css-blank-pseudo/README.md b/plugins/css-blank-pseudo/README.md index 4179bd424..8729637c7 100644 --- a/plugins/css-blank-pseudo/README.md +++ b/plugins/css-blank-pseudo/README.md @@ -12,7 +12,7 @@ input:blank { /* becomes */ -input[blank] { +input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] { background-color: yellow; } input:blank { @@ -63,7 +63,7 @@ input:blank { /* becomes */ -input[blank] { +input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] { background-color: yellow; } ``` @@ -149,6 +149,9 @@ cssBlankPseudoInit({ replaceWith: '.css-blank' }); ``` This option should be used if it was changed at PostCSS configuration level. +Please note that using a class, leverages `classList` under the hood which +might not be supported on some old browsers such as IE9, so you may need +to polyfill `classList` in those cases. [cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test [css-url]: https://cssdb.org/#blank-pseudo-class diff --git a/plugins/css-blank-pseudo/docs/README.md b/plugins/css-blank-pseudo/docs/README.md index fbd96f626..9ddbd33b8 100644 --- a/plugins/css-blank-pseudo/docs/README.md +++ b/plugins/css-blank-pseudo/docs/README.md @@ -122,6 +122,9 @@ cssBlankPseudoInit({ replaceWith: '.css-blank' }); ``` This option should be used if it was changed at PostCSS configuration level. +Please note that using a class, leverages `classList` under the hood which +might not be supported on some old browsers such as IE9, so you may need +to polyfill `classList` in those cases. [Selectors Level 4]: diff --git a/plugins/css-blank-pseudo/src/browser.js b/plugins/css-blank-pseudo/src/browser.js index e2a1bee1c..3371ad776 100644 --- a/plugins/css-blank-pseudo/src/browser.js +++ b/plugins/css-blank-pseudo/src/browser.js @@ -1,6 +1,8 @@ /* global document,window,self,MutationObserver */ import isValidReplacement from './is-valid-replacement.mjs'; +const CSS_CLASS_LOADED = 'js-blank-pseudo'; + // form control elements selector function isFormControlElement(element) { if (element.nodeName === 'INPUT' || element.nodeName === 'SELECT' || element.nodeName === 'TEXTAREA') { @@ -114,17 +116,29 @@ export default function cssBlankPseudoInit(opts) { } catch (ignoredError) { /* do nothing and continue */ } const handler = generateHandler(options.replaceWith); + const bindEvents = () => { + if (document.body) { + document.body.addEventListener( 'change', handler ); + document.body.addEventListener( 'input', handler ); + } + }; + const updateAllCandidates = () => { + Array.prototype.forEach.call( + document.querySelectorAll('input, select, textarea'), + node => { + handler({ target: node }); + }, + ); + }; if (document.body) { - document.body.addEventListener('change', handler); - document.body.addEventListener('input', handler); + bindEvents(); } else { - window.addEventListener('load', () => { - if (document.body) { - document.body.addEventListener('change', handler); - document.body.addEventListener('input', handler); - } - }); + window.addEventListener('load', bindEvents); + } + + if (document.documentElement.className.indexOf(CSS_CLASS_LOADED) === -1) { + document.documentElement.className += ` ${CSS_CLASS_LOADED}`; } observeValueOfHTMLElement(self.HTMLInputElement, handler); @@ -133,12 +147,7 @@ export default function cssBlankPseudoInit(opts) { observeSelectedOfHTMLElement(self.HTMLOptionElement, handler); // conditionally update all form control elements - Array.prototype.forEach.call( - document.querySelectorAll('input, select, textarea'), - node => { - handler({ target: node }); - }, - ); + updateAllCandidates(); if (typeof self.MutationObserver !== 'undefined') { // conditionally observe added or unobserve removed form control elements @@ -155,22 +164,9 @@ export default function cssBlankPseudoInit(opts) { }); }).observe(document, { childList: true, subtree: true }); } else { - window.addEventListener('load', () => { - Array.prototype.forEach.call( - document.querySelectorAll('input, select, textarea'), - node => { - handler({ target: node }); - }, - ); - }); - - window.addEventListener('DOMContentLoaded', () => { - Array.prototype.forEach.call( - document.querySelectorAll('input, select, textarea'), - node => { - handler({ target: node }); - }, - ); - }); + const handleOnLoad = () => updateAllCandidates(); + + window.addEventListener('load', handleOnLoad); + window.addEventListener('DOMContentLoaded', handleOnLoad); } } diff --git a/plugins/css-blank-pseudo/src/index.ts b/plugins/css-blank-pseudo/src/index.ts index d7bf4007d..0a7b19c08 100644 --- a/plugins/css-blank-pseudo/src/index.ts +++ b/plugins/css-blank-pseudo/src/index.ts @@ -4,6 +4,9 @@ import isValidReplacement from './is-valid-replacement.mjs'; type pluginOptions = { preserve?: boolean, replaceWith?: string }; +const POLYFILL_READY_CLASSNAME = 'js-blank-pseudo'; +const PSEUDO = ':blank'; + const creator: PluginCreator = (opts?: pluginOptions) => { const options = Object.assign( // Default options @@ -30,43 +33,86 @@ const creator: PluginCreator = (opts?: pluginOptions) => { return { postcssPlugin: 'css-blank-pseudo', - Rule: (rule, { result }) => { - if (rule.selector.toLowerCase().indexOf(':blank') === -1) { + Rule(rule, { result }) { + if (!rule.selector.toLowerCase().includes(PSEUDO)) { return; } - let modifiedSelector; - try { - const modifiedSelectorAST = parser((selectors) => { - selectors.walkPseudos((selector) => { - if (selector.value.toLowerCase() !== ':blank') { - return; - } + const selectors = rule.selectors.flatMap((selector) => { + if (!selector.toLowerCase().includes(PSEUDO)) { + return [selector]; + } - if (selector.nodes && selector.nodes.length) { - // `:blank` is not a function - return; - } + let selectorAST; - selector.replaceWith(replacementAST.clone({})); - }); - }).processSync(rule.selector); + try { + selectorAST = parser().astSync(selector); + } catch (_) { + rule.warn(result, `Failed to parse selector : ${selector}`); + return selector; + } - modifiedSelector = String(modifiedSelectorAST); - } catch (_) { - rule.warn(result, `Failed to parse selector : ${rule.selector}`); - return; - } + if (typeof selectorAST === 'undefined') { + return [selector]; + } - if (typeof modifiedSelector === 'undefined') { - return; - } + let containsPseudo = false; + selectorAST.walkPseudos((pseudo) => { + if (pseudo.value.toLowerCase() !== PSEUDO) { + 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-blank-pseudo > .foo:focus-within, + // .js-blank-pseudo 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; } - rule.cloneBefore({ selector: modifiedSelector }); + rule.cloneBefore({ selectors: selectors }); if (!options.preserve) { rule.remove(); diff --git a/plugins/css-blank-pseudo/test/basic.expect.css b/plugins/css-blank-pseudo/test/basic.expect.css index a3540af95..f010758e9 100644 --- a/plugins/css-blank-pseudo/test/basic.expect.css +++ b/plugins/css-blank-pseudo/test/basic.expect.css @@ -1,4 +1,4 @@ -[blank] { +[blank].js-blank-pseudo, .js-blank-pseudo [blank] { order: 1; } @@ -6,19 +6,34 @@ order: 1; } -[blank],[blank] test, -test [blank], -test test[blank], -test [blank] test, -test test[blank] test, -test [blank] [blank] test, -test :matches([blank]) test, -test :matches([blank] test) test, -test :matches(test [blank]) test, -test :matches(test test[blank]) test, -test :matches(test [blank] test) test, -test :matches(test test[blank] test) test, -test :matches(test [blank] [blank] test) test { +[blank].js-blank-pseudo, +.js-blank-pseudo [blank], +[blank].js-blank-pseudo test, +.js-blank-pseudo [blank] test, +test.js-blank-pseudo [blank], +.js-blank-pseudo test [blank], +test.js-blank-pseudo test[blank], +.js-blank-pseudo test test[blank], +test.js-blank-pseudo [blank] test, +.js-blank-pseudo test [blank] test, +test.js-blank-pseudo test[blank] test, +.js-blank-pseudo test test[blank] test, +test.js-blank-pseudo [blank] [blank] test, +.js-blank-pseudo test [blank] [blank] test, +test.js-blank-pseudo :matches([blank]) test, +.js-blank-pseudo test :matches([blank]) test, +test.js-blank-pseudo :matches([blank] test) test, +.js-blank-pseudo test :matches([blank] test) test, +test.js-blank-pseudo :matches(test [blank]) test, +.js-blank-pseudo test :matches(test [blank]) test, +test.js-blank-pseudo :matches(test test[blank]) test, +.js-blank-pseudo test :matches(test test[blank]) test, +test.js-blank-pseudo :matches(test [blank] test) test, +.js-blank-pseudo test :matches(test [blank] test) test, +test.js-blank-pseudo :matches(test test[blank] test) test, +.js-blank-pseudo test :matches(test test[blank] test) test, +test.js-blank-pseudo :matches(test [blank] [blank] test) test, +.js-blank-pseudo test :matches(test [blank] [blank] test) test { order: 2; } @@ -50,7 +65,7 @@ test :matches(test :blank :blank test) test { order: 4; } -test:not([blank]) { +test:not([blank]).js-blank-pseudo, .js-blank-pseudo test:not([blank]) { order: 5; } @@ -58,7 +73,7 @@ test:not(:blank) { order: 5; } -uppercase [blank] { +uppercase.js-blank-pseudo [blank], .js-blank-pseudo uppercase [blank] { order: 6; } diff --git a/plugins/css-blank-pseudo/test/basic.preserve.expect.css b/plugins/css-blank-pseudo/test/basic.preserve.expect.css index f7eddfe81..6492c7519 100644 --- a/plugins/css-blank-pseudo/test/basic.preserve.expect.css +++ b/plugins/css-blank-pseudo/test/basic.preserve.expect.css @@ -1,20 +1,35 @@ -[blank] { +[blank].js-blank-pseudo, .js-blank-pseudo [blank] { order: 1; } -[blank],[blank] test, -test [blank], -test test[blank], -test [blank] test, -test test[blank] test, -test [blank] [blank] test, -test :matches([blank]) test, -test :matches([blank] test) test, -test :matches(test [blank]) test, -test :matches(test test[blank]) test, -test :matches(test [blank] test) test, -test :matches(test test[blank] test) test, -test :matches(test [blank] [blank] test) test { +[blank].js-blank-pseudo, +.js-blank-pseudo [blank], +[blank].js-blank-pseudo test, +.js-blank-pseudo [blank] test, +test.js-blank-pseudo [blank], +.js-blank-pseudo test [blank], +test.js-blank-pseudo test[blank], +.js-blank-pseudo test test[blank], +test.js-blank-pseudo [blank] test, +.js-blank-pseudo test [blank] test, +test.js-blank-pseudo test[blank] test, +.js-blank-pseudo test test[blank] test, +test.js-blank-pseudo [blank] [blank] test, +.js-blank-pseudo test [blank] [blank] test, +test.js-blank-pseudo :matches([blank]) test, +.js-blank-pseudo test :matches([blank]) test, +test.js-blank-pseudo :matches([blank] test) test, +.js-blank-pseudo test :matches([blank] test) test, +test.js-blank-pseudo :matches(test [blank]) test, +.js-blank-pseudo test :matches(test [blank]) test, +test.js-blank-pseudo :matches(test test[blank]) test, +.js-blank-pseudo test :matches(test test[blank]) test, +test.js-blank-pseudo :matches(test [blank] test) test, +.js-blank-pseudo test :matches(test [blank] test) test, +test.js-blank-pseudo :matches(test test[blank] test) test, +.js-blank-pseudo test :matches(test test[blank] test) test, +test.js-blank-pseudo :matches(test [blank] [blank] test) test, +.js-blank-pseudo test :matches(test [blank] [blank] test) test { order: 2; } @@ -29,10 +44,10 @@ test :matches(test [blank] [blank] test) test { order: 4; } -test:not([blank]) { +test:not([blank]).js-blank-pseudo, .js-blank-pseudo test:not([blank]) { order: 5; } -uppercase [blank] { +uppercase.js-blank-pseudo [blank], .js-blank-pseudo uppercase [blank] { order: 6; } diff --git a/plugins/css-blank-pseudo/test/basic.replacewith.expect.css b/plugins/css-blank-pseudo/test/basic.replacewith.expect.css index 6874cfbb0..612840589 100644 --- a/plugins/css-blank-pseudo/test/basic.replacewith.expect.css +++ b/plugins/css-blank-pseudo/test/basic.replacewith.expect.css @@ -1,4 +1,4 @@ -.css-blank { +.css-blank.js-blank-pseudo, .js-blank-pseudo .css-blank { order: 1; } @@ -6,19 +6,34 @@ order: 1; } -.css-blank,.css-blank test, -test .css-blank, -test test.css-blank, -test .css-blank test, -test test.css-blank test, -test .css-blank .css-blank test, -test :matches(.css-blank) test, -test :matches(.css-blank test) test, -test :matches(test .css-blank) test, -test :matches(test test.css-blank) test, -test :matches(test .css-blank test) test, -test :matches(test test.css-blank test) test, -test :matches(test .css-blank .css-blank test) test { +.css-blank.js-blank-pseudo, +.js-blank-pseudo .css-blank, +.css-blank.js-blank-pseudo test, +.js-blank-pseudo .css-blank test, +test.js-blank-pseudo .css-blank, +.js-blank-pseudo test .css-blank, +test.js-blank-pseudo test.css-blank, +.js-blank-pseudo test test.css-blank, +test.js-blank-pseudo .css-blank test, +.js-blank-pseudo test .css-blank test, +test.js-blank-pseudo test.css-blank test, +.js-blank-pseudo test test.css-blank test, +test.js-blank-pseudo .css-blank .css-blank test, +.js-blank-pseudo test .css-blank .css-blank test, +test.js-blank-pseudo :matches(.css-blank) test, +.js-blank-pseudo test :matches(.css-blank) test, +test.js-blank-pseudo :matches(.css-blank test) test, +.js-blank-pseudo test :matches(.css-blank test) test, +test.js-blank-pseudo :matches(test .css-blank) test, +.js-blank-pseudo test :matches(test .css-blank) test, +test.js-blank-pseudo :matches(test test.css-blank) test, +.js-blank-pseudo test :matches(test test.css-blank) test, +test.js-blank-pseudo :matches(test .css-blank test) test, +.js-blank-pseudo test :matches(test .css-blank test) test, +test.js-blank-pseudo :matches(test test.css-blank test) test, +.js-blank-pseudo test :matches(test test.css-blank test) test, +test.js-blank-pseudo :matches(test .css-blank .css-blank test) test, +.js-blank-pseudo test :matches(test .css-blank .css-blank test) test { order: 2; } @@ -50,7 +65,7 @@ test :matches(test :blank :blank test) test { order: 4; } -test:not(.css-blank) { +test:not(.css-blank).js-blank-pseudo, .js-blank-pseudo test:not(.css-blank) { order: 5; } @@ -58,7 +73,7 @@ test:not(:blank) { order: 5; } -uppercase .css-blank { +uppercase.js-blank-pseudo .css-blank, .js-blank-pseudo uppercase .css-blank { order: 6; } diff --git a/plugins/css-blank-pseudo/test/browser.expect.css b/plugins/css-blank-pseudo/test/browser.expect.css index ade83fb55..5ec76bce7 100644 --- a/plugins/css-blank-pseudo/test/browser.expect.css +++ b/plugins/css-blank-pseudo/test/browser.expect.css @@ -4,7 +4,7 @@ textarea { background-color: rgb(255, 192, 203); } -[blank] { +[blank].js-blank-pseudo, .js-blank-pseudo [blank] { background-color: rgb(128, 0, 128); } diff --git a/plugins/css-blank-pseudo/test/browser.replacewith.expect.css b/plugins/css-blank-pseudo/test/browser.replacewith.expect.css index 9ea7c84de..47623b0b7 100644 --- a/plugins/css-blank-pseudo/test/browser.replacewith.expect.css +++ b/plugins/css-blank-pseudo/test/browser.replacewith.expect.css @@ -4,7 +4,7 @@ textarea { background-color: rgb(255, 192, 203); } -.css-blank { +.css-blank.js-blank-pseudo, .js-blank-pseudo .css-blank { background-color: rgb(128, 0, 128); } diff --git a/plugins/css-blank-pseudo/test/examples/example.expect.css b/plugins/css-blank-pseudo/test/examples/example.expect.css index df6c00a20..16b2b4d03 100644 --- a/plugins/css-blank-pseudo/test/examples/example.expect.css +++ b/plugins/css-blank-pseudo/test/examples/example.expect.css @@ -1,4 +1,4 @@ -input[blank] { +input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] { background-color: yellow; } input:blank { diff --git a/plugins/css-blank-pseudo/test/examples/example.preserve-false.expect.css b/plugins/css-blank-pseudo/test/examples/example.preserve-false.expect.css index a3a7b9d30..00e3c924d 100644 --- a/plugins/css-blank-pseudo/test/examples/example.preserve-false.expect.css +++ b/plugins/css-blank-pseudo/test/examples/example.preserve-false.expect.css @@ -1,3 +1,3 @@ -input[blank] { +input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] { background-color: yellow; } diff --git a/plugins/css-blank-pseudo/test/examples/example.replacewith.expect.css b/plugins/css-blank-pseudo/test/examples/example.replacewith.expect.css index 24f2fc6d1..e37419756 100644 --- a/plugins/css-blank-pseudo/test/examples/example.replacewith.expect.css +++ b/plugins/css-blank-pseudo/test/examples/example.replacewith.expect.css @@ -1,4 +1,4 @@ -input.css-blank { +input.css-blank.js-blank-pseudo, .js-blank-pseudo input.css-blank { background-color: yellow; } input:blank { diff --git a/plugins/postcss-focus-within/README.md b/plugins/postcss-focus-within/README.md index a38a13ed6..bea315da3 100644 --- a/plugins/postcss-focus-within/README.md +++ b/plugins/postcss-focus-within/README.md @@ -78,6 +78,9 @@ postcssFocusWithin({ preserve: false }) The `replaceWith` option defines the selector to replace `:focus-within`. By default, the replacement selector is `[focus-within]`. +Please note that using a class, leverages `classList` under the hood which +might not be supported on some old browsers such as IE9, so you may need +to polyfill `classList` in those cases. ```js postcssFocusWithin({ replaceWith: '.focus-within' }); diff --git a/plugins/postcss-focus-within/docs/README.md b/plugins/postcss-focus-within/docs/README.md index cd8d22648..f2d551b91 100644 --- a/plugins/postcss-focus-within/docs/README.md +++ b/plugins/postcss-focus-within/docs/README.md @@ -60,6 +60,9 @@ is preserved. By default, it is preserved. The `replaceWith` option defines the selector to replace `:focus-within`. By default, the replacement selector is `[focus-within]`. +Please note that using a class, leverages `classList` under the hood which +might not be supported on some old browsers such as IE9, so you may need +to polyfill `classList` in those cases. ```js ({ replaceWith: '.focus-within' });