Skip to content

Commit 8c0dac2

Browse files
authored
improve support for open-props (#1050)
1 parent 5c3fdbd commit 8c0dac2

36 files changed

+437
-93
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const yourConfig = {
3838
- [Stylelint plugins](https://github.com/csstools/postcss-plugins/tree/main/plugins-stylelint)
3939
- [cli's](https://github.com/csstools/postcss-plugins/tree/main/cli)
4040
- [sites](https://github.com/csstools/postcss-plugins/tree/main/sites)
41+
- [PostCSS recipes](https://github.com/csstools/postcss-plugins/tree/main/postcss-recipes)
4142

4243
## Our current focus
4344

package-lock.json

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import type { Node, Root } from 'postcss';
22
export declare function collectCascadeLayerOrder(root: Root): WeakMap<Node, number>;
3-
export declare function cascadeLayerNumberForNode(node: Node, layers: WeakMap<Node, number>): number | undefined;
3+
export declare function cascadeLayerNumberForNode(node: Node, layers: WeakMap<Node, number>): number;

plugins/postcss-custom-media/dist/index.cjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

plugins/postcss-custom-media/dist/index.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

plugins/postcss-custom-media/src/cascade-layers.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,19 @@ export function collectCascadeLayerOrder(root: Root) {
103103
return out;
104104
}
105105

106-
// -1 : node was not found
106+
// 0 : node was not found
107107
// any number : node was found, higher numbers have higher priority
108-
// Infinity : node wasn't layered, highest priority
109-
export function cascadeLayerNumberForNode(node: Node, layers: WeakMap<Node, number>) {
108+
// a very large number : node wasn't layered, highest priority
109+
export function cascadeLayerNumberForNode(node: Node, layers: WeakMap<Node, number>): number {
110110
if (node.parent && node.parent.type === 'atrule' && (node.parent as AtRule).name.toLowerCase() === 'layer') {
111111
if (!layers.has(node.parent)) {
112-
return -1;
112+
return 0;
113113
}
114114

115-
return layers.get(node.parent);
115+
return layers.get(node.parent)! + 1;
116116
}
117117

118-
return Infinity;
118+
return 10_000_000;
119119
}
120120

121121
function normalizeLayerName(layerName: string, counter: number) {

plugins/postcss-custom-properties/.tape.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ postcssTape(plugin)({
2424
preserve: false
2525
}
2626
},
27+
'specificity': {
28+
message: 'supports different specificities of html and :root selectors'
29+
},
2730
'examples/example': {
2831
message: 'minimal example',
2932
},

plugins/postcss-custom-properties/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changes to PostCSS Custom Properties
22

3+
### Unreleased (minor)
4+
5+
- Added: support for `:where(html)` and `:where(:root)` selectors
6+
- Fixed: cascade layers support
7+
38
### 13.2.1
49

510
_July 3, 2023_
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import type { Node, Root } from 'postcss';
22
export declare function collectCascadeLayerOrder(root: Root): WeakMap<Node, number>;
3-
export declare function cascadeLayerNumberForNode(node: Node, layers: WeakMap<Node, number>): number | undefined;
3+
export declare function cascadeLayerNumberForNode(node: Node, layers: WeakMap<Node, number>): number;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"use strict";var e=require("postcss-value-parser"),r=require("@csstools/cascade-layer-name-parser");const t=r.parse("csstools-implicit-layer")[0];function collectCascadeLayerOrder(e){const n=new Map,o=new Map,s=[];e.walkAtRules((e=>{var a;if("layer"!==e.name.toLowerCase())return;{let r=e.parent;for(;r;){if("atrule"!==r.type||"layer"!==r.name.toLowerCase()){if(r===e.root())break;return}r=r.parent}}let l;if(e.nodes)l=normalizeLayerName(e.params,1);else{if(!e.params.trim())return;l=e.params}let i=r.parse(l);if(null!=(a=i)&&a.length){{let r=e.parent;for(;r&&"atrule"===r.type&&"layer"===r.name.toLowerCase();){const e=o.get(r);e?(i=i.map((r=>e.concat(r))),r=r.parent):r=r.parent}}if(r.addLayerToModel(s,i),e.nodes){const r=i[0].concat(t);n.set(e,r),o.set(e,i[0])}}}));for(const e of n.values())r.addLayerToModel(s,[e]);const a=new WeakMap;for(const[e,r]of n)a.set(e,s.findIndex((e=>r.equal(e))));return a}function cascadeLayerNumberForNode(e,r){return e.parent&&"atrule"===e.parent.type&&"layer"===e.parent.name.toLowerCase()?r.has(e.parent)?r.get(e.parent):-1:1/0}function normalizeLayerName(e,r){return e.trim()?e:"csstools-anon-layer--"+r++}const n=/(!\s*)?postcss-custom-properties:\s*off\b/i,o=new WeakMap;function isBlockIgnored(e){if(!e||!e.nodes)return!1;if(o.has(e))return o.get(e);const r=e.some((e=>isIgnoreComment(e,n)));return o.set(e,r),r}const s=/(!\s*)?postcss-custom-properties:\s*ignore\s+next\b/i;function isDeclarationIgnored(e){return!!e&&(!!isBlockIgnored(e.parent)||isIgnoreComment(e.prev(),s))}function isIgnoreComment(e,r){return!!e&&"comment"===e.type&&r.test(e.text)}const a=new Set(["layer"]);function isProcessableRule(e){if(!isHtmlRule(e)&&!isRootRule(e))return!1;let r=e.parent;for(;r;){if("atrule"===r.type&&!a.has(r.name.toLowerCase()))return!1;r=r.parent}return!0}const l=/^html$/i,i=/^:root$/i;function isHtmlRule(e){return e.selectors.some((e=>l.test(e)))&&e.nodes&&e.nodes.length}function isRootRule(e){return e.selectors.some((e=>i.test(e)))&&e.nodes&&e.nodes.length}const c=/^var$/i;function isVarFunction(e){return"function"===e.type&&c.test(e.value)&&Object(e.nodes).length>0}function removeCyclicReferences(e,r){const t=new Set;let n=r;for(;e.size>0;)try{toposort(Array.from(e.keys()),n);break}catch(r){if(!r._graphNode)throw r;e.delete(r._graphNode),t.add(r._graphNode),n=n.filter((e=>-1===e.indexOf(r._graphNode)))}return t}function toposort(e,r){let t=e.length;const n=new Array(t),o={};let s=t;const a=makeOutgoingEdges(r),l=makeNodesHash(e);for(;s--;)o[s]||visit(e[s],s,new Set);return n;function visit(e,r,s){if(s.has(e)){const r=new Error("Cyclic dependency"+JSON.stringify(e));throw r._graphNode=e,r}if(!l.has(e))return;if(o[r])return;o[r]=!0;let i=a.get(e)||new Set;if(i=Array.from(i),r=i.length){s.add(e);do{const e=i[--r];visit(e,l.get(e),s)}while(r);s.delete(e)}n[--t]=e}}function makeOutgoingEdges(e){const r=new Map;for(let t=0,n=e.length;t<n;t++){const n=e[t];r.has(n[0])||r.set(n[0],new Set),r.has(n[1])||r.set(n[1],new Set),r.get(n[0]).add(n[1])}return r}function makeNodesHash(e){const r=new Map;for(let t=0,n=e.length;t<n;t++)r.set(e[t],t);return r}function getCustomPropertiesFromRoot(r){const t=new Map,n=new Map,o=new Map,s=new Map,a=new Map,l=collectCascadeLayerOrder(r);r.walkRules((e=>{isProcessableRule(e)&&(isBlockIgnored(e)||(isHtmlRule(e)?e.each((e=>{if("decl"!==e.type)return;if(!e.variable||isDeclarationIgnored(e))return;if("initial"===e.value.toLowerCase().trim())return;const r=cascadeLayerNumberForNode(e,l),n=s.get(e.prop)??-1;r&&r>=n&&(s.set(e.prop,r),t.set(e.prop,e.value))})):isRootRule(e)&&e.each((e=>{if("decl"!==e.type)return;if(!e.variable||isDeclarationIgnored(e))return;if("initial"===e.value.toLowerCase().trim())return;const r=cascadeLayerNumberForNode(e,l),t=a.get(e.prop)??-1;r&&r>=t&&(a.set(e.prop,r),n.set(e.prop,e.value))}))))}));for(const[e,r]of t.entries())o.set(e,r);for(const[e,r]of n.entries())o.set(e,r);const i=[],c=new Map;for(const[r,t]of o.entries()){const n=e(t);e.walk(n.nodes,(e=>{if(isVarFunction(e)){const[t]=e.nodes.filter((e=>"word"===e.type));i.push([t.value,r])}})),c.set(r,e(t))}return removeCyclicReferences(c,i),c}function transformValueAST(r,t){if(r.nodes&&r.nodes.length){const n=new Map;r.nodes.forEach((e=>{n.set(e,r)})),e.walk(r.nodes,(e=>{"nodes"in e&&e.nodes.length&&e.nodes.forEach((r=>{n.set(r,e)}))})),e.walk(r.nodes,(r=>{if(!isVarFunction(r))return;const[o,...s]=r.nodes.filter((e=>"div"!==e.type)),{value:a}=o,l=n.get(r);if(!l)return;const i=l.nodes.indexOf(r);if(-1===i)return;let c=!1;s&&e.walk(s,(e=>{if(isVarFunction(e)){const[r]=e.nodes.filter((e=>"word"===e.type));if(t.has(r.value))return;return c=!0,!1}}));let u=[];if(t.has(a)){var p;u=(null==(p=t.get(a))?void 0:p.nodes)??[]}else{if(!s.length||c)return;u=r.nodes.slice(r.nodes.indexOf(s[0]))}u.length?(l.nodes.splice(i,1,...u),l.nodes.forEach((e=>n.set(e,l)))):(l.nodes.splice(i,1,{type:"comment",value:"",sourceIndex:r.sourceIndex,sourceEndIndex:r.sourceEndIndex}),l.nodes.forEach((e=>n.set(e,l))))}),!0)}return r.toString()}var transformProperties=(r,t,n)=>{if(isTransformableDecl(r)&&!isDeclarationIgnored(r)){const a=r.value;let l=transformValueAST(e(a),t);const i=new Set;for(;l.includes("--")&&l.toLowerCase().includes("var(")&&!i.has(l);){i.add(l);l=transformValueAST(e(l),t)}if(l!==a){if(parentHasExactFallback(r,l))return void(n.preserve||r.remove());if(n.preserve){var o;const e=r.cloneBefore({value:l});hasTrailingComment(e)&&null!=(o=e.raws)&&o.value&&(e.raws.value.value=e.value.replace(u,"$1"),e.raws.value.raw=e.raws.value.value+e.raws.value.raw.replace(u,"$2"))}else{var s;r.value=l,hasTrailingComment(r)&&null!=(s=r.raws)&&s.value&&(r.raws.value.value=r.value.replace(u,"$1"),r.raws.value.raw=r.raws.value.value+r.raws.value.raw.replace(u,"$2"))}}}};const isTransformableDecl=e=>!e.variable&&e.value.includes("--")&&e.value.toLowerCase().includes("var("),hasTrailingComment=e=>{var r,t;return"value"in Object(Object(e.raws).value)&&"raw"in((null==(r=e.raws)?void 0:r.value)??{})&&u.test((null==(t=e.raws.value)?void 0:t.raw)??"")},u=/^([\W\w]+)(\s*\/\*[\W\w]+?\*\/)$/;function parentHasExactFallback(e,r){if(!e||!e.parent)return!1;let t=!1;const n=e.parent.index(e);return e.parent.each(((o,s)=>o!==e&&(!(s>=n)&&void("decl"===o.type&&o.prop.toLowerCase()===e.prop.toLowerCase()&&o.value===r&&(t=!0))))),t}function hasSupportsAtRuleAncestor(e){let r=e.parent;for(;r;)if("atrule"===r.type){if("supports"===r.name.toLowerCase()&&/([^\w]var\()|(\(top: var\(--f\))/i.test(r.params))return!0;r=r.parent}else r=r.parent;return!1}const creator=r=>{const t=!("preserve"in Object(r))||Boolean(null==r?void 0:r.preserve);if("importFrom"in Object(r))throw new Error('[postcss-custom-properties] "importFrom" is no longer supported');if("exportTo"in Object(r))throw new Error('[postcss-custom-properties] "exportTo" is no longer supported');return{postcssPlugin:"postcss-custom-properties",prepare:()=>{let r=new Map;return{Once:e=>{r=getCustomPropertiesFromRoot(e)},Declaration:n=>{if(hasSupportsAtRuleAncestor(n))return;let o=r;if(t&&n.parent){let t=!1;n.parent.each((s=>{n!==s&&"decl"===s.type&&s.variable&&!isDeclarationIgnored(s)&&(t||(o=new Map(r),t=!0),"initial"!==s.value.toLowerCase().trim()?o.set(s.prop,e(s.value)):o.delete(s.prop))}))}transformProperties(n,o,{preserve:t})}}}}};creator.postcss=!0,module.exports=creator;
1+
"use strict";var e=require("postcss-value-parser"),r=require("@csstools/cascade-layer-name-parser");const t=r.parse("csstools-implicit-layer")[0];function collectCascadeLayerOrder(e){const n=new Map,o=new Map,s=[];e.walkAtRules((e=>{var a;if("layer"!==e.name.toLowerCase())return;{let r=e.parent;for(;r;){if("atrule"!==r.type||"layer"!==r.name.toLowerCase()){if(r===e.root())break;return}r=r.parent}}let l;if(e.nodes)l=normalizeLayerName(e.params,1);else{if(!e.params.trim())return;l=e.params}let i=r.parse(l);if(null!=(a=i)&&a.length){{let r=e.parent;for(;r&&"atrule"===r.type&&"layer"===r.name.toLowerCase();){const e=o.get(r);e?(i=i.map((r=>e.concat(r))),r=r.parent):r=r.parent}}if(r.addLayerToModel(s,i),e.nodes){const r=i[0].concat(t);n.set(e,r),o.set(e,i[0])}}}));for(const e of n.values())r.addLayerToModel(s,[e]);const a=new WeakMap;for(const[e,r]of n)a.set(e,s.findIndex((e=>r.equal(e))));return a}function normalizeLayerName(e,r){return e.trim()?e:"csstools-anon-layer--"+r++}const n=/(!\s*)?postcss-custom-properties:\s*off\b/i,o=new WeakMap;function isBlockIgnored(e){if(!e||!e.nodes)return!1;if(o.has(e))return o.get(e);const r=e.some((e=>isIgnoreComment(e,n)));return o.set(e,r),r}const s=/(!\s*)?postcss-custom-properties:\s*ignore\s+next\b/i;function isDeclarationIgnored(e){return!!e&&(!!isBlockIgnored(e.parent)||isIgnoreComment(e.prev(),s))}function isIgnoreComment(e,r){return!!e&&"comment"===e.type&&r.test(e.text)}const a=new Set(["layer"]);function isProcessableRule(e){let r=e.parent;for(;r;){if("atrule"===r.type&&!a.has(r.name.toLowerCase()))return!1;r=r.parent}return!0}const l=/^html$/i,i=/^:where\(html\)$/i,c=/^:root$/i,u=/^:where\(:root\)$/i,p=/(html|:root)/i,f=/^var$/i;function isVarFunction(e){return"function"===e.type&&f.test(e.value)&&Object(e.nodes).length>0}function removeCyclicReferences(e,r){const t=new Set;let n=r;for(;e.size>0;)try{toposort(Array.from(e.keys()),n);break}catch(r){if(!r._graphNode)throw r;e.delete(r._graphNode),t.add(r._graphNode),n=n.filter((e=>-1===e.indexOf(r._graphNode)))}return t}function toposort(e,r){let t=e.length;const n=new Array(t),o={};let s=t;const a=makeOutgoingEdges(r),l=makeNodesHash(e);for(;s--;)o[s]||visit(e[s],s,new Set);return n;function visit(e,r,s){if(s.has(e)){const r=new Error("Cyclic dependency"+JSON.stringify(e));throw r._graphNode=e,r}if(!l.has(e))return;if(o[r])return;o[r]=!0;let i=a.get(e)||new Set;if(i=Array.from(i),r=i.length){s.add(e);do{const e=i[--r];visit(e,l.get(e),s)}while(r);s.delete(e)}n[--t]=e}}function makeOutgoingEdges(e){const r=new Map;for(let t=0,n=e.length;t<n;t++){const n=e[t];r.has(n[0])||r.set(n[0],new Set),r.has(n[1])||r.set(n[1],new Set),r.get(n[0]).add(n[1])}return r}function makeNodesHash(e){const r=new Map;for(let t=0,n=e.length;t<n;t++)r.set(e[t],t);return r}function getCustomPropertiesFromRoot(r){const t=new Map,n=new Map,o=collectCascadeLayerOrder(r);r.walkRules((e=>{var r;p.test(e.selector)&&null!=(r=e.nodes)&&r.length&&isProcessableRule(e)&&(isBlockIgnored(e)||e.selectors.forEach((r=>{let s=-1;if(i.test(r)||u.test(r))s=0;else if(l.test(r))s=1;else{if(!c.test(r))return;s=2}const a=(f=o,((p=e).parent&&"atrule"===p.parent.type&&"layer"===p.parent.name.toLowerCase()?f.has(p.parent)?f.get(p.parent)+1:0:1e7)+10+s);var p,f;e.each((e=>{if("decl"!==e.type)return;if(!e.variable||isDeclarationIgnored(e))return;if("initial"===e.value.toLowerCase().trim())return;const r=n.get(e.prop)??-1;a>=r&&(n.set(e.prop,a),t.set(e.prop,e.value))}))})))}));const s=[],a=new Map;for(const[r,n]of t.entries()){const t=e(n);e.walk(t.nodes,(e=>{if(isVarFunction(e)){const[t]=e.nodes.filter((e=>"word"===e.type));s.push([t.value,r])}})),a.set(r,e(n))}return removeCyclicReferences(a,s),a}function transformValueAST(r,t){if(r.nodes&&r.nodes.length){const n=new Map;r.nodes.forEach((e=>{n.set(e,r)})),e.walk(r.nodes,(e=>{"nodes"in e&&e.nodes.length&&e.nodes.forEach((r=>{n.set(r,e)}))})),e.walk(r.nodes,(r=>{if(!isVarFunction(r))return;const[o,...s]=r.nodes.filter((e=>"div"!==e.type)),{value:a}=o,l=n.get(r);if(!l)return;const i=l.nodes.indexOf(r);if(-1===i)return;let c=!1;s&&e.walk(s,(e=>{if(isVarFunction(e)){const[r]=e.nodes.filter((e=>"word"===e.type));if(t.has(r.value))return;return c=!0,!1}}));let u=[];if(t.has(a)){var p;u=(null==(p=t.get(a))?void 0:p.nodes)??[]}else{if(!s.length||c)return;u=r.nodes.slice(r.nodes.indexOf(s[0]))}u.length?(l.nodes.splice(i,1,...u),l.nodes.forEach((e=>n.set(e,l)))):(l.nodes.splice(i,1,{type:"comment",value:"",sourceIndex:r.sourceIndex,sourceEndIndex:r.sourceEndIndex}),l.nodes.forEach((e=>n.set(e,l))))}),!0)}return r.toString()}var transformProperties=(r,t,n)=>{if(isTransformableDecl(r)&&!isDeclarationIgnored(r)){const a=r.value;let l=transformValueAST(e(a),t);const i=new Set;for(;l.includes("--")&&l.toLowerCase().includes("var(")&&!i.has(l);){i.add(l);l=transformValueAST(e(l),t)}if(l!==a){if(parentHasExactFallback(r,l))return void(n.preserve||r.remove());if(n.preserve){var o;const e=r.cloneBefore({value:l});hasTrailingComment(e)&&null!=(o=e.raws)&&o.value&&(e.raws.value.value=e.value.replace(d,"$1"),e.raws.value.raw=e.raws.value.value+e.raws.value.raw.replace(d,"$2"))}else{var s;r.value=l,hasTrailingComment(r)&&null!=(s=r.raws)&&s.value&&(r.raws.value.value=r.value.replace(d,"$1"),r.raws.value.raw=r.raws.value.value+r.raws.value.raw.replace(d,"$2"))}}}};const isTransformableDecl=e=>!e.variable&&e.value.includes("--")&&e.value.toLowerCase().includes("var("),hasTrailingComment=e=>{var r,t;return"value"in Object(Object(e.raws).value)&&"raw"in((null==(r=e.raws)?void 0:r.value)??{})&&d.test((null==(t=e.raws.value)?void 0:t.raw)??"")},d=/^([\W\w]+)(\s*\/\*[\W\w]+?\*\/)$/;function parentHasExactFallback(e,r){if(!e||!e.parent)return!1;let t=!1;const n=e.parent.index(e);return e.parent.each(((o,s)=>o!==e&&(!(s>=n)&&void("decl"===o.type&&o.prop.toLowerCase()===e.prop.toLowerCase()&&o.value===r&&(t=!0))))),t}function hasSupportsAtRuleAncestor(e){let r=e.parent;for(;r;)if("atrule"===r.type){if("supports"===r.name.toLowerCase()&&/([^\w]var\()|(\(top: var\(--f\))/i.test(r.params))return!0;r=r.parent}else r=r.parent;return!1}const creator=r=>{const t=!("preserve"in Object(r))||Boolean(null==r?void 0:r.preserve);if("importFrom"in Object(r))throw new Error('[postcss-custom-properties] "importFrom" is no longer supported');if("exportTo"in Object(r))throw new Error('[postcss-custom-properties] "exportTo" is no longer supported');return{postcssPlugin:"postcss-custom-properties",prepare:()=>{let r=new Map;return{Once:e=>{r=getCustomPropertiesFromRoot(e)},Declaration:n=>{if(hasSupportsAtRuleAncestor(n))return;let o=r;if(t&&n.parent){let t=!1;n.parent.each((s=>{n!==s&&"decl"===s.type&&s.variable&&!isDeclarationIgnored(s)&&(t||(o=new Map(r),t=!0),"initial"!==s.value.toLowerCase().trim()?o.set(s.prop,e(s.value)):o.delete(s.prop))}))}transformProperties(n,o,{preserve:t})}}}}};creator.postcss=!0,module.exports=creator;

0 commit comments

Comments
 (0)