Skip to content

Commit 65cd703

Browse files
authored
postcss-pseudo-class-any-link: ignore :not() pseudos (#1373)
1 parent 0056d36 commit 65cd703

11 files changed

+32
-4
lines changed

plugins/postcss-pseudo-class-any-link/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes to PostCSS Pseudo Class Any Link
22

3+
### Unreleased (patch)
4+
5+
- Ignore `:any-link` in `:not()` pseudo class functions
6+
37
### 9.0.1
48

59
_December 15, 2023_
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"use strict";var e=require("postcss-selector-parser");const t=e().astSync(":link").nodes[0],s=e().astSync(":visited").nodes[0],n=e().astSync("area[href]").nodes[0],o=e().astSync("[href]").nodes[0];function replaceAnyLink(e,t,s,n){const o=[],r=[];try{for(let t=0;t<e.selectors.length;t++){const s=e.selectors[t],l=modifiedSelector(s,n);l.length?o.push(...l):r.push(s)}}catch(s){return e.warn(t,`Failed to parse selector : "${e.selector}" with message: "${s instanceof Error?s.message:s}"`),!1}return!!o.length&&(e.cloneBefore({selectors:o}),r.length&&e.cloneBefore({selectors:r}),s||e.remove(),!0)}function modifiedSelector(r,l){const c=[];return e((e=>{const r=[];if(e.walkPseudos((e=>{if(":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length)return;if(!l)return void r.push([t.clone(),s.clone()]);const c=getTagElementsNextToPseudo(e);c.includes("area")?r.push([t.clone(),s.clone(),o.clone()]):c.length?r.push([t.clone(),s.clone()]):r.push([t.clone(),s.clone(),n.clone()])})),!r.length)return;cartesianProduct(...r).forEach((t=>{const s=e.clone();s.walkPseudos((e=>{":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length||(insertNode(e.parent,e,t.shift()),e.remove())})),c.push(s.toString())}))})).processSync(r),c}function cartesianProduct(...e){const t=[],s=e.length-1;return function helper(n,o){for(let r=0,l=e[o].length;r<l;r++){const l=n.slice(0);l.push(e[o][r]),o==s?t.push(l):helper(l,o+1)}}([],0),t}function getTagElementsNextToPseudo(t){const s=[];let n=t.prev();for(;n&&"combinator"!==n.type&&!e.isPseudoElement(n);)"tag"===n.type&&s.push(n.value.toLowerCase()),n=n.prev();let o=t.next();for(;o&&"combinator"!==o.type&&!e.isPseudoElement(o);)"tag"===o.type&&s.push(o.value.toLowerCase()),o=o.next();return s}function insertNode(t,s,n){if(!t||!n)return;let o=n.type;"selector"===n.type&&n.nodes&&n.nodes.length&&(o=n.nodes[0].type);let r=-1,l=-1;const c=t.index(s);for(let s=c;s>=0&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s--)r=s;if("tag"!==o){for(let s=c;s<t.nodes.length&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s++)l=s;for(let e=r;e<=l;e++)if(t.nodes[e].type===o)return void t.insertAfter(t.at(e),n);t.insertAfter(t.at(r),n)}else t.insertBefore(t.at(r),n)}const creator=e=>{const t={preserve:!0,...e},s={areaHrefNeedsFixing:!1,...Object(t.subFeatures)};return{postcssPlugin:"postcss-pseudo-class-any-link",prepare(){const e=new WeakSet;return{postcssPlugin:"postcss-pseudo-class-any-link",Rule(n,{result:o}){if(!n.selector.toLowerCase().includes(":any-link"))return;if(e.has(n))return;if((n.raws.selector&&n.raws.selector.raw||n.selector).endsWith(":"))return;replaceAnyLink(n,o,t.preserve,s.areaHrefNeedsFixing)&&e.add(n)}}}}};creator.postcss=!0,module.exports=creator;
1+
"use strict";var e=require("postcss-selector-parser");const t=e().astSync(":link").nodes[0],s=e().astSync(":visited").nodes[0],n=e().astSync("area[href]").nodes[0],o=e().astSync("[href]").nodes[0];function replaceAnyLink(e,t,s,n){const o=[],r=[];try{for(let t=0;t<e.selectors.length;t++){const s=e.selectors[t],l=modifiedSelector(s,n);l.length?o.push(...l):r.push(s)}}catch(s){return e.warn(t,`Failed to parse selector : "${e.selector}" with message: "${s instanceof Error?s.message:s}"`),!1}return!!o.length&&(e.cloneBefore({selectors:o}),r.length&&e.cloneBefore({selectors:r}),s||e.remove(),!0)}function modifiedSelector(r,l){const c=[];return e((e=>{const r=[];if(e.walkPseudos((e=>{if(":not"===e.value.toLowerCase())return!1;if(":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length)return;if(!l)return void r.push([t.clone(),s.clone()]);const c=getTagElementsNextToPseudo(e);c.includes("area")?r.push([t.clone(),s.clone(),o.clone()]):c.length?r.push([t.clone(),s.clone()]):r.push([t.clone(),s.clone(),n.clone()])})),!r.length)return;cartesianProduct(...r).forEach((t=>{const s=e.clone();s.walkPseudos((e=>{":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length||(insertNode(e.parent,e,t.shift()),e.remove())})),c.push(s.toString())}))})).processSync(r),c}function cartesianProduct(...e){const t=[],s=e.length-1;return function helper(n,o){for(let r=0,l=e[o].length;r<l;r++){const l=n.slice(0);l.push(e[o][r]),o==s?t.push(l):helper(l,o+1)}}([],0),t}function getTagElementsNextToPseudo(t){const s=[];let n=t.prev();for(;n&&"combinator"!==n.type&&!e.isPseudoElement(n);)"tag"===n.type&&s.push(n.value.toLowerCase()),n=n.prev();let o=t.next();for(;o&&"combinator"!==o.type&&!e.isPseudoElement(o);)"tag"===o.type&&s.push(o.value.toLowerCase()),o=o.next();return s}function insertNode(t,s,n){if(!t||!n)return;let o=n.type;"selector"===n.type&&n.nodes&&n.nodes.length&&(o=n.nodes[0].type);let r=-1,l=-1;const c=t.index(s);for(let s=c;s>=0&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s--)r=s;if("tag"!==o){for(let s=c;s<t.nodes.length&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s++)l=s;for(let e=r;e<=l;e++)if(t.nodes[e].type===o)return void t.insertAfter(t.at(e),n);t.insertAfter(t.at(r),n)}else t.insertBefore(t.at(r),n)}const creator=e=>{const t={preserve:!0,...e},s={areaHrefNeedsFixing:!1,...Object(t.subFeatures)};return{postcssPlugin:"postcss-pseudo-class-any-link",prepare(){const e=new WeakSet;return{postcssPlugin:"postcss-pseudo-class-any-link",Rule(n,{result:o}){if(!n.selector.toLowerCase().includes(":any-link"))return;if(e.has(n))return;if((n.raws.selector&&n.raws.selector.raw||n.selector).endsWith(":"))return;replaceAnyLink(n,o,t.preserve,s.areaHrefNeedsFixing)&&e.add(n)}}}}};creator.postcss=!0,module.exports=creator;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import e from"postcss-selector-parser";const t=e().astSync(":link").nodes[0],s=e().astSync(":visited").nodes[0],n=e().astSync("area[href]").nodes[0],o=e().astSync("[href]").nodes[0];function replaceAnyLink(e,t,s,n){const o=[],r=[];try{for(let t=0;t<e.selectors.length;t++){const s=e.selectors[t],l=modifiedSelector(s,n);l.length?o.push(...l):r.push(s)}}catch(s){return e.warn(t,`Failed to parse selector : "${e.selector}" with message: "${s instanceof Error?s.message:s}"`),!1}return!!o.length&&(e.cloneBefore({selectors:o}),r.length&&e.cloneBefore({selectors:r}),s||e.remove(),!0)}function modifiedSelector(r,l){const c=[];return e((e=>{const r=[];if(e.walkPseudos((e=>{if(":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length)return;if(!l)return void r.push([t.clone(),s.clone()]);const c=getTagElementsNextToPseudo(e);c.includes("area")?r.push([t.clone(),s.clone(),o.clone()]):c.length?r.push([t.clone(),s.clone()]):r.push([t.clone(),s.clone(),n.clone()])})),!r.length)return;cartesianProduct(...r).forEach((t=>{const s=e.clone();s.walkPseudos((e=>{":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length||(insertNode(e.parent,e,t.shift()),e.remove())})),c.push(s.toString())}))})).processSync(r),c}function cartesianProduct(...e){const t=[],s=e.length-1;return function helper(n,o){for(let r=0,l=e[o].length;r<l;r++){const l=n.slice(0);l.push(e[o][r]),o==s?t.push(l):helper(l,o+1)}}([],0),t}function getTagElementsNextToPseudo(t){const s=[];let n=t.prev();for(;n&&"combinator"!==n.type&&!e.isPseudoElement(n);)"tag"===n.type&&s.push(n.value.toLowerCase()),n=n.prev();let o=t.next();for(;o&&"combinator"!==o.type&&!e.isPseudoElement(o);)"tag"===o.type&&s.push(o.value.toLowerCase()),o=o.next();return s}function insertNode(t,s,n){if(!t||!n)return;let o=n.type;"selector"===n.type&&n.nodes&&n.nodes.length&&(o=n.nodes[0].type);let r=-1,l=-1;const c=t.index(s);for(let s=c;s>=0&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s--)r=s;if("tag"!==o){for(let s=c;s<t.nodes.length&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s++)l=s;for(let e=r;e<=l;e++)if(t.nodes[e].type===o)return void t.insertAfter(t.at(e),n);t.insertAfter(t.at(r),n)}else t.insertBefore(t.at(r),n)}const creator=e=>{const t={preserve:!0,...e},s={areaHrefNeedsFixing:!1,...Object(t.subFeatures)};return{postcssPlugin:"postcss-pseudo-class-any-link",prepare(){const e=new WeakSet;return{postcssPlugin:"postcss-pseudo-class-any-link",Rule(n,{result:o}){if(!n.selector.toLowerCase().includes(":any-link"))return;if(e.has(n))return;if((n.raws.selector&&n.raws.selector.raw||n.selector).endsWith(":"))return;replaceAnyLink(n,o,t.preserve,s.areaHrefNeedsFixing)&&e.add(n)}}}}};creator.postcss=!0;export{creator as default};
1+
import e from"postcss-selector-parser";const t=e().astSync(":link").nodes[0],s=e().astSync(":visited").nodes[0],n=e().astSync("area[href]").nodes[0],o=e().astSync("[href]").nodes[0];function replaceAnyLink(e,t,s,n){const o=[],r=[];try{for(let t=0;t<e.selectors.length;t++){const s=e.selectors[t],l=modifiedSelector(s,n);l.length?o.push(...l):r.push(s)}}catch(s){return e.warn(t,`Failed to parse selector : "${e.selector}" with message: "${s instanceof Error?s.message:s}"`),!1}return!!o.length&&(e.cloneBefore({selectors:o}),r.length&&e.cloneBefore({selectors:r}),s||e.remove(),!0)}function modifiedSelector(r,l){const c=[];return e((e=>{const r=[];if(e.walkPseudos((e=>{if(":not"===e.value.toLowerCase())return!1;if(":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length)return;if(!l)return void r.push([t.clone(),s.clone()]);const c=getTagElementsNextToPseudo(e);c.includes("area")?r.push([t.clone(),s.clone(),o.clone()]):c.length?r.push([t.clone(),s.clone()]):r.push([t.clone(),s.clone(),n.clone()])})),!r.length)return;cartesianProduct(...r).forEach((t=>{const s=e.clone();s.walkPseudos((e=>{":any-link"!==e.value.toLowerCase()||e.nodes&&e.nodes.length||(insertNode(e.parent,e,t.shift()),e.remove())})),c.push(s.toString())}))})).processSync(r),c}function cartesianProduct(...e){const t=[],s=e.length-1;return function helper(n,o){for(let r=0,l=e[o].length;r<l;r++){const l=n.slice(0);l.push(e[o][r]),o==s?t.push(l):helper(l,o+1)}}([],0),t}function getTagElementsNextToPseudo(t){const s=[];let n=t.prev();for(;n&&"combinator"!==n.type&&!e.isPseudoElement(n);)"tag"===n.type&&s.push(n.value.toLowerCase()),n=n.prev();let o=t.next();for(;o&&"combinator"!==o.type&&!e.isPseudoElement(o);)"tag"===o.type&&s.push(o.value.toLowerCase()),o=o.next();return s}function insertNode(t,s,n){if(!t||!n)return;let o=n.type;"selector"===n.type&&n.nodes&&n.nodes.length&&(o=n.nodes[0].type);let r=-1,l=-1;const c=t.index(s);for(let s=c;s>=0&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s--)r=s;if("tag"!==o){for(let s=c;s<t.nodes.length&&("combinator"!==t.nodes[s].type&&!e.isPseudoElement(t.nodes[s].type));s++)l=s;for(let e=r;e<=l;e++)if(t.nodes[e].type===o)return void t.insertAfter(t.at(e),n);t.insertAfter(t.at(r),n)}else t.insertBefore(t.at(r),n)}const creator=e=>{const t={preserve:!0,...e},s={areaHrefNeedsFixing:!1,...Object(t.subFeatures)};return{postcssPlugin:"postcss-pseudo-class-any-link",prepare(){const e=new WeakSet;return{postcssPlugin:"postcss-pseudo-class-any-link",Rule(n,{result:o}){if(!n.selector.toLowerCase().includes(":any-link"))return;if(e.has(n))return;if((n.raws.selector&&n.raws.selector.raw||n.selector).endsWith(":"))return;replaceAnyLink(n,o,t.preserve,s.areaHrefNeedsFixing)&&e.add(n)}}}}};creator.postcss=!0;export{creator as default};

plugins/postcss-pseudo-class-any-link/src/replace-any-link.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ function modifiedSelector(selector: string, areaHrefNeedsFixing: boolean): Array
5454
parser((selectorsAST) => {
5555
const replacements: Array<Array<parser.Selector>> = [];
5656
selectorsAST.walkPseudos((pseudo) => {
57+
if (pseudo.value.toLowerCase() === ':not') {
58+
return false;
59+
}
60+
5761
if (pseudo.value.toLowerCase() !== ':any-link' || (pseudo.nodes && pseudo.nodes.length)) {
5862
return;
5963
}

plugins/postcss-pseudo-class-any-link/test/basic.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,7 @@ b {
117117
:any-link {
118118
to-clone: 1;
119119
}
120+
121+
:not(:any-link) {
122+
order: 110;
123+
}

plugins/postcss-pseudo-class-any-link/test/basic.expect.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,7 @@ b {
243243
:any-link {
244244
to-clone: 1;
245245
}
246+
247+
:not(:any-link) {
248+
order: 110;
249+
}

plugins/postcss-pseudo-class-any-link/test/basic.preserve-false.expect.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,7 @@ b {
127127
:link, :visited {
128128
to-clone: 1;
129129
}
130+
131+
:not(:any-link) {
132+
order: 110;
133+
}

plugins/postcss-pseudo-class-any-link/test/basic.sub-features-area-href.expect.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,7 @@ b {
248248
:any-link {
249249
to-clone: 1;
250250
}
251+
252+
:not(:any-link) {
253+
order: 110;
254+
}

plugins/postcss-pseudo-class-any-link/test/basic.with-cloned-declarations.expect.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,7 @@ b {
250250
cloned: 1;
251251
to-clone: 1;
252252
}
253+
254+
:not(:any-link) {
255+
order: 110;
256+
}

plugins/postcss-pseudo-class-any-link/test/generated-selector-cases.expect.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ foo[baz=":any-link"] {
966966
order: 221;
967967
}
968968

969-
:not(:link), :not(:visited) {
969+
:not(:any-link) {
970970
order: 222;
971971
}
972972

plugins/postcss-pseudo-class-any-link/test/generated-selector-cases.sub-features-area-href.expect.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ foo[baz=":any-link"] {
966966
order: 221;
967967
}
968968

969-
:not(:link), :not(:visited), :not(area[href]) {
969+
:not(:any-link) {
970970
order: 222;
971971
}
972972

0 commit comments

Comments
 (0)