postcss-custom-properties
Version:
Use Custom Properties Queries in CSS
2 lines (1 loc) • 9.32 kB
JavaScript
import{parse as e,addLayerToModel as t}from"@csstools/cascade-layer-name-parser";import n from"postcss-value-parser";import{hasSupportsAtRuleAncestor as r}from"@csstools/utilities";const o=e("csstools-implicit-layer")[0];function collectCascadeLayerOrder(n){const r=new Map,s=new Map,a=[];let i=1;n.walkAtRules(n=>{if("layer"!==n.name.toLowerCase())return;{let e=n.parent,t=0;for(;e;){if("atrule"!==e.type||"layer"!==e.name.toLowerCase()){if(e===n.root())break;return}if(t++,t>100)throw new Error("Maximum nested @layer depth exceeded, reduce the complexity of your layers");e=e.parent}}let c;if(n.nodes)c=normalizeLayerName(n.params,i++);else{if(!n.params.trim())return;c=n.params}let l=e(c);if(l?.length){{let e=n.parent;for(;e&&"atrule"===e.type&&"layer"===e.name.toLowerCase();){const t=s.get(e);if(t){l=l.map(e=>t.concat(e));break}e=e.parent}}if(t(a,l),n.nodes){const e=l[0].concat(o);r.set(n,e),s.set(n,l[0])}}});for(const e of r.values())t(a,[e]);const c=new WeakMap;for(const[e,t]of r)c.set(e,a.findIndex(e=>t.equal(e)));return c}function normalizeLayerName(e,t){return e.trim()?e:`csstools-anon-layer--${t}`}const s=/(?:!\s*)?postcss-custom-properties:\s*off\b/i,a=new WeakMap;function isBlockIgnored(e){if(!e||!e.nodes)return!1;if(a.has(e))return a.get(e);const t=e.some(e=>isIgnoreComment(e,s));return a.set(e,t),t}const i=/(?:!\s*)?postcss-custom-properties:\s*ignore\s+next\b/i;function isDeclarationIgnored(e){return!!e&&(!!isBlockIgnored(e.parent)||isIgnoreComment(e.prev(),i))}function isIgnoreComment(e,t){return!!e&&"comment"===e.type&&t.test(e.text)}const c=new Set(["layer"]);function isProcessableRule(e){let t=e.parent;for(;t;){if("atrule"===t.type&&!c.has(t.name.toLowerCase()))return!1;t=t.parent}return!0}const l=/^html$/i,u=/^:where\(html\)$/i,p=/^:root$/i,f=/^:where\(:root\)$/i,d=/(html|:root)/i,m=/^var$/i;function isVarFunction(e){return"function"===e.type&&m.test(e.value)&&e.nodes?.length>0}const g=/\bvar\(/i;function parseOrCached(e,t){let r=t.get(e);return r||(r=n(e),t.set(e,r),r)}function toposort(e,t){let n=e.length;const r=new Array(n),o=new Set,s=makeOutgoingEdges(t),a=makeNodesHash(e);for(let t=e.length-1;t>=0;t--){if(o.has(t))continue;const i=e[t],c=new Set,l=[];for(o.add(t),c.add(i),l.push({node:i,outgoing:Array.from(s.get(i)||new Set),next:0});l.length;){const e=l[l.length-1];if(e.next<e.outgoing.length){const t=e.outgoing[e.outgoing.length-1-e.next];if(e.next++,c.has(t)){let e;try{e=", node was:"+JSON.stringify(t)}catch{e=""}throw new Error("Cyclic dependency"+e)}const n=a.get(t);if(void 0===n)throw new Error("Found unknown node. Make sure to provided all involved nodes. Unknown node: "+JSON.stringify(t));if(o.has(n))continue;o.add(n),c.add(t),l.push({node:t,outgoing:Array.from(s.get(t)||new Set),next:0});continue}l.pop(),c.delete(e.node),r[--n]=e.node}}return r}function removeCyclicReferences(e,t){const n=new Set,r=new Set(e.keys()),o=new Map;for(const e of r)o.set(e,[]);for(const e of t){const t=e[0],s=e[1];if(!r.has(t)||!r.has(s))continue;if(t===s){n.add(t);continue}const a=o.get(t);a&&a.push(s)}const s=new Map,a=new Map,i=new Set,c=[];let l=0;const getIndex=e=>s.get(e)??0,getLowLink=e=>a.get(e)??0;for(const e of r){if(s.has(e))continue;const t=[{node:e,childIndex:0}];for(s.set(e,l),a.set(e,l),l++,c.push(e),i.add(e);t.length;){const e=t[t.length-1],r=o.get(e.node)??[];if(e.childIndex<r.length){const n=r[e.childIndex];e.childIndex++,s.has(n)?i.has(n)&&a.set(e.node,Math.min(getLowLink(e.node),getIndex(n))):(s.set(n,l),a.set(n,l),l++,c.push(n),i.add(n),t.push({node:n,childIndex:0}));continue}t.pop();const u=t[t.length-1];if(u&&a.set(u.node,Math.min(getLowLink(u.node),getLowLink(e.node))),getLowLink(e.node)===getIndex(e.node)){const t=[];let r;do{if(r=c.pop(),void 0===r)break;i.delete(r),t.push(r)}while(r!==e.node);if(t.length>1)for(const e of t)n.add(e)}}}for(const t of n)e.delete(t);return n}function makeOutgoingEdges(e){const t=new Map;for(let n=0,r=e.length;n<r;n++){const r=e[n];t.has(r[0])||t.set(r[0],new Set),t.has(r[1])||t.set(r[1],new Set),t.get(r[0]).add(r[1])}return t}function makeNodesHash(e){const t=new Map;for(let n=0,r=e.length;n<r;n++)t.set(e[n],n);return t}function parseVarFunction(e){let t,n,r=!1;for(const o of e.nodes)if(t||"word"!==o.type)if(!t||r||"div"!==o.type||","!==o.value){if(r&&Array.isArray(n))n.push(o);else if("space"!==o.type&&("div"!==o.type||""!==o.value.trim()))return}else r=!0,n=[];else t=o;if(t)return{name:t,fallback:n}}const h=1e5;function replaceNodeWithNodes(e,t,n){if(n.length<=8192)return void e.splice(t,1,...n);const r=e.slice(0,t).concat(n,e.slice(t+1));e.length=0;for(let t=0;t<r.length;t++)e.push(r[t])}function transformValueAST(e,t,r={remaining:h}){return e.nodes?.length?(walk(e.nodes,(e,o,s)=>{if(r.remaining--,r.remaining<0)throw new Error("Maximum custom property expansion size exceeded, reduce the complexity of your custom properties");if(!isVarFunction(e))return;const a=parseVarFunction(e);if(!a)return;let i=!1;a.fallback&&n.walk(a.fallback,e=>{if(!isVarFunction(e))return;const n=parseVarFunction(e);return n?n.fallback||t.has(n.name.value)?void 0:(i=!0,!1):void 0});let c=t.get(a.name.value)?.nodes;c||!a.fallback||i||(c=a.fallback),void 0!==c&&(c.length?replaceNodeWithNodes(s,o,c):s.splice(o,1,{type:"div",value:" ",before:"",after:"",sourceIndex:e.sourceIndex,sourceEndIndex:e.sourceEndIndex}))}),n.stringify(e.nodes)):""}function walk(e,t){let n,r,o;for(n=0,r=e.length;n<r;n+=1)o=e[n],"function"===o.type&&Array.isArray(o.nodes)&&walk(o.nodes,t),t(o,n,e),r=e.length}const w=/^initial$/i;function isInitial(e){const t=e.nodes.filter(e=>"comment"!==e.type&&"space"!==e.type);return 1===t.length&&("word"===t[0].type&&w.test(t[0].value))}function buildCustomPropertiesMap(e,t,r){if(!e.size)return t;const o=new Map(t);{const s=[];for(const[a,i]of e.entries()){const c=parseOrCached(i,r);let l=!1;n.walk(c.nodes,n=>{if(!isVarFunction(n))return;const r=parseVarFunction(n);r&&(r.fallback||e.has(r.name.value)||t.has(r.name.value)?s.push([r.name.value,a]):l=!0)}),l||o.set(a,c)}removeCyclicReferences(o,s)}{const e=[];for(const[t,r]of o.entries())n.walk(r.nodes,n=>{if(!isVarFunction(n))return;const r=parseVarFunction(n);r&&(r.fallback||o.has(r.name.value)?e.push([r.name.value,t]):o.delete(t))});for(let t=0;t<e.length;t++){const[n,r]=e[t];o.has(n)&&o.has(r)||e.splice(t--,1)}const t=toposort(Array.from(o.keys()),e),s={remaining:h};for(const e of t){const t=o.get(e);if(!t)continue;const n=parseOrCached(transformValueAST(t,o,s),r);o.set(e,n)}}for(const[e,t]of o.entries())isInitial(t)&&o.delete(e);return o}const v=/^function$/i;function inFunction$1(e){let t=e.parent;for(;t;){if("atrule"===t.type&&v.test(t.name))return!0;t=t.parent}return!1}function getCustomPropertiesFromRoot(e,t){const n=new Map,r=new Map,o=collectCascadeLayerOrder(e);return e.walkRules(e=>{d.test(e.selector)&&e.nodes?.length&&isProcessableRule(e)&&(isBlockIgnored(e)||e.selectors.forEach(t=>{let s;if(u.test(t)||f.test(t))s=0;else if(l.test(t))s=1;else{if(!p.test(t))return;s=2}const a=(c=o,((i=e).parent&&"atrule"===i.parent.type&&"layer"===i.parent.name.toLowerCase()?c.has(i.parent)?c.get(i.parent)+1:0:1e7)+10+s);var i,c;e.each(e=>{if("decl"!==e.type)return;if(!e.variable||isDeclarationIgnored(e))return;if(inFunction$1(e))return;if("initial"===e.value.toLowerCase().trim())return;const t=r.get(e.prop)??-1;a>=t&&(r.set(e.prop,a),n.set(e.prop,e.value))})}))}),buildCustomPropertiesMap(n,new Map,t)}function getCustomPropertiesFromSiblings(e,t,n){if(!e.parent)return t;const r=new Map;return e.parent.each(t=>{"decl"===t.type&&t.variable&&e!==t&&(isDeclarationIgnored(t)||r.set(t.prop,t.value))}),r.size?buildCustomPropertiesMap(r,t,n):t}function transformProperties(e,t,r){if(isTransformableDecl(e)&&!isDeclarationIgnored(e)){const o=e.raws?.value?.raw??e.value,s=transformValueAST(n(o),t,r.budget);if(s===o)return;if(parentHasExactFallback(e,s))return void(r.preserve||e.remove());const a=e.cloneBefore({value:s});a.raws?.value?.raw&&(a.raws.value.raw=""),r?.preserve||e.remove()}}const isTransformableDecl=e=>!e.variable&&e.value.includes("--")&&e.value.toLowerCase().includes("var(");function parentHasExactFallback(e,t){if(!e||!e.parent)return!1;const n=e.prop.toLowerCase();let r=e.prev();for(;r;){if("decl"===r.type&&r.prop.toLowerCase()===n&&r.value===t)return!0;r=r.prev()}return!1}const y=/\bvar\(|\(top: var\(--f\)/i,k=/^function$/i;function inFunction(e){let t=e.parent;for(;t;){if("atrule"===t.type&&k.test(t.name))return!0;t=t.parent}return!1}const creator=e=>{const t=!("preserve"in Object(e))||Boolean(e?.preserve);if("importFrom"in Object(e))throw new Error('[postcss-custom-properties] "importFrom" is no longer supported');if("exportTo"in Object(e))throw new Error('[postcss-custom-properties] "exportTo" is no longer supported');return{postcssPlugin:"postcss-custom-properties",prepare(){let e=new Map;const n=new WeakMap,o=new Map;let s={remaining:h};return{postcssPlugin:"postcss-custom-properties",Once(t){s={remaining:h},e=getCustomPropertiesFromRoot(t,o)},Declaration(a){if(inFunction(a))return;if(!g.test(a.value))return;if(r(a,y))return;let i=e;t&&a.parent&&(i=n.get(a.parent)??getCustomPropertiesFromSiblings(a,e,o),n.set(a.parent,i)),transformProperties(a,i,{preserve:t,budget:s})}}}}};creator.postcss=!0;export{creator as default,creator as"module.exports"};