Skip to content

Commit

Permalink
selector-specificity : fix unwanted mutation (#1395)
Browse files Browse the repository at this point in the history
  • Loading branch information
romainmenke committed May 13, 2024
1 parent 65c1f5f commit 7a58984
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 28 deletions.
4 changes: 4 additions & 0 deletions packages/selector-specificity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changes to Selector Specificity

### Unreleased (patch)

- Prevent mutation of selectors with An+B microsyntax (e.g. `:nth-child(2n+1 of .foo)`) during specificity calculation

### 3.1.0

_May 11, 2024_
Expand Down
2 changes: 1 addition & 1 deletion packages/selector-specificity/dist/index.cjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"use strict";var e=require("postcss-selector-parser");function selectorSpecificity(t,s){const i=s?.customSpecificity?.(t);if(i)return i;if(!t)return{a:0,b:0,c:0};let c=0,n=0,o=0;if("universal"==t.type)return{a:0,b:0,c:0};if("id"===t.type)c+=1;else if("tag"===t.type)o+=1;else if("class"===t.type)n+=1;else if("attribute"===t.type)n+=1;else if(isPseudoElement(t))switch(t.value.toLowerCase()){case"::slotted":if(o+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case"::view-transition-group":case"::view-transition-image-pair":case"::view-transition-old":case"::view-transition-new":return t.nodes&&1===t.nodes.length&&"selector"===t.nodes[0].type&&selectorNodeContainsNothingOrOnlyUniversal(t.nodes[0])?{a:0,b:0,c:0}:{a:0,b:0,c:1};default:o+=1}else if(e.isPseudoClass(t))switch(t.value.toLowerCase()){case":-webkit-any":case":any":default:n+=1;break;case":-moz-any":case":has":case":is":case":matches":case":not":if(t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":where":break;case":nth-child":case":nth-last-child":if(n+=1,t.nodes&&t.nodes.length>0){const i=t.nodes[0].nodes.findIndex((e=>"tag"===e.type&&"of"===e.value.toLowerCase()));if(i>-1){const a=e.selector({nodes:[],value:""});a.parent=t;t.nodes[0].nodes.slice(i+1).forEach((e=>{e.remove(),a.append(e)}));const r=[a];t.nodes.length>1&&r.push(...t.nodes.slice(1));const f=specificityOfMostSpecificListItem(r,s);c+=f.a,n+=f.b,o+=f.c}}break;case":local":case":global":t.nodes&&t.nodes.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));break;case":host":case":host-context":if(n+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":active-view-transition":case":active-view-transition-type":return{a:0,b:1,c:0}}else e.isContainer(t)&&t.nodes.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));return{a:c,b:n,c:o}}function specificityOfMostSpecificListItem(e,t){let s={a:0,b:0,c:0};return e.forEach((e=>{const i=selectorSpecificity(e,t);i.a>s.a?s=i:i.a<s.a||(i.b>s.b?s=i:i.b<s.b||i.c>s.c&&(s=i))})),s}function isPseudoElement(t){return e.isPseudoElement(t)}function selectorNodeContainsNothingOrOnlyUniversal(e){if(!e)return!1;if(!e.nodes)return!1;const t=e.nodes.filter((e=>"comment"!==e.type));return 0===t.length||1===t.length&&"universal"===t[0].type}exports.compare=function compare(e,t){return e.a===t.a?e.b===t.b?e.c-t.c:e.b-t.b:e.a-t.a},exports.selectorSpecificity=selectorSpecificity,exports.specificityOfMostSpecificListItem=specificityOfMostSpecificListItem;
"use strict";var e=require("postcss-selector-parser");function compare(e,t){return e.a===t.a?e.b===t.b?e.c-t.c:e.b-t.b:e.a-t.a}function selectorSpecificity(t,s){const i=s?.customSpecificity?.(t);if(i)return i;if(!t)return{a:0,b:0,c:0};let c=0,n=0,o=0;if("universal"==t.type)return{a:0,b:0,c:0};if("id"===t.type)c+=1;else if("tag"===t.type)o+=1;else if("class"===t.type)n+=1;else if("attribute"===t.type)n+=1;else if(isPseudoElement(t))switch(t.value.toLowerCase()){case"::slotted":if(o+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case"::view-transition-group":case"::view-transition-image-pair":case"::view-transition-old":case"::view-transition-new":return t.nodes&&1===t.nodes.length&&"selector"===t.nodes[0].type&&selectorNodeContainsNothingOrOnlyUniversal(t.nodes[0])?{a:0,b:0,c:0}:{a:0,b:0,c:1};default:o+=1}else if(e.isPseudoClass(t))switch(t.value.toLowerCase()){case":-webkit-any":case":any":default:n+=1;break;case":-moz-any":case":has":case":is":case":matches":case":not":if(t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":where":break;case":nth-child":case":nth-last-child":if(n+=1,t.nodes&&t.nodes.length>0){const i=t.nodes[0].nodes.findIndex((e=>"tag"===e.type&&"of"===e.value.toLowerCase()));if(i>-1){const a=e.selector({nodes:[],value:""});t.nodes[0].nodes.slice(i+1).forEach((e=>{a.append(e.clone())}));const r=[a];t.nodes.length>1&&r.push(...t.nodes.slice(1));const l=specificityOfMostSpecificListItem(r,s);c+=l.a,n+=l.b,o+=l.c}}break;case":local":case":global":t.nodes&&t.nodes.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));break;case":host":case":host-context":if(n+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":active-view-transition":case":active-view-transition-type":return{a:0,b:1,c:0}}else e.isContainer(t)&&t.nodes?.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));return{a:c,b:n,c:o}}function specificityOfMostSpecificListItem(e,t){let s={a:0,b:0,c:0};return e.forEach((e=>{const i=selectorSpecificity(e,t);compare(i,s)<0||(s=i)})),s}function isPseudoElement(t){return e.isPseudoElement(t)}function selectorNodeContainsNothingOrOnlyUniversal(e){if(!e)return!1;if(!e.nodes)return!1;const t=e.nodes.filter((e=>"comment"!==e.type));return 0===t.length||1===t.length&&"universal"===t[0].type}exports.compare=compare,exports.selectorSpecificity=selectorSpecificity,exports.specificityOfMostSpecificListItem=specificityOfMostSpecificListItem;
2 changes: 1 addition & 1 deletion packages/selector-specificity/dist/index.mjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import e from"postcss-selector-parser";function compare(e,t){return e.a===t.a?e.b===t.b?e.c-t.c:e.b-t.b:e.a-t.a}function selectorSpecificity(t,s){const i=s?.customSpecificity?.(t);if(i)return i;if(!t)return{a:0,b:0,c:0};let c=0,n=0,o=0;if("universal"==t.type)return{a:0,b:0,c:0};if("id"===t.type)c+=1;else if("tag"===t.type)o+=1;else if("class"===t.type)n+=1;else if("attribute"===t.type)n+=1;else if(isPseudoElement(t))switch(t.value.toLowerCase()){case"::slotted":if(o+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case"::view-transition-group":case"::view-transition-image-pair":case"::view-transition-old":case"::view-transition-new":return t.nodes&&1===t.nodes.length&&"selector"===t.nodes[0].type&&selectorNodeContainsNothingOrOnlyUniversal(t.nodes[0])?{a:0,b:0,c:0}:{a:0,b:0,c:1};default:o+=1}else if(e.isPseudoClass(t))switch(t.value.toLowerCase()){case":-webkit-any":case":any":default:n+=1;break;case":-moz-any":case":has":case":is":case":matches":case":not":if(t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":where":break;case":nth-child":case":nth-last-child":if(n+=1,t.nodes&&t.nodes.length>0){const i=t.nodes[0].nodes.findIndex((e=>"tag"===e.type&&"of"===e.value.toLowerCase()));if(i>-1){const a=e.selector({nodes:[],value:""});a.parent=t;t.nodes[0].nodes.slice(i+1).forEach((e=>{e.remove(),a.append(e)}));const r=[a];t.nodes.length>1&&r.push(...t.nodes.slice(1));const l=specificityOfMostSpecificListItem(r,s);c+=l.a,n+=l.b,o+=l.c}}break;case":local":case":global":t.nodes&&t.nodes.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));break;case":host":case":host-context":if(n+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":active-view-transition":case":active-view-transition-type":return{a:0,b:1,c:0}}else e.isContainer(t)&&t.nodes.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));return{a:c,b:n,c:o}}function specificityOfMostSpecificListItem(e,t){let s={a:0,b:0,c:0};return e.forEach((e=>{const i=selectorSpecificity(e,t);i.a>s.a?s=i:i.a<s.a||(i.b>s.b?s=i:i.b<s.b||i.c>s.c&&(s=i))})),s}function isPseudoElement(t){return e.isPseudoElement(t)}function selectorNodeContainsNothingOrOnlyUniversal(e){if(!e)return!1;if(!e.nodes)return!1;const t=e.nodes.filter((e=>"comment"!==e.type));return 0===t.length||1===t.length&&"universal"===t[0].type}export{compare,selectorSpecificity,specificityOfMostSpecificListItem};
import e from"postcss-selector-parser";function compare(e,t){return e.a===t.a?e.b===t.b?e.c-t.c:e.b-t.b:e.a-t.a}function selectorSpecificity(t,s){const i=s?.customSpecificity?.(t);if(i)return i;if(!t)return{a:0,b:0,c:0};let c=0,n=0,o=0;if("universal"==t.type)return{a:0,b:0,c:0};if("id"===t.type)c+=1;else if("tag"===t.type)o+=1;else if("class"===t.type)n+=1;else if("attribute"===t.type)n+=1;else if(isPseudoElement(t))switch(t.value.toLowerCase()){case"::slotted":if(o+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case"::view-transition-group":case"::view-transition-image-pair":case"::view-transition-old":case"::view-transition-new":return t.nodes&&1===t.nodes.length&&"selector"===t.nodes[0].type&&selectorNodeContainsNothingOrOnlyUniversal(t.nodes[0])?{a:0,b:0,c:0}:{a:0,b:0,c:1};default:o+=1}else if(e.isPseudoClass(t))switch(t.value.toLowerCase()){case":-webkit-any":case":any":default:n+=1;break;case":-moz-any":case":has":case":is":case":matches":case":not":if(t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":where":break;case":nth-child":case":nth-last-child":if(n+=1,t.nodes&&t.nodes.length>0){const i=t.nodes[0].nodes.findIndex((e=>"tag"===e.type&&"of"===e.value.toLowerCase()));if(i>-1){const a=e.selector({nodes:[],value:""});t.nodes[0].nodes.slice(i+1).forEach((e=>{a.append(e.clone())}));const r=[a];t.nodes.length>1&&r.push(...t.nodes.slice(1));const l=specificityOfMostSpecificListItem(r,s);c+=l.a,n+=l.b,o+=l.c}}break;case":local":case":global":t.nodes&&t.nodes.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));break;case":host":case":host-context":if(n+=1,t.nodes&&t.nodes.length>0){const e=specificityOfMostSpecificListItem(t.nodes,s);c+=e.a,n+=e.b,o+=e.c}break;case":active-view-transition":case":active-view-transition-type":return{a:0,b:1,c:0}}else e.isContainer(t)&&t.nodes?.length>0&&t.nodes.forEach((e=>{const t=selectorSpecificity(e,s);c+=t.a,n+=t.b,o+=t.c}));return{a:c,b:n,c:o}}function specificityOfMostSpecificListItem(e,t){let s={a:0,b:0,c:0};return e.forEach((e=>{const i=selectorSpecificity(e,t);compare(i,s)<0||(s=i)})),s}function isPseudoElement(t){return e.isPseudoElement(t)}function selectorNodeContainsNothingOrOnlyUniversal(e){if(!e)return!1;if(!e.nodes)return!1;const t=e.nodes.filter((e=>"comment"!==e.type));return 0===t.length||1===t.length&&"universal"===t[0].type}export{compare,selectorSpecificity,specificityOfMostSpecificListItem};
28 changes: 5 additions & 23 deletions packages/selector-specificity/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,11 @@ export function selectorSpecificity(node: Node, options?: CalculationOptions): S
value: '',
});

selector.parent = node;

const firstPart = node.nodes[0].nodes.slice(ofSeparatorIndex + 1);
firstPart.forEach((child) => {
child.remove();
selector.append(child);
node.nodes[0].nodes.slice(ofSeparatorIndex + 1).forEach((child) => {
selector.append(child.clone());
});

const selectorList = [selector];

if (node.nodes.length > 1) {
selectorList.push(...node.nodes.slice(1));
}
Expand Down Expand Up @@ -273,7 +268,7 @@ export function selectorSpecificity(node: Node, options?: CalculationOptions): S
default:
b += 1;
}
} else if ((parser.isContainer(node)) && node.nodes.length > 0) {
} else if ((parser.isContainer(node)) && node.nodes?.length > 0) {
node.nodes.forEach((child) => {
const specificity = selectorSpecificity(child, options);
a += specificity.a;
Expand Down Expand Up @@ -301,24 +296,11 @@ export function specificityOfMostSpecificListItem(nodes: Array<Node>, options?:

nodes.forEach((child) => {
const itemSpecificity = selectorSpecificity(child, options);
if (itemSpecificity.a > mostSpecificListItem.a) {
mostSpecificListItem = itemSpecificity;
return;
} else if (itemSpecificity.a < mostSpecificListItem.a) {
if (compare(itemSpecificity, mostSpecificListItem) < 0) {
return;
}

if (itemSpecificity.b > mostSpecificListItem.b) {
mostSpecificListItem = itemSpecificity;
return;
} else if (itemSpecificity.b < mostSpecificListItem.b) {
return;
}

if (itemSpecificity.c > mostSpecificListItem.c) {
mostSpecificListItem = itemSpecificity;
return;
}
mostSpecificListItem = itemSpecificity;
});

return mostSpecificListItem;
Expand Down

0 comments on commit 7a58984

Please sign in to comment.