@webflow/variables 2.8.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # @webflow/variables
2
2
 
3
+ ## 2.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7e7c01f: `@webflow/variables/postcss` reads `@webflow-collection` blocks in `.css` variable declaration files into a style variable catalog (`parseVariableSources`) and strips them from component bundles (`stripWebflowCollectionsPlugin`, a PostCSS plugin). The blocks hold metadata only. Values stay in plain CSS rules, and every problem is reported with its file, line and column.
8
+
9
+ ```css
10
+ :root {
11
+ --radius--md: 0px;
12
+ --brand: #232f3e;
13
+ }
14
+
15
+ [data-theme="dark"] {
16
+ --brand: #f3f3f3;
17
+ }
18
+
19
+ @webflow-collection colors "Colors" {
20
+ @mode dark "Dark" {
21
+ selector: "[data-theme='dark']";
22
+ }
23
+
24
+ @variable --brand {
25
+ label: "color/brand";
26
+ }
27
+
28
+ @variable --radius--md {
29
+ type: "length";
30
+ }
31
+ }
32
+ ```
33
+
34
+ - `@variable --id` exports a custom property. `label` is optional and defaults to the id without `--`. `type` is optional: `color`, `length`, `number`, `percentage` or `font-family`. A bare `@variable --id;` is the same as an empty block.
35
+ - `@mode id "Label"` needs a quoted `selector`. A mode value is the declaration of the id on the top-level rule with that selector. A mode with no declaration uses the base value.
36
+ - The base value is the declaration on `:root` or `:host`. A collection-level `selector: "…"` reads it from another top-level rule instead. Declarations inside `@media`, `@layer` or `@supports` are not read, and the parser warns when one would have matched.
37
+ - The type comes from the value. When a value can have more than one type (a bare `0`), the parser uses `number` and warns; add `type: "length"` (or another type) to choose. A value with no Webflow type (a keyword, a shadow) is left out with a warning. An unknown descriptor or `type`, an unquoted `selector`, or a missing base declaration is an error.
38
+ - `var(--x)` aliases a variable exported with `@variable`. Any other `var()` is an error.
39
+
40
+ `stripWebflowCollectionsPlugin({ sources, onUnlisted })` removes `@webflow-collection` blocks from the CSS of every file it processes. `onUnlisted` is called for a file that has blocks but is not in `sources`.
41
+
42
+ ### Patch Changes
43
+
44
+ - 2d4d12d: `validateStyleVariableCatalog` is now the full share contract:
45
+
46
+ - Variable ids must use only ASCII letters, digits, `-` and `_` after the leading `--`.
47
+ - Color values must be colors Webflow can parse (adds a `tinycolor2` dependency).
48
+ - No declared collection may have a name that becomes the same CSS name as the implicit base collection (`RESERVED_BASE_COLLECTION_NAME`, "Base collection") when a variable uses it.
49
+ - Number values must have unit `-` and percentage values must have unit `%`.
50
+
51
+ - Updated dependencies [e9bdf91]
52
+ - @webflow/data-types@2.9.0
53
+
3
54
  ## 2.8.0
4
55
 
5
56
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var M=/\s/;function m(s){if(s===void 0)return false;let e=s.charCodeAt(0);return (e>=128||e>=97&&e<=122||e>=65&&e<=90||e>=48&&e<=57||s==="_")&&!M.test(s)}function v(s){let e=s.length,t="",a=0,r=e;for(;a<e&&!m(s[a]);a+=1);for(;r>=1&&!m(s[r-1]);r-=1);for(;a<r;a+=1){let i=s[a];if(i==="/"){for(t[t.length-1]==="-"&&(t=t.substring(0,t.length-1));a<r;a+=1)if(i=s[a],m(i)){t+="--"+i;break}}else m(i)?t+=i:t[t.length-1]!=="-"&&(t+="-");}return t.toLowerCase()}var g="base",_="webflow-collection";var R=/var\(\s*(--[^\s,)(]+)/gi,F=/var\(\s*(--[^\s,)(]+)\s*,/gi;function h(s){return [...s.matchAll(R)].map(e=>e[1]).filter(e=>e!==void 0)}function V(s){return [...s.matchAll(F)].map(e=>e[1]).filter(e=>e!==void 0)}var A=/^--[A-Za-z0-9_\-\u0080-\uFFFF]+$/,E=/^(?:--|-?[A-Za-z_\u0080-\uFFFF])[A-Za-z0-9_\-\u0080-\uFFFF]*$/,L={px:true,em:true,rem:true,vh:true,vw:true,dvh:true,dvw:true,lvh:true,lvw:true,svh:true,svw:true,vmax:true,vmin:true,ch:true};function $(s,e,t,a){let r=new Map,i=[];return s.forEach((n,d)=>{let l=e(n),o=r.get(l);o===void 0?r.set(l,d):i.push({path:t(d),message:a(l,o,d)});}),i}function b(s){return s.variables.flatMap((e,t)=>[{path:`variables[${t}].value`,value:e.value,variableIndex:t},...Object.entries(e.modes??{}).map(([a,r])=>({path:`variables[${t}].modes.${a}`,value:r,variableIndex:t}))])}function x(s){let e=new Map;return s.variables.forEach((t,a)=>{e.has(t.id)||e.set(t.id,{variable:t,index:a});}),e}var w=50;function T(s){let e=x(s),t=new Map;for(let{value:l,variableIndex:o}of b(s)){let c=s.variables[o]?.id;if(c===void 0||e.get(c)?.index!==o)continue;let u=l.type==="ref"?l.value.variableId===c?[]:[l.value.variableId]:l.type==="raw"?h(l.value):[],p=t.get(c)??new Set;u.filter(f=>e.has(f)).forEach(f=>p.add(f)),t.set(c,p);}let a=[],r=new Set,i=new Map,n=false,d=l=>{let o=[],c=u=>{i.set(u,"visiting"),o.push({id:u,targets:(t.get(u)??new Set).values()});};for(c(l);o.length>0&&!n;){let u=o[o.length-1],p=u.targets.next();if(p.done){i.set(u.id,"done"),o.pop();continue}let f=p.value,S=i.get(f);if(S==="visiting"){let C=o.slice(o.findIndex(y=>y.id===f)).map(y=>y.id),I=[...C].sort().join(`
2
- `);if(!r.has(I)){if(r.size===w){n=true,a.push({path:"variables",message:`More than ${w} circular references, the rest are not shown`});continue}r.add(I),a.push({path:`variables[${e.get(f)?.index}]`,message:`Circular reference: ${[...C,f].join(" \u2192 ")}`});}}else S===void 0&&c(f);}};for(let l of e.keys()){if(n)break;i.has(l)||d(l);}return a}var k=[({variables:s})=>s.flatMap((e,t)=>A.test(e.id)?[]:[{path:`variables[${t}].id`,message:`"${e.id}" is not a valid CSS custom property name (it must start with "--")`}]),({variables:s})=>$(s,e=>e.id,e=>`variables[${e}].id`,(e,t,a)=>`Duplicate variable id "${e}" at variables[${t}] and variables[${a}]`),({collections:s})=>s.flatMap((e,t)=>[...e.id===g?[{path:`collections[${t}].id`,message:`Collection id "${g}" is reserved`}]:E.test(e.id)?[]:[{path:`collections[${t}].id`,message:`"${e.id}" is not a valid CSS identifier`}],..."isDefault"in e?[{path:`collections[${t}].isDefault`,message:"Library collections cannot set isDefault"}]:[]]),({collections:s})=>$(s,e=>e.id,e=>`collections[${e}].id`,(e,t,a)=>`Duplicate collection id "${e}" at collections[${t}] and collections[${a}]`),({collections:s})=>s.flatMap((e,t)=>[...e.modes.flatMap((a,r)=>{let i=`collections[${t}].modes[${r}].id`;return a.id===g?[{path:i,message:`Mode id "${g}" is reserved`}]:E.test(a.id)?[]:[{path:i,message:`"${a.id}" is not a valid CSS identifier`}]}),...$(e.modes,a=>a.id,a=>`collections[${t}].modes[${a}].id`,(a,r,i)=>`Duplicate mode id "${a}" at modes[${r}] and modes[${i}] of collection "${e.id}"`)]),({collections:s,variables:e})=>{let t=[],a=(i,n)=>{let d=new Map,l=new Set;for(let{item:o,path:c}of i){if(l.has(o.id))continue;l.add(o.id);let u=o.name??o.id,p=v(u);if(p===""){t.push({path:c,message:`"${u}" has no characters usable in a CSS variable name`});continue}let f=d.get(p);f===void 0?d.set(p,{label:u,path:c}):t.push({path:c,message:`"${f.label}" at ${f.path} and "${u}" at ${c} both become "${p}" ${n}`});}};a(s.map((i,n)=>({item:i,path:`collections[${n}]`})),"in this library"),s.forEach((i,n)=>a(i.modes.map((d,l)=>({item:d,path:`collections[${n}].modes[${l}]`})),`in collection "${i.id}"`));let r=new Map;return e.forEach((i,n)=>{let d=i.collectionId??g,l=r.get(d)??[];l.push({item:i,path:`variables[${n}]`}),r.set(d,l);}),r.forEach((i,n)=>a(i,`in collection "${n}"`)),t},({collections:s,variables:e})=>{let t=new Map(s.map(a=>[a.id,new Set(a.modes.map(r=>r.id))]));return e.flatMap((a,r)=>{let i=a.collectionId===void 0?new Set:t.get(a.collectionId);return i===void 0?[{path:`variables[${r}].collectionId`,message:a.collectionId===g?`Collection id "${g}" is reserved; omit the id for the implicit base collection`:`Collection "${a.collectionId}" is not declared`}]:Object.keys(a.modes??{}).filter(n=>!i.has(n)).map(n=>({path:`variables[${r}].modes.${n}`,message:`Mode "${n}" is not declared in collection "${a.collectionId??g}"`}))})},s=>{let e=new Set(s.variables.map(t=>t.id));return b(s).flatMap(({path:t,value:a,variableIndex:r})=>{if(a.type!=="ref")return [];let i=a.value.variableId;return i===s.variables[r]?.id?[{path:t,message:`Variable "${i}" references itself`}]:e.has(i)?[]:[{path:t,message:`Referenced variable "${i}" does not exist`}]})},s=>{let e=new Set(s.variables.map(t=>t.id));return b(s).flatMap(({path:t,value:a})=>a.type!=="raw"?[]:h(a.value).filter(r=>!e.has(r)).map(r=>({path:t,message:`var(${r}) does not name a variable in this library`})))},s=>b(s).flatMap(({path:e,value:t})=>t.type!=="raw"?[]:V(t.value).map(a=>({path:e,message:`var(${a}, \u2026) has a fallback; library variables do not support var() fallbacks`}))),s=>b(s).flatMap(({path:e,value:t,variableIndex:a})=>{let r=s.variables[a]?.type;return t.type==="ref"||t.type==="raw"?[]:t.type===r?[]:[{path:e,message:`A "${t.type}" value does not match the variable type "${r}"`}]}),s=>b(s).flatMap(({path:e,value:t})=>t.type!=="length"?[]:Object.hasOwn(L,t.value.unit)?[]:[{path:e,message:`"${t.value.unit}" is not a supported length unit`}]),s=>{let e=x(s);return b(s).flatMap(({path:t,value:a,variableIndex:r})=>{if(a.type!=="ref")return [];let i=s.variables[r],n=e.get(a.value.variableId)?.variable;return i===void 0||n===void 0?[]:n.id===i.id?[]:n.type===i.type?[]:[{path:t,message:`"${i.id}" is a ${i.type} variable but references "${n.id}", a ${n.type} variable`}]})},T];function D(s){return k.flatMap(e=>e(s))}exports.RESERVED_BASE_ID=g;exports.WEBFLOW_COLLECTION_AT_RULE=_;exports.extractVarReferences=h;exports.sanitizeVariableName=v;exports.validateStyleVariableCatalog=D;
1
+ 'use strict';var R=require('tinycolor2');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var R__default=/*#__PURE__*/_interopDefault(R);var A=/\s/;function h(a){if(a===void 0)return false;let t=a.charCodeAt(0);return (t>=128||t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||a==="_")&&!A.test(a)}function v(a){let t=a.length,e="",i=0,r=t;for(;i<t&&!h(a[i]);i+=1);for(;r>=1&&!h(a[r-1]);r-=1);for(;i<r;i+=1){let s=a[i];if(s==="/"){for(e[e.length-1]==="-"&&(e=e.substring(0,e.length-1));i<r;i+=1)if(s=a[i],h(s)){e+="--"+s;break}}else h(s)?e+=s:e[e.length-1]!=="-"&&(e+="-");}return e.toLowerCase()}function L(a){let t=a.toLowerCase().trim();if(!/^rgba?\([^)]+\)$/.test(t))return a;let e=t.split(/[,()]/).map(s=>s.trim()).filter(s=>s!==""&&!Number.isNaN(Number(s)));if(e.length<3)return a;e[3]=e[3]||"1";let i=parseFloat(e[3]),r=!Number.isNaN(i)&&i<1;return r||e.pop(),`${r?"rgba":"rgb"}(${e.join(", ")})`}function V(a){return R__default.default(L(a)).isValid()}var p="base",S="Base collection",N="webflow-collection";var D=/var\(\s*(--[^\s,)(]+)/gi,T=/var\(\s*(--[^\s,)(]+)\s*,/gi;function y(a){return [...a.matchAll(D)].map(t=>t[1]).filter(t=>t!==void 0)}function w(a){return [...a.matchAll(T)].map(t=>t[1]).filter(t=>t!==void 0)}var F=/^--[A-Za-z0-9_-]+$/,x=/^(?:--|-?[A-Za-z_\u0080-\uFFFF])[A-Za-z0-9_\-\u0080-\uFFFF]*$/,O={px:true,em:true,rem:true,vh:true,vw:true,dvh:true,dvw:true,lvh:true,lvw:true,svh:true,svw:true,vmax:true,vmin:true,ch:true};function E(a,t,e,i){let r=new Map,s=[];return a.forEach((n,c)=>{let o=t(n),l=r.get(o);l===void 0?r.set(o,c):s.push({path:e(c),message:i(o,l,c)});}),s}function m(a){return a.variables.flatMap((t,e)=>[{path:`variables[${e}].value`,value:t.value,variableIndex:e},...Object.entries(t.modes??{}).map(([i,r])=>({path:`variables[${e}].modes.${i}`,value:r,variableIndex:e}))])}function M(a){let t=new Map;return a.variables.forEach((e,i)=>{t.has(e.id)||t.set(e.id,{variable:e,index:i});}),t}var _=50;function B(a){let t=M(a),e=new Map;for(let{value:o,variableIndex:l}of m(a)){let u=a.variables[l]?.id;if(u===void 0||t.get(u)?.index!==l)continue;let f=o.type==="ref"?o.value.variableId===u?[]:[o.value.variableId]:o.type==="raw"?y(o.value):[],g=e.get(u)??new Set;f.filter(d=>t.has(d)).forEach(d=>g.add(d)),e.set(u,g);}let i=[],r=new Set,s=new Map,n=false,c=o=>{let l=[],u=f=>{s.set(f,"visiting"),l.push({id:f,targets:(e.get(f)??new Set).values()});};for(u(o);l.length>0&&!n;){let f=l[l.length-1],g=f.targets.next();if(g.done){s.set(f.id,"done"),l.pop();continue}let d=g.value,b=s.get(d);if(b==="visiting"){let C=l.slice(l.findIndex($=>$.id===d)).map($=>$.id),I=[...C].sort().join(`
2
+ `);if(!r.has(I)){if(r.size===_){n=true,i.push({path:"variables",message:`More than ${_} circular references, the rest are not shown`});continue}r.add(I),i.push({path:`variables[${t.get(d)?.index}]`,message:`Circular reference: ${[...C,d].join(" \u2192 ")}`});}}else b===void 0&&u(d);}};for(let o of t.keys()){if(n)break;s.has(o)||c(o);}return i}var k=[({variables:a})=>a.flatMap((t,e)=>F.test(t.id)?[]:[{path:`variables[${e}].id`,message:`"${t.id}" is not a valid variable id (it must start with "--" and use only ASCII letters, digits, "-" and "_")`}]),({variables:a})=>E(a,t=>t.id,t=>`variables[${t}].id`,(t,e,i)=>`Duplicate variable id "${t}" at variables[${e}] and variables[${i}]`),({collections:a})=>a.flatMap((t,e)=>[...t.id===p?[{path:`collections[${e}].id`,message:`Collection id "${p}" is reserved`}]:x.test(t.id)?[]:[{path:`collections[${e}].id`,message:`"${t.id}" is not a valid CSS identifier`}],..."isDefault"in t?[{path:`collections[${e}].isDefault`,message:"Library collections cannot set isDefault"}]:[]]),({collections:a})=>E(a,t=>t.id,t=>`collections[${t}].id`,(t,e,i)=>`Duplicate collection id "${t}" at collections[${e}] and collections[${i}]`),({collections:a})=>a.flatMap((t,e)=>[...t.modes.flatMap((i,r)=>{let s=`collections[${e}].modes[${r}].id`;return i.id===p?[{path:s,message:`Mode id "${p}" is reserved`}]:x.test(i.id)?[]:[{path:s,message:`"${i.id}" is not a valid CSS identifier`}]}),...E(t.modes,i=>i.id,i=>`collections[${e}].modes[${i}].id`,(i,r,s)=>`Duplicate mode id "${i}" at modes[${r}] and modes[${s}] of collection "${t.id}"`)]),({collections:a,variables:t})=>{let e=[],i=(n,c)=>{let o=new Map,l=new Set;for(let{item:u,path:f}of n){if(l.has(u.id))continue;l.add(u.id);let g=u.name??u.id,d=v(g);if(d===""){e.push({path:f,message:`"${g}" has no characters usable in a CSS variable name`});continue}let b=o.get(d);b===void 0?o.set(d,{label:g,path:f}):e.push({path:f,message:`"${b.label}" at ${b.path} and "${g}" at ${f} both become "${d}" ${c}`});}},r=t.some(n=>!n.collectionId)?[{item:{id:p,name:S},path:"the implicit base collection"}]:[];i([...r,...a.map((n,c)=>({item:n,path:`collections[${c}]`}))],"in this library"),a.forEach((n,c)=>i(n.modes.map((o,l)=>({item:o,path:`collections[${c}].modes[${l}]`})),`in collection "${n.id}"`));let s=new Map;return t.forEach((n,c)=>{let o=n.collectionId??p,l=s.get(o)??[];l.push({item:n,path:`variables[${c}]`}),s.set(o,l);}),s.forEach((n,c)=>i(n,`in collection "${c}"`)),e},({collections:a,variables:t})=>{let e=new Map(a.map(i=>[i.id,new Set(i.modes.map(r=>r.id))]));return t.flatMap((i,r)=>{let s=i.collectionId===void 0?new Set:e.get(i.collectionId);return s===void 0?[{path:`variables[${r}].collectionId`,message:i.collectionId===p?`Collection id "${p}" is reserved; omit the id for the implicit base collection`:`Collection "${i.collectionId}" is not declared`}]:Object.keys(i.modes??{}).filter(n=>!s.has(n)).map(n=>({path:`variables[${r}].modes.${n}`,message:`Mode "${n}" is not declared in collection "${i.collectionId??p}"`}))})},a=>{let t=new Set(a.variables.map(e=>e.id));return m(a).flatMap(({path:e,value:i,variableIndex:r})=>{if(i.type!=="ref")return [];let s=i.value.variableId;return s===a.variables[r]?.id?[{path:e,message:`Variable "${s}" references itself`}]:t.has(s)?[]:[{path:e,message:`Referenced variable "${s}" does not exist`}]})},a=>{let t=new Set(a.variables.map(e=>e.id));return m(a).flatMap(({path:e,value:i})=>i.type!=="raw"?[]:y(i.value).filter(r=>!t.has(r)).map(r=>({path:e,message:`var(${r}) does not name a variable in this library`})))},a=>m(a).flatMap(({path:t,value:e})=>e.type!=="raw"?[]:w(e.value).map(i=>({path:t,message:`var(${i}, \u2026) has a fallback; library variables do not support var() fallbacks`}))),a=>m(a).flatMap(({path:t,value:e,variableIndex:i})=>{let r=a.variables[i]?.type;return e.type==="ref"||e.type==="raw"?[]:e.type===r?[]:[{path:t,message:`A "${e.type}" value does not match the variable type "${r}"`}]}),a=>m(a).flatMap(({path:t,value:e})=>e.type!=="color"?[]:V(e.value)?[]:[{path:t,message:`"${e.value}" is not a valid color`}]),a=>m(a).flatMap(({path:t,value:e})=>e.type!=="length"?[]:Object.hasOwn(O,e.value.unit)?[]:[{path:t,message:`"${e.value.unit}" is not a supported length unit`}]),a=>m(a).flatMap(({path:t,value:e})=>{if(e.type!=="number"&&e.type!=="percentage")return [];let i=e.type==="number"?"-":"%";return e.value.unit===i?[]:[{path:t,message:`A ${e.type} value must have unit "${i}", not "${e.value.unit}"`}]}),a=>{let t=M(a);return m(a).flatMap(({path:e,value:i,variableIndex:r})=>{if(i.type!=="ref")return [];let s=a.variables[r],n=t.get(i.value.variableId)?.variable;return s===void 0||n===void 0?[]:n.id===s.id?[]:n.type===s.type?[]:[{path:e,message:`"${s.id}" is a ${s.type} variable but references "${n.id}", a ${n.type} variable`}]})},B];function z(a){return k.flatMap(t=>t(a))}exports.RESERVED_BASE_COLLECTION_NAME=S;exports.RESERVED_BASE_ID=p;exports.WEBFLOW_COLLECTION_AT_RULE=N;exports.extractVarReferences=y;exports.sanitizeVariableName=v;exports.validateStyleVariableCatalog=z;
package/dist/index.d.ts CHANGED
@@ -20,13 +20,17 @@ type StyleVariableCatalogIssue = {
20
20
  * valid. Shared by the CLI (before share) and the server (on receive).
21
21
  *
22
22
  * The catalog must already match the `StyleVariableCatalog` shape: the server
23
- * parses the request body with its schema first. Color syntax is checked by
24
- * the server, not here.
23
+ * parses the request body with its schema first.
25
24
  */
26
25
  declare function validateStyleVariableCatalog(catalog: StyleVariableCatalog): StyleVariableCatalogIssue[];
27
26
 
28
27
  /** Id of the implicit collection. Reserved as a collection id and as a mode id. */
29
28
  declare const RESERVED_BASE_ID = "base";
29
+ /**
30
+ * Name Webflow gives the implicit collection. It is part of the CSS name of
31
+ * every variable in it, so no declared collection may sanitize to the same name.
32
+ */
33
+ declare const RESERVED_BASE_COLLECTION_NAME = "Base collection";
30
34
  /** PostCSS at-rule name, without the leading `@`. */
31
35
  declare const WEBFLOW_COLLECTION_AT_RULE = "webflow-collection";
32
36
 
@@ -38,4 +42,4 @@ declare const WEBFLOW_COLLECTION_AT_RULE = "webflow-collection";
38
42
  */
39
43
  declare function extractVarReferences(raw: string): string[];
40
44
 
41
- export { RESERVED_BASE_ID, type StyleVariableCatalogIssue, WEBFLOW_COLLECTION_AT_RULE, extractVarReferences, sanitizeVariableName, validateStyleVariableCatalog };
45
+ export { RESERVED_BASE_COLLECTION_NAME, RESERVED_BASE_ID, type StyleVariableCatalogIssue, WEBFLOW_COLLECTION_AT_RULE, extractVarReferences, sanitizeVariableName, validateStyleVariableCatalog };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var M=/\s/;function m(s){if(s===void 0)return false;let e=s.charCodeAt(0);return (e>=128||e>=97&&e<=122||e>=65&&e<=90||e>=48&&e<=57||s==="_")&&!M.test(s)}function v(s){let e=s.length,t="",a=0,r=e;for(;a<e&&!m(s[a]);a+=1);for(;r>=1&&!m(s[r-1]);r-=1);for(;a<r;a+=1){let i=s[a];if(i==="/"){for(t[t.length-1]==="-"&&(t=t.substring(0,t.length-1));a<r;a+=1)if(i=s[a],m(i)){t+="--"+i;break}}else m(i)?t+=i:t[t.length-1]!=="-"&&(t+="-");}return t.toLowerCase()}var g="base",_="webflow-collection";var R=/var\(\s*(--[^\s,)(]+)/gi,F=/var\(\s*(--[^\s,)(]+)\s*,/gi;function h(s){return [...s.matchAll(R)].map(e=>e[1]).filter(e=>e!==void 0)}function V(s){return [...s.matchAll(F)].map(e=>e[1]).filter(e=>e!==void 0)}var A=/^--[A-Za-z0-9_\-\u0080-\uFFFF]+$/,E=/^(?:--|-?[A-Za-z_\u0080-\uFFFF])[A-Za-z0-9_\-\u0080-\uFFFF]*$/,L={px:true,em:true,rem:true,vh:true,vw:true,dvh:true,dvw:true,lvh:true,lvw:true,svh:true,svw:true,vmax:true,vmin:true,ch:true};function $(s,e,t,a){let r=new Map,i=[];return s.forEach((n,d)=>{let l=e(n),o=r.get(l);o===void 0?r.set(l,d):i.push({path:t(d),message:a(l,o,d)});}),i}function b(s){return s.variables.flatMap((e,t)=>[{path:`variables[${t}].value`,value:e.value,variableIndex:t},...Object.entries(e.modes??{}).map(([a,r])=>({path:`variables[${t}].modes.${a}`,value:r,variableIndex:t}))])}function x(s){let e=new Map;return s.variables.forEach((t,a)=>{e.has(t.id)||e.set(t.id,{variable:t,index:a});}),e}var w=50;function T(s){let e=x(s),t=new Map;for(let{value:l,variableIndex:o}of b(s)){let c=s.variables[o]?.id;if(c===void 0||e.get(c)?.index!==o)continue;let u=l.type==="ref"?l.value.variableId===c?[]:[l.value.variableId]:l.type==="raw"?h(l.value):[],p=t.get(c)??new Set;u.filter(f=>e.has(f)).forEach(f=>p.add(f)),t.set(c,p);}let a=[],r=new Set,i=new Map,n=false,d=l=>{let o=[],c=u=>{i.set(u,"visiting"),o.push({id:u,targets:(t.get(u)??new Set).values()});};for(c(l);o.length>0&&!n;){let u=o[o.length-1],p=u.targets.next();if(p.done){i.set(u.id,"done"),o.pop();continue}let f=p.value,S=i.get(f);if(S==="visiting"){let C=o.slice(o.findIndex(y=>y.id===f)).map(y=>y.id),I=[...C].sort().join(`
2
- `);if(!r.has(I)){if(r.size===w){n=true,a.push({path:"variables",message:`More than ${w} circular references, the rest are not shown`});continue}r.add(I),a.push({path:`variables[${e.get(f)?.index}]`,message:`Circular reference: ${[...C,f].join(" \u2192 ")}`});}}else S===void 0&&c(f);}};for(let l of e.keys()){if(n)break;i.has(l)||d(l);}return a}var k=[({variables:s})=>s.flatMap((e,t)=>A.test(e.id)?[]:[{path:`variables[${t}].id`,message:`"${e.id}" is not a valid CSS custom property name (it must start with "--")`}]),({variables:s})=>$(s,e=>e.id,e=>`variables[${e}].id`,(e,t,a)=>`Duplicate variable id "${e}" at variables[${t}] and variables[${a}]`),({collections:s})=>s.flatMap((e,t)=>[...e.id===g?[{path:`collections[${t}].id`,message:`Collection id "${g}" is reserved`}]:E.test(e.id)?[]:[{path:`collections[${t}].id`,message:`"${e.id}" is not a valid CSS identifier`}],..."isDefault"in e?[{path:`collections[${t}].isDefault`,message:"Library collections cannot set isDefault"}]:[]]),({collections:s})=>$(s,e=>e.id,e=>`collections[${e}].id`,(e,t,a)=>`Duplicate collection id "${e}" at collections[${t}] and collections[${a}]`),({collections:s})=>s.flatMap((e,t)=>[...e.modes.flatMap((a,r)=>{let i=`collections[${t}].modes[${r}].id`;return a.id===g?[{path:i,message:`Mode id "${g}" is reserved`}]:E.test(a.id)?[]:[{path:i,message:`"${a.id}" is not a valid CSS identifier`}]}),...$(e.modes,a=>a.id,a=>`collections[${t}].modes[${a}].id`,(a,r,i)=>`Duplicate mode id "${a}" at modes[${r}] and modes[${i}] of collection "${e.id}"`)]),({collections:s,variables:e})=>{let t=[],a=(i,n)=>{let d=new Map,l=new Set;for(let{item:o,path:c}of i){if(l.has(o.id))continue;l.add(o.id);let u=o.name??o.id,p=v(u);if(p===""){t.push({path:c,message:`"${u}" has no characters usable in a CSS variable name`});continue}let f=d.get(p);f===void 0?d.set(p,{label:u,path:c}):t.push({path:c,message:`"${f.label}" at ${f.path} and "${u}" at ${c} both become "${p}" ${n}`});}};a(s.map((i,n)=>({item:i,path:`collections[${n}]`})),"in this library"),s.forEach((i,n)=>a(i.modes.map((d,l)=>({item:d,path:`collections[${n}].modes[${l}]`})),`in collection "${i.id}"`));let r=new Map;return e.forEach((i,n)=>{let d=i.collectionId??g,l=r.get(d)??[];l.push({item:i,path:`variables[${n}]`}),r.set(d,l);}),r.forEach((i,n)=>a(i,`in collection "${n}"`)),t},({collections:s,variables:e})=>{let t=new Map(s.map(a=>[a.id,new Set(a.modes.map(r=>r.id))]));return e.flatMap((a,r)=>{let i=a.collectionId===void 0?new Set:t.get(a.collectionId);return i===void 0?[{path:`variables[${r}].collectionId`,message:a.collectionId===g?`Collection id "${g}" is reserved; omit the id for the implicit base collection`:`Collection "${a.collectionId}" is not declared`}]:Object.keys(a.modes??{}).filter(n=>!i.has(n)).map(n=>({path:`variables[${r}].modes.${n}`,message:`Mode "${n}" is not declared in collection "${a.collectionId??g}"`}))})},s=>{let e=new Set(s.variables.map(t=>t.id));return b(s).flatMap(({path:t,value:a,variableIndex:r})=>{if(a.type!=="ref")return [];let i=a.value.variableId;return i===s.variables[r]?.id?[{path:t,message:`Variable "${i}" references itself`}]:e.has(i)?[]:[{path:t,message:`Referenced variable "${i}" does not exist`}]})},s=>{let e=new Set(s.variables.map(t=>t.id));return b(s).flatMap(({path:t,value:a})=>a.type!=="raw"?[]:h(a.value).filter(r=>!e.has(r)).map(r=>({path:t,message:`var(${r}) does not name a variable in this library`})))},s=>b(s).flatMap(({path:e,value:t})=>t.type!=="raw"?[]:V(t.value).map(a=>({path:e,message:`var(${a}, \u2026) has a fallback; library variables do not support var() fallbacks`}))),s=>b(s).flatMap(({path:e,value:t,variableIndex:a})=>{let r=s.variables[a]?.type;return t.type==="ref"||t.type==="raw"?[]:t.type===r?[]:[{path:e,message:`A "${t.type}" value does not match the variable type "${r}"`}]}),s=>b(s).flatMap(({path:e,value:t})=>t.type!=="length"?[]:Object.hasOwn(L,t.value.unit)?[]:[{path:e,message:`"${t.value.unit}" is not a supported length unit`}]),s=>{let e=x(s);return b(s).flatMap(({path:t,value:a,variableIndex:r})=>{if(a.type!=="ref")return [];let i=s.variables[r],n=e.get(a.value.variableId)?.variable;return i===void 0||n===void 0?[]:n.id===i.id?[]:n.type===i.type?[]:[{path:t,message:`"${i.id}" is a ${i.type} variable but references "${n.id}", a ${n.type} variable`}]})},T];function D(s){return k.flatMap(e=>e(s))}export{g as RESERVED_BASE_ID,_ as WEBFLOW_COLLECTION_AT_RULE,h as extractVarReferences,v as sanitizeVariableName,D as validateStyleVariableCatalog};
1
+ import R from'tinycolor2';var A=/\s/;function h(a){if(a===void 0)return false;let t=a.charCodeAt(0);return (t>=128||t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||a==="_")&&!A.test(a)}function v(a){let t=a.length,e="",i=0,r=t;for(;i<t&&!h(a[i]);i+=1);for(;r>=1&&!h(a[r-1]);r-=1);for(;i<r;i+=1){let s=a[i];if(s==="/"){for(e[e.length-1]==="-"&&(e=e.substring(0,e.length-1));i<r;i+=1)if(s=a[i],h(s)){e+="--"+s;break}}else h(s)?e+=s:e[e.length-1]!=="-"&&(e+="-");}return e.toLowerCase()}function L(a){let t=a.toLowerCase().trim();if(!/^rgba?\([^)]+\)$/.test(t))return a;let e=t.split(/[,()]/).map(s=>s.trim()).filter(s=>s!==""&&!Number.isNaN(Number(s)));if(e.length<3)return a;e[3]=e[3]||"1";let i=parseFloat(e[3]),r=!Number.isNaN(i)&&i<1;return r||e.pop(),`${r?"rgba":"rgb"}(${e.join(", ")})`}function V(a){return R(L(a)).isValid()}var p="base",S="Base collection",N="webflow-collection";var D=/var\(\s*(--[^\s,)(]+)/gi,T=/var\(\s*(--[^\s,)(]+)\s*,/gi;function y(a){return [...a.matchAll(D)].map(t=>t[1]).filter(t=>t!==void 0)}function w(a){return [...a.matchAll(T)].map(t=>t[1]).filter(t=>t!==void 0)}var F=/^--[A-Za-z0-9_-]+$/,x=/^(?:--|-?[A-Za-z_\u0080-\uFFFF])[A-Za-z0-9_\-\u0080-\uFFFF]*$/,O={px:true,em:true,rem:true,vh:true,vw:true,dvh:true,dvw:true,lvh:true,lvw:true,svh:true,svw:true,vmax:true,vmin:true,ch:true};function E(a,t,e,i){let r=new Map,s=[];return a.forEach((n,c)=>{let o=t(n),l=r.get(o);l===void 0?r.set(o,c):s.push({path:e(c),message:i(o,l,c)});}),s}function m(a){return a.variables.flatMap((t,e)=>[{path:`variables[${e}].value`,value:t.value,variableIndex:e},...Object.entries(t.modes??{}).map(([i,r])=>({path:`variables[${e}].modes.${i}`,value:r,variableIndex:e}))])}function M(a){let t=new Map;return a.variables.forEach((e,i)=>{t.has(e.id)||t.set(e.id,{variable:e,index:i});}),t}var _=50;function B(a){let t=M(a),e=new Map;for(let{value:o,variableIndex:l}of m(a)){let u=a.variables[l]?.id;if(u===void 0||t.get(u)?.index!==l)continue;let f=o.type==="ref"?o.value.variableId===u?[]:[o.value.variableId]:o.type==="raw"?y(o.value):[],g=e.get(u)??new Set;f.filter(d=>t.has(d)).forEach(d=>g.add(d)),e.set(u,g);}let i=[],r=new Set,s=new Map,n=false,c=o=>{let l=[],u=f=>{s.set(f,"visiting"),l.push({id:f,targets:(e.get(f)??new Set).values()});};for(u(o);l.length>0&&!n;){let f=l[l.length-1],g=f.targets.next();if(g.done){s.set(f.id,"done"),l.pop();continue}let d=g.value,b=s.get(d);if(b==="visiting"){let C=l.slice(l.findIndex($=>$.id===d)).map($=>$.id),I=[...C].sort().join(`
2
+ `);if(!r.has(I)){if(r.size===_){n=true,i.push({path:"variables",message:`More than ${_} circular references, the rest are not shown`});continue}r.add(I),i.push({path:`variables[${t.get(d)?.index}]`,message:`Circular reference: ${[...C,d].join(" \u2192 ")}`});}}else b===void 0&&u(d);}};for(let o of t.keys()){if(n)break;s.has(o)||c(o);}return i}var k=[({variables:a})=>a.flatMap((t,e)=>F.test(t.id)?[]:[{path:`variables[${e}].id`,message:`"${t.id}" is not a valid variable id (it must start with "--" and use only ASCII letters, digits, "-" and "_")`}]),({variables:a})=>E(a,t=>t.id,t=>`variables[${t}].id`,(t,e,i)=>`Duplicate variable id "${t}" at variables[${e}] and variables[${i}]`),({collections:a})=>a.flatMap((t,e)=>[...t.id===p?[{path:`collections[${e}].id`,message:`Collection id "${p}" is reserved`}]:x.test(t.id)?[]:[{path:`collections[${e}].id`,message:`"${t.id}" is not a valid CSS identifier`}],..."isDefault"in t?[{path:`collections[${e}].isDefault`,message:"Library collections cannot set isDefault"}]:[]]),({collections:a})=>E(a,t=>t.id,t=>`collections[${t}].id`,(t,e,i)=>`Duplicate collection id "${t}" at collections[${e}] and collections[${i}]`),({collections:a})=>a.flatMap((t,e)=>[...t.modes.flatMap((i,r)=>{let s=`collections[${e}].modes[${r}].id`;return i.id===p?[{path:s,message:`Mode id "${p}" is reserved`}]:x.test(i.id)?[]:[{path:s,message:`"${i.id}" is not a valid CSS identifier`}]}),...E(t.modes,i=>i.id,i=>`collections[${e}].modes[${i}].id`,(i,r,s)=>`Duplicate mode id "${i}" at modes[${r}] and modes[${s}] of collection "${t.id}"`)]),({collections:a,variables:t})=>{let e=[],i=(n,c)=>{let o=new Map,l=new Set;for(let{item:u,path:f}of n){if(l.has(u.id))continue;l.add(u.id);let g=u.name??u.id,d=v(g);if(d===""){e.push({path:f,message:`"${g}" has no characters usable in a CSS variable name`});continue}let b=o.get(d);b===void 0?o.set(d,{label:g,path:f}):e.push({path:f,message:`"${b.label}" at ${b.path} and "${g}" at ${f} both become "${d}" ${c}`});}},r=t.some(n=>!n.collectionId)?[{item:{id:p,name:S},path:"the implicit base collection"}]:[];i([...r,...a.map((n,c)=>({item:n,path:`collections[${c}]`}))],"in this library"),a.forEach((n,c)=>i(n.modes.map((o,l)=>({item:o,path:`collections[${c}].modes[${l}]`})),`in collection "${n.id}"`));let s=new Map;return t.forEach((n,c)=>{let o=n.collectionId??p,l=s.get(o)??[];l.push({item:n,path:`variables[${c}]`}),s.set(o,l);}),s.forEach((n,c)=>i(n,`in collection "${c}"`)),e},({collections:a,variables:t})=>{let e=new Map(a.map(i=>[i.id,new Set(i.modes.map(r=>r.id))]));return t.flatMap((i,r)=>{let s=i.collectionId===void 0?new Set:e.get(i.collectionId);return s===void 0?[{path:`variables[${r}].collectionId`,message:i.collectionId===p?`Collection id "${p}" is reserved; omit the id for the implicit base collection`:`Collection "${i.collectionId}" is not declared`}]:Object.keys(i.modes??{}).filter(n=>!s.has(n)).map(n=>({path:`variables[${r}].modes.${n}`,message:`Mode "${n}" is not declared in collection "${i.collectionId??p}"`}))})},a=>{let t=new Set(a.variables.map(e=>e.id));return m(a).flatMap(({path:e,value:i,variableIndex:r})=>{if(i.type!=="ref")return [];let s=i.value.variableId;return s===a.variables[r]?.id?[{path:e,message:`Variable "${s}" references itself`}]:t.has(s)?[]:[{path:e,message:`Referenced variable "${s}" does not exist`}]})},a=>{let t=new Set(a.variables.map(e=>e.id));return m(a).flatMap(({path:e,value:i})=>i.type!=="raw"?[]:y(i.value).filter(r=>!t.has(r)).map(r=>({path:e,message:`var(${r}) does not name a variable in this library`})))},a=>m(a).flatMap(({path:t,value:e})=>e.type!=="raw"?[]:w(e.value).map(i=>({path:t,message:`var(${i}, \u2026) has a fallback; library variables do not support var() fallbacks`}))),a=>m(a).flatMap(({path:t,value:e,variableIndex:i})=>{let r=a.variables[i]?.type;return e.type==="ref"||e.type==="raw"?[]:e.type===r?[]:[{path:t,message:`A "${e.type}" value does not match the variable type "${r}"`}]}),a=>m(a).flatMap(({path:t,value:e})=>e.type!=="color"?[]:V(e.value)?[]:[{path:t,message:`"${e.value}" is not a valid color`}]),a=>m(a).flatMap(({path:t,value:e})=>e.type!=="length"?[]:Object.hasOwn(O,e.value.unit)?[]:[{path:t,message:`"${e.value.unit}" is not a supported length unit`}]),a=>m(a).flatMap(({path:t,value:e})=>{if(e.type!=="number"&&e.type!=="percentage")return [];let i=e.type==="number"?"-":"%";return e.value.unit===i?[]:[{path:t,message:`A ${e.type} value must have unit "${i}", not "${e.value.unit}"`}]}),a=>{let t=M(a);return m(a).flatMap(({path:e,value:i,variableIndex:r})=>{if(i.type!=="ref")return [];let s=a.variables[r],n=t.get(i.value.variableId)?.variable;return s===void 0||n===void 0?[]:n.id===s.id?[]:n.type===s.type?[]:[{path:e,message:`"${s.id}" is a ${s.type} variable but references "${n.id}", a ${n.type} variable`}]})},B];function z(a){return k.flatMap(t=>t(a))}export{S as RESERVED_BASE_COLLECTION_NAME,p as RESERVED_BASE_ID,N as WEBFLOW_COLLECTION_AT_RULE,y as extractVarReferences,v as sanitizeVariableName,z as validateStyleVariableCatalog};
@@ -0,0 +1 @@
1
+ 'use strict';var tn=require('postcss'),H=require('postcss-value-parser'),Ue=require('tinycolor2'),fs=require('fs'),path=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var tn__default=/*#__PURE__*/_interopDefault(tn);var H__default=/*#__PURE__*/_interopDefault(H);var Ue__default=/*#__PURE__*/_interopDefault(Ue);var O="base";var v="webflow-collection";var Pe=/\s/;function q(t){if(t===void 0)return false;let s=t.charCodeAt(0);return (s>=128||s>=97&&s<=122||s>=65&&s<=90||s>=48&&s<=57||t==="_")&&!Pe.test(t)}function ue(t){let s=t.length,i="",d=0,a=s;for(;d<s&&!q(t[d]);d+=1);for(;a>=1&&!q(t[a-1]);a-=1);for(;d<a;d+=1){let f=t[d];if(f==="/"){for(i[i.length-1]==="-"&&(i=i.substring(0,i.length-1));d<a;d+=1)if(f=t[d],q(f)){i+="--"+f;break}}else q(f)?i+=f:i[i.length-1]!=="-"&&(i+="-");}return i.toLowerCase()}function We(t){let s=t.toLowerCase().trim();if(!/^rgba?\([^)]+\)$/.test(s))return t;let i=s.split(/[,()]/).map(f=>f.trim()).filter(f=>f!==""&&!Number.isNaN(Number(f)));if(i.length<3)return t;i[3]=i[3]||"1";let d=parseFloat(i[3]),a=!Number.isNaN(d)&&d<1;return a||i.pop(),`${a?"rgba":"rgb"}(${i.join(", ")})`}function fe(t){return Ue__default.default(We(t)).isValid()}var qe=new Set("aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato transparent turquoise violet wheat white whitesmoke yellow yellowgreen".split(" ")),Be=/^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i,N=String.raw`[+-]?(?:\d+\.?\d*|\.\d+)`,Fe=new RegExp(`^${N}%?\\s*,\\s*${N}%?\\s*,\\s*${N}%?(?:\\s*,\\s*${N}%?)?$`),ze=new RegExp(`^${N}%?(?:deg|grad|rad|turn)?\\s+${N}%?\\s+${N}%?(?:\\s*/\\s*${N}%?)?$`),je=/^(rgba?|hsla?)\(([^()]*)\)$/i;function B(t){let s=t.trim();if(Be.test(s)||qe.has(s.toLowerCase()))return true;let i=je.exec(s);if(i===null)return false;let d=i[2].trim();return Fe.test(d)||ze.test(d)}var Y=new Set(["oklch","oklab","lab","lch","hwb","color","color-mix"]),pe=new Set(["rgb","rgba","hsl","hsla"]);var K=["number","length","percentage"],Ge=new Set(["px","em","rem","vh","vw","dvh","dvw","lvh","lvw","svh","svw","vmax","vmin","ch"]),ge=new Set(["deg","grad","rad","turn","s","ms","hz","khz","dpi","dpcm","dppx","x","fr"]),me=new Set(["","calc","clamp","min","max","abs","sign","round","mod","rem","sin","cos","tan","asin","acos","atan","atan2","pow","sqrt","hypot","log","exp"]),Ye=new Set(["pi","e","infinity","-infinity","nan"]),He=new Set(["+","-","*","/"]),Ke=new Set(["nearest","up","down","to-zero"]),Xe=new Set(["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","emoji","math","fangsong"]),ye=new Set(["auto","none","normal","inherit","initial","unset","revert","revert-layer","currentcolor","min-content","max-content","fit-content","inline","block","flex","grid","hidden","visible","bold","italic"]),X=/^-?[A-Za-z_\u0080-￿][\w\u0080-￿-]*$/,_="has no matching Webflow variable type (a color, length, number, percentage or font family)",F=t=>t.filter(s=>s.type!=="space"&&s.type!=="comment");function D(t,s=[]){return {error:t,warnings:s}}function x(t,s=[]){return {unsupported:t,warnings:s}}function be(t){return `"${t}" is unquoted, so it can be a font family or a keyword; quote it ("${t}") or add type: "font-family"`}function w(t,s=[]){return {inferred:t,warnings:s}}function he(t){let s=H__default.default.unit(t);return s===false?void 0:{number:parseFloat(s.number),unit:s.unit.toLowerCase()}}function ve(t,s,i){for(let d of t)if(d.type==="function"){if(d.value.toLowerCase()==="var"){let a=F(d.nodes),f=a[0]?.type==="word"?a[0].value:void 0;f?.startsWith("--")&&(s.push(f),a.length>1&&i.push(f));}ve(d.nodes,s,i);}}function Ze(t,s){let i=F(t.nodes),d=i[0]?.type==="word"?i[0].value:void 0;return d===void 0||!d.startsWith("--")?D(`var() must name a custom property, e.g. var(--brand), not "${H__default.default.stringify(t)}"`):(i.length>1&&s.push(`The fallback of var(${d}, \u2026) is dropped: Webflow aliases ${d} without one`),w({value:{type:"ref",value:{variableId:d}},operands:[d]},s))}function Je(t,s,i){let d={length:false,percentage:false},a=[],f,g=false,h=V=>{for(let $ of V){if(f!==void 0)return;if($.type==="word"){let L=$.value;if(He.has(L)||Ke.has(L.toLowerCase())||Ye.has(L.toLowerCase()))continue;let C=he(L);C===void 0?f=`"${L}" is a keyword or unsupported token; ${ye.has(L.toLowerCase())?"keywords are not supported":"only numbers, dimensions and var() are supported"} in a math expression`:C.unit==="%"?d.percentage=true:C.unit!==""&&(ge.has(C.unit)?(f=`"${L}" ${_}`,g=true):d.length=true);}else if($.type==="string")f=`A string in a math expression ${_}`,g=true;else if($.type==="function"){let L=$.value.toLowerCase();if(L==="var"){let C=F($.nodes),p=C[0]?.type==="word"?C[0].value:void 0;p===void 0||!p.startsWith("--")?f="var() must name a custom property, e.g. var(--brand)":C.length>1?f=`var(${p}, \u2026) has a fallback; use var(${p}) without one inside an expression`:a.push(p);}else me.has(L)?h($.nodes):(f=`${L}() inside a math expression ${_}`,g=true);}}};return h(t.nodes),f!==void 0?g?x(f,i):D(f,i):w({value:{type:"raw",value:s},math:d,operands:a},i)}function Qe(t,s){let i=t.value.toLowerCase(),d=[],a=[];return ve(t.nodes,d,a),a.length>0?D(`var(${a[0]}, \u2026) has a fallback; use var(${a[0]}) without one inside an expression`):Y.has(i)||d.length>0?w({value:{type:"raw",value:s},type:"color",operands:d}):w({value:B(s)&&fe(s)?{type:"color",value:s}:{type:"raw",value:s},type:"color",operands:d})}function en(t,s){let i=t.toLowerCase();if(t.startsWith("#"))return B(t)?w({value:{type:"color",value:t},type:"color",operands:[]}):D(`"${t}" is not a valid color`);let d=he(t);if(d!==void 0){let{number:a,unit:f}=d;return f===""?w({value:{type:"number",value:{value:a,unit:"-"}},type:"number",operands:[],zero:a===0}):f==="%"?w({value:{type:"percentage",value:{value:a,unit:"%"}},type:"percentage",operands:[]}):Ge.has(f)?w({value:{type:"length",value:{value:a,unit:f}},type:"length",operands:[]}):ge.has(f)?x(`"${t}" ${_}`):w({value:{type:"raw",value:t},type:"length",operands:[]})}return Xe.has(i)?w({value:{type:"font-family",value:t},type:"font-family",operands:[]}):B(t)?w({value:{type:"color",value:t},type:"color",operands:[]}):ye.has(i)?x(`"${t}" is a keyword; keywords are not supported as variable values`):s&&X.test(t)?w({value:{type:"font-family",value:t},type:"font-family",operands:[]}):x(be(t))}function nn(t,s){let i=[[]];for(let a of t)a.type==="div"&&a.value===","?i.push([]):i[i.length-1].push(a);return i.every(a=>a.length>0&&(a.length===1&&a[0].type==="string"?true:a.every(f=>f.type==="word"&&X.test(f.value))))?w({value:{type:"font-family",value:s},type:"font-family",operands:[]}):x(`"${s}" ${_}`)}function $e(t,{type:s}={}){let i=t.trim(),d=[],a=F(H__default.default(i).nodes);if(a.length===0)return D("the value is empty");if(a.length===1){let g=a[0];if(g.type==="string")return w({value:{type:"font-family",value:i},type:"font-family",operands:[]});if(g.type==="word")return en(g.value,s==="font-family");if(g.type==="function"){let h=g.value.toLowerCase();if(h==="var")return Ze(g,d);if(me.has(h)&&h!=="")return Je(g,i,d);if(pe.has(h)||Y.has(h))return Qe(g,i)}return x(`"${i}" ${_}`)}return a.some(g=>g.type==="div"&&g.value===",")?nn(a,i):a.every(g=>g.type==="word"&&X.test(g.value))?s==="font-family"?w({value:{type:"font-family",value:i},type:"font-family",operands:[]}):x(be(i)):x(`"${i}" ${_}`)}function Z(t,s){if(t.zero)return [...K];if(t.type!==void 0)return [t.type];let i=t.operands.map(s);if(i.some(a=>a===void 0))return;if(t.math===void 0)return [i[0]];let d=i.find(a=>a==="color"||a==="font-family");return d!==void 0?{error:`A ${d} variable cannot be used in a math expression`}:t.math.length||i.includes("length")?["length"]:t.math.percentage||i.includes("percentage")?["percentage"]:["number"]}function J(t,s){return t.zero?s==="length"?{type:"length",value:{value:0,unit:"px"}}:s==="percentage"?{type:"percentage",value:{value:0,unit:"%"}}:t.value:t.value}var R="mode",S="variable",ee="Base",M=[":root",":host"],Se=["color","length","number","percentage","font-family"],Le=new Map([["selector",[v,R]],["label",[S]],["type",[S]]]),T=t=>`${t.file}:${t.line}:${t.column}`,Re=(t,s)=>`Add type: "${s}" to @${S} ${t}`,Ce=t=>t.filter(s=>s.type!=="space"&&s.type!=="comment"),P=t=>{let s=t.trim().replace(/\s+/g," ").replace(/\s*,\s*/g,", ").replace(/'/g,'"'),i="",d=0,a=false;for(let f of s)f==='"'?a=!a:!a&&(f==="["||f==="(")?d++:!a&&(f==="]"||f===")")&&d--,!a&&d===0&&">+~".includes(f)?i=`${i.trimEnd()} ${f} `:f===" "&&i.endsWith(" ")||(i+=f);return i.trim()},Q=t=>t.length<2?t.join(""):`${t.slice(0,-1).join(", ")} or ${t[t.length-1]}`;function on(t){let s=[],i=new Map,d=new Map,a=new Set,f=new Set,g=new Set,h=new Map,V=new Map,$=new Map,L=0,C=(e,n,r)=>s.push({severity:e,message:r,file:n.file,line:n.line,column:n.column}),p=(e,n)=>C("error",e,n),I=(e,n)=>C("warning",e,n),k=(e,n)=>({file:n,line:e.source?.start?.line??1,column:e.source?.start?.column??1});function ne(e,n,r,o){n!==void 0&&(e.label===void 0?(e.label=n,e.labelLoc=r):e.label!==n&&p(r,`${o} has conflicting labels "${e.label}" (${T(e.labelLoc)}) and "${n}" (${T(r)})`));}function Ee(e,n,r,o){e.selector===void 0?(e.selector=n,e.selectorLoc=r):P(e.selector)!==P(n)&&p(r,`${o} has conflicting selectors "${e.selector}" (${T(e.selectorLoc)}) and "${n}" (${T(r)})`);}function Ne(e,n){let r=i.get(e);return r===void 0&&(r={id:e,loc:n,modes:new Map},i.set(e,r)),r}function te(e){let n=Ce(H__default.default(e.params).nodes),[r,o]=n;if(n.length===0)return {};if(!(r?.type!=="word"||n.length>2||o!==void 0&&o.type!=="string"))return {id:r.value,label:o?.value}}function z(e,n,r){let o=e.prop.toLowerCase(),l=Le.get(o);if(l===void 0){let c=[...Le].filter(([,u])=>u.includes(n)).map(([u])=>u).join(", ");p(r,`Unknown descriptor "${e.prop}" in @${n}; expected ${c}`);}else if(!l.includes(n))p(r,`"${o}" is not a descriptor of @${n}; it belongs in ${l.map(c=>`@${c}`).join(" or ")}`);else if(e.important)p(r,`${o}: !important is not supported on a descriptor`);else return o}function j(e){let n=Ce(H__default.default(e.value).nodes);return n.length===1&&n[0].type==="string"?n[0].value:void 0}function oe(e,n,r,o){let l=j(e);if(l===void 0||l.trim()===""){let c=e.value.trim().replace(/^(["'])(.*)\1$/,"$2"),u=c.includes('"')?"'":'"';return p(o,c===""?'selector needs a quoted selector string, e.g. selector: ":root"':`selector must be a quoted string; use selector: ${u}${c}${u}`)}Ee(n,l,o,r);}function xe(e,n,r){let o=k(e,r),l=e.params.trim();if(!/^--[\w\u0080-\uffff-]+$/.test(l))return p(o,`@${S} needs a custom property name, e.g. @${S} --brand`);let c,u,m=new Set;for(let y of e.nodes??[]){if(y.type==="comment")continue;if(y.type!=="decl"){p(k(y,r),`@${S} can hold only descriptors`);continue}let E=k(y,r),A=z(y,S,E);if(A!==void 0){if(m.has(A)){p(E,`Duplicate descriptor "${A}" in @${S} ${l}`);continue}if(m.add(A),A==="label")c=j(y),c===void 0&&p(E,'label must be a quoted string, e.g. label: "color/brand"');else {let de=j(y)??y.value.trim();u=Se.find(Me=>Me===de.toLowerCase()),u===void 0&&p(E,`Unknown type "${de}"; expected ${Se.join(", ")}`);}}}let b=d.get(l);if(b!==void 0)return p(o,`${l} is defined twice: ${T(b.loc)} and ${T(o)}`);d.set(l,{id:l,label:c??l.slice(2),type:u,loc:o,collection:n});}function Ie(e,n,r){let o=k(e,r);if(n.id===void 0)return p(o,`The base collection cannot have modes; give the collection an id with @${v} <id>`);let l=te(e);if(l?.id===void 0)return p(o,`@${R} needs a mode id, e.g. @${R} dark "Dark"`);if(e.nodes===void 0)return p(o,`@${R} needs a block with a selector, e.g. @${R} dark "Dark" { selector: "[data-theme='dark']"; }`);let c=l.id;if(c===O)return p(o,`Mode id "${O}" is reserved`);let u=n.modes.get(c);u===void 0&&(u={loc:o},n.modes.set(c,u));let m=`Mode "${c}" of collection "${n.id}"`;ne(u,l.label,o,m);for(let b of e.nodes){if(b.type==="comment")continue;if(b.type!=="decl"){p(k(b,r),`@${R} can hold only descriptors`);continue}let y=k(b,r);if(b.prop.startsWith("--")){p(y,`${b.prop}: values don't go in @${R}; declare it in a top-level rule with the mode's selector`);continue}z(b,R,y)==="selector"&&(g.add(u),oe(b,u,m,y));}}function Ae(e,n){let r=k(e,n),o=te(e);if(o===void 0)return p(r,`Invalid @${v} prelude "${e.params}"; expected an id and an optional quoted label: @${v} colors "Colors"`);if(e.nodes===void 0)return p(r,`@${v} needs a block with @${S} rules`);let l=o.id===void 0||o.id===O,c=Ne(l?void 0:o.id,r);l?o.label!==void 0&&o.label!==ee&&p(r,`The base collection is always named "${ee}"; remove the label "${o.label}"`):ne(c,o.label,r,`Collection "${o.id}"`);for(let u of e.nodes){if(u.type==="comment")continue;let m=k(u,n);if(u.type==="decl")u.prop.startsWith("--")?p(m,`${u.prop} can't be declared in @${v}; export it with @${S} ${u.prop} and declare its value in a top-level rule`):z(u,v,m)==="selector"&&oe(u,c,`Collection "${c.id??O}"`,m);else if(u.type==="atrule"){let b=u.name.toLowerCase();b===R?Ie(u,c,n):b===S?xe(u,c,n):b===v?p(m,`@${v} must be at the top level of a stylesheet`):p(m,`@${v} can hold only selector, @${R} and @${S}`);}else p(m,`@${v} can hold only selector, @${R} and @${S}`);}}function re(e,n,r){let o=new Set([e.selector,...e.selectors].map(P));e.each(l=>{if(l.type!=="decl"||!l.prop.startsWith("--"))return;let c={value:l.value,important:l.important===true,loc:k(l,n),order:L++};for(let u of o){let m=r.get(u)??new Map;m.set(l.prop,[...m.get(l.prop)??[],c]),r.set(u,m);}});}function Oe(e,n){e.each(r=>{r.type==="rule"?re(r,n,V):r.type==="atrule"&&r.name.toLowerCase()!==v&&r.walkRules(o=>re(o,n,$));});}function _e({file:e,css:n}){let r;try{r=tn__default.default.parse(n,{from:e});}catch(l){let c=l;p({file:e,line:c.line??1,column:c.column??1},c.reason??String(l));return}Oe(r,e);let o=new Set;r.walkAtRules(l=>{let c=l.name.toLowerCase();if(c!==v&&c!==R&&c!==S)return;for(let m=l.parent;m;m=m.parent)if(o.has(m))return;o.add(l);let u=k(l,e);c===v&&l.parent?.type==="root"?Ae(l,e):c===v?p(u,`@${v} must be at the top level of a stylesheet, not inside a rule or at-rule such as @media, @layer or @supports`):p(u,`@${c} must be directly inside @${v}`);});}t.forEach(_e);for(let e of i.values())for(let[n,r]of e.modes)g.has(r)||p(r.loc,`@${R} ${n} needs a selector, e.g. selector: "[data-theme='${n}']"`);function U(e,n,r=V){let o=new Set;for(let l of e)r.get(P(l))?.get(n)?.forEach(c=>o.add(c));return [...o].sort((l,c)=>l.order-c.order)}function ie(e,n,r){let o=U(n,e),l=o[o.length-1];if(l!==void 0&&o.length>1){let c=o.every(u=>u.loc.file===l.loc.file);I(l.loc,`${e} is declared more than once on ${r} (${o.map(u=>c?`${u.loc.line}:${u.loc.column}`:T(u.loc)).join(", ")}); the last declaration is used`);}return l}let ae=(e,n,r)=>{let o=$e(n.value,{type:r});return o.warnings.forEach(l=>I(n.loc,`${e}: ${l}`)),o};for(let e of d.values()){let{id:n,collection:r}=e,o=r.selector,l=o??M.join(" or ");if(o!==void 0&&!M.includes(P(o)))for(let y of U(M,n))I(y.loc,`${n} is declared on :root or :host, but collection "${r.id??O}" reads its values from ${o}; this declaration is ignored`);let c=ie(n,o?[o]:M,l);if(c===void 0){a.add(n);let[y]=U(o?[o]:M,n,$);p(e.loc,`${n} is exported but not declared on ${l}${y?`. It is declared inside an at-rule (${T(y.loc)}), and declarations inside @media, @layer or @supports are not read`:""}`);continue}if(c.important){a.add(n),p(c.loc,`${n}: !important is not supported on a variable value`);continue}let{inferred:u,error:m,unsupported:b}=ae(n,c,e.type);u!==void 0?h.set(n,{inferred:u,text:c.value.trim(),loc:c.loc}):m!==void 0?(a.add(n),p(c.loc,`${n}: ${m}`)):e.type!==void 0?(a.add(n),p(c.loc,`${n} has type: ${e.type}, but ${b}`)):(f.add(n),I(c.loc,`${n}: ${b}. It is left out of the catalog (code-only).`));}let se=(e,n)=>{let r=e.operands.filter(l=>!d.has(l)||f.has(l));if(r.length===0)return true;let o=r.find(l=>!a.has(l));return o!==void 0&&p(n,f.has(o)?`var(${o}) refers to a variable that is left out of the catalog (code-only)`:`var(${o}) is not a library variable; var() can only reference variables exported with @${S} in @${v} blocks`),false};function De(e,n,r){let{id:o,type:l}=e;if(r.length===1){let[c]=r;if(l!==void 0&&l!==c){p(n.loc,`${o} has type: ${l}, but its value ${n.text} is a ${c}`);return}return c}if(l===void 0)return I(n.loc,`${o}: ${n.text} can be a ${Q(r)}. Using number. ${Re(o,"<type>")} to choose.`),"number";if(r.includes(l))return l;p(n.loc,`${o} has type: ${l}, but its value ${n.text} can only be a ${Q(r)}`);}let le=new Map,W=[];function G(e){let n=le.get(e);if(n!==void 0)return n??void 0;let r=d.get(e),o=h.get(e);if(r===void 0||o===void 0)return;let l=W.indexOf(e);if(l!==-1){p(r.loc,`Circular reference: ${[...W.slice(l),e].join(" \u2192 ")}`);return}W.push(e);let c=se(o.inferred,o.loc)?Z(o.inferred,G):void 0;W.pop();let u;return c!==void 0&&!Array.isArray(c)?p(o.loc,`${e}: ${c.error}`):c!==void 0&&(u=De(r,o,c)),le.set(e,u??null),u}let ce=[];for(let e of d.values()){let n=G(e.id),r=h.get(e.id);if(n===void 0||r===void 0)continue;let o={};for(let[l,c]of e.collection.modes){if(c.selector===void 0)continue;let u=ie(e.id,[c.selector],c.selector);if(u===void 0){let[E]=U([c.selector],e.id,$);E!==void 0&&I(E.loc,`${e.id} in mode "${l}" (${c.selector}) is declared only inside an at-rule. Declarations inside @media, @layer or @supports are not read, so the mode uses the base value.`);continue}if(u.important){p(u.loc,`${e.id}: !important is not supported on a variable value`);continue}let m=(E,A="")=>I(u.loc,`${e.id} in mode "${l}" (${c.selector}, ${T(u.loc)})${E}. The mode value is ignored, and the mode uses the base value.${A}`),b=ae(e.id,u,n);if(b.error!==void 0){p(u.loc,`${e.id}: ${b.error}`);continue}if(b.inferred===void 0){m(`: ${b.unsupported}`);continue}if(!se(b.inferred,u.loc))continue;let y=Z(b.inferred,G);y!==void 0&&(Array.isArray(y)?y.includes(n)?o[l]=J(b.inferred,n):m(` ${y.length===1?"is":"can be"} a ${Q(y)}, but its base value is a ${n}`,r.inferred.zero&&y.length===1&&K.includes(y[0])?` ${Re(e.id,y[0])} to use the mode value.`:""):p(u.loc,`${e.id}: ${y.error}`));}ce.push({id:e.id,name:e.label,type:n,...e.collection.id===void 0?{}:{collectionId:e.collection.id},value:J(r.inferred,n),...Object.keys(o).length>0?{modes:o}:{}});}return rn(i,d,p),{catalog:{collections:[...i.values()].filter(e=>e.id!==void 0&&Te(e,d)).map(e=>({id:e.id,...e.label===void 0?{}:{name:e.label},modes:[...e.modes].map(([n,r])=>({id:n,...r.label===void 0?{}:{name:r.label}}))})),variables:ce},diagnostics:s}}function rn(t,s,i){let d=(a,f)=>{let g=new Map;for(let h of a){let V=ue(h.label);if(V===""){i(h.loc,`"${h.label}" has no characters usable in a CSS variable name`);continue}let $=g.get(V);$===void 0?g.set(V,h):i(h.loc,`"${$.label}" (${T($.loc)}) and "${h.label}" (${T(h.loc)}) both become "${V}" ${f}`);}};d([...t.values()].filter(a=>a.id!==void 0||Te(a,s)).map(a=>({label:a.label??a.id??ee,loc:a.labelLoc??a.loc})),"in this library");for(let a of t.values()){let f=`in collection "${a.id??O}"`;d([...a.modes].map(([g,h])=>({label:h.label??g,loc:h.labelLoc??h.loc})),f),d([...s.values()].filter(g=>g.collection===a).map(g=>({label:g.label,loc:g.loc})),f);}}function Te(t,s){return [...s.values()].some(i=>i.collection===t)}var ln=new RegExp(`^${v}$`,"i");function ke(t){try{return fs.realpathSync.native(t)}catch{return path.resolve(t)}}var Ve=t=>{let s=new Set((t?.sources??[]).map(ke));return {postcssPlugin:"webflow-variables-strip-collections",Once(i){let d=false;i.walkAtRules(ln,f=>{f.remove(),d=true;});let a=i.source?.input.file;d&&a!==void 0&&!s.has(ke(a))&&t?.onUnlisted?.(a);}}};Ve.postcss=true;exports.parseVariableSources=on;exports.stripWebflowCollectionsPlugin=Ve;
@@ -0,0 +1,38 @@
1
+ import { StyleVariableCatalog } from '@webflow/data-types/variables';
2
+ import { PluginCreator } from 'postcss';
3
+
4
+ type VariableSource = {
5
+ /** Path shown in diagnostics. */
6
+ file: string;
7
+ css: string;
8
+ };
9
+ type VariableDiagnostic = {
10
+ severity: "error" | "warning";
11
+ message: string;
12
+ file: string;
13
+ line: number;
14
+ column: number;
15
+ };
16
+ type ParsedVariables = {
17
+ catalog: StyleVariableCatalog;
18
+ diagnostics: VariableDiagnostic[];
19
+ };
20
+ /**
21
+ * Reads `@webflow-collection` blocks from the variable declaration files, in
22
+ * the given order, into one catalog. The blocks name the exported variables;
23
+ * their values come from the top-level rules of the same files. Every problem
24
+ * is a diagnostic; the catalog holds what could be read. Callers fail the
25
+ * build on any error and run `validateStyleVariableCatalog` on the catalog.
26
+ */
27
+ declare function parseVariableSources(sources: readonly VariableSource[]): ParsedVariables;
28
+
29
+ type StripWebflowCollectionsOptions = {
30
+ /** Absolute paths of the files listed in `library.variables.sources`. */
31
+ sources?: readonly string[];
32
+ /** Called with a file that has `@webflow-collection` blocks but is not in `sources`. */
33
+ onUnlisted?: (file: string) => void;
34
+ };
35
+ /** Removes `@webflow-collection` blocks from every file; `onUnlisted` flags the ones not in `sources`. */
36
+ declare const stripWebflowCollectionsPlugin: PluginCreator<StripWebflowCollectionsOptions>;
37
+
38
+ export { type ParsedVariables, type StripWebflowCollectionsOptions, type VariableDiagnostic, type VariableSource, parseVariableSources, stripWebflowCollectionsPlugin };
@@ -0,0 +1 @@
1
+ import tn from'postcss';import H from'postcss-value-parser';import Ue from'tinycolor2';import {realpathSync}from'fs';import {resolve}from'path';var O="base";var v="webflow-collection";var Pe=/\s/;function q(t){if(t===void 0)return false;let s=t.charCodeAt(0);return (s>=128||s>=97&&s<=122||s>=65&&s<=90||s>=48&&s<=57||t==="_")&&!Pe.test(t)}function ue(t){let s=t.length,i="",d=0,a=s;for(;d<s&&!q(t[d]);d+=1);for(;a>=1&&!q(t[a-1]);a-=1);for(;d<a;d+=1){let f=t[d];if(f==="/"){for(i[i.length-1]==="-"&&(i=i.substring(0,i.length-1));d<a;d+=1)if(f=t[d],q(f)){i+="--"+f;break}}else q(f)?i+=f:i[i.length-1]!=="-"&&(i+="-");}return i.toLowerCase()}function We(t){let s=t.toLowerCase().trim();if(!/^rgba?\([^)]+\)$/.test(s))return t;let i=s.split(/[,()]/).map(f=>f.trim()).filter(f=>f!==""&&!Number.isNaN(Number(f)));if(i.length<3)return t;i[3]=i[3]||"1";let d=parseFloat(i[3]),a=!Number.isNaN(d)&&d<1;return a||i.pop(),`${a?"rgba":"rgb"}(${i.join(", ")})`}function fe(t){return Ue(We(t)).isValid()}var qe=new Set("aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato transparent turquoise violet wheat white whitesmoke yellow yellowgreen".split(" ")),Be=/^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i,N=String.raw`[+-]?(?:\d+\.?\d*|\.\d+)`,Fe=new RegExp(`^${N}%?\\s*,\\s*${N}%?\\s*,\\s*${N}%?(?:\\s*,\\s*${N}%?)?$`),ze=new RegExp(`^${N}%?(?:deg|grad|rad|turn)?\\s+${N}%?\\s+${N}%?(?:\\s*/\\s*${N}%?)?$`),je=/^(rgba?|hsla?)\(([^()]*)\)$/i;function B(t){let s=t.trim();if(Be.test(s)||qe.has(s.toLowerCase()))return true;let i=je.exec(s);if(i===null)return false;let d=i[2].trim();return Fe.test(d)||ze.test(d)}var Y=new Set(["oklch","oklab","lab","lch","hwb","color","color-mix"]),pe=new Set(["rgb","rgba","hsl","hsla"]);var K=["number","length","percentage"],Ge=new Set(["px","em","rem","vh","vw","dvh","dvw","lvh","lvw","svh","svw","vmax","vmin","ch"]),ge=new Set(["deg","grad","rad","turn","s","ms","hz","khz","dpi","dpcm","dppx","x","fr"]),me=new Set(["","calc","clamp","min","max","abs","sign","round","mod","rem","sin","cos","tan","asin","acos","atan","atan2","pow","sqrt","hypot","log","exp"]),Ye=new Set(["pi","e","infinity","-infinity","nan"]),He=new Set(["+","-","*","/"]),Ke=new Set(["nearest","up","down","to-zero"]),Xe=new Set(["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","emoji","math","fangsong"]),ye=new Set(["auto","none","normal","inherit","initial","unset","revert","revert-layer","currentcolor","min-content","max-content","fit-content","inline","block","flex","grid","hidden","visible","bold","italic"]),X=/^-?[A-Za-z_\u0080-￿][\w\u0080-￿-]*$/,_="has no matching Webflow variable type (a color, length, number, percentage or font family)",F=t=>t.filter(s=>s.type!=="space"&&s.type!=="comment");function D(t,s=[]){return {error:t,warnings:s}}function x(t,s=[]){return {unsupported:t,warnings:s}}function be(t){return `"${t}" is unquoted, so it can be a font family or a keyword; quote it ("${t}") or add type: "font-family"`}function w(t,s=[]){return {inferred:t,warnings:s}}function he(t){let s=H.unit(t);return s===false?void 0:{number:parseFloat(s.number),unit:s.unit.toLowerCase()}}function ve(t,s,i){for(let d of t)if(d.type==="function"){if(d.value.toLowerCase()==="var"){let a=F(d.nodes),f=a[0]?.type==="word"?a[0].value:void 0;f?.startsWith("--")&&(s.push(f),a.length>1&&i.push(f));}ve(d.nodes,s,i);}}function Ze(t,s){let i=F(t.nodes),d=i[0]?.type==="word"?i[0].value:void 0;return d===void 0||!d.startsWith("--")?D(`var() must name a custom property, e.g. var(--brand), not "${H.stringify(t)}"`):(i.length>1&&s.push(`The fallback of var(${d}, \u2026) is dropped: Webflow aliases ${d} without one`),w({value:{type:"ref",value:{variableId:d}},operands:[d]},s))}function Je(t,s,i){let d={length:false,percentage:false},a=[],f,g=false,h=V=>{for(let $ of V){if(f!==void 0)return;if($.type==="word"){let L=$.value;if(He.has(L)||Ke.has(L.toLowerCase())||Ye.has(L.toLowerCase()))continue;let C=he(L);C===void 0?f=`"${L}" is a keyword or unsupported token; ${ye.has(L.toLowerCase())?"keywords are not supported":"only numbers, dimensions and var() are supported"} in a math expression`:C.unit==="%"?d.percentage=true:C.unit!==""&&(ge.has(C.unit)?(f=`"${L}" ${_}`,g=true):d.length=true);}else if($.type==="string")f=`A string in a math expression ${_}`,g=true;else if($.type==="function"){let L=$.value.toLowerCase();if(L==="var"){let C=F($.nodes),p=C[0]?.type==="word"?C[0].value:void 0;p===void 0||!p.startsWith("--")?f="var() must name a custom property, e.g. var(--brand)":C.length>1?f=`var(${p}, \u2026) has a fallback; use var(${p}) without one inside an expression`:a.push(p);}else me.has(L)?h($.nodes):(f=`${L}() inside a math expression ${_}`,g=true);}}};return h(t.nodes),f!==void 0?g?x(f,i):D(f,i):w({value:{type:"raw",value:s},math:d,operands:a},i)}function Qe(t,s){let i=t.value.toLowerCase(),d=[],a=[];return ve(t.nodes,d,a),a.length>0?D(`var(${a[0]}, \u2026) has a fallback; use var(${a[0]}) without one inside an expression`):Y.has(i)||d.length>0?w({value:{type:"raw",value:s},type:"color",operands:d}):w({value:B(s)&&fe(s)?{type:"color",value:s}:{type:"raw",value:s},type:"color",operands:d})}function en(t,s){let i=t.toLowerCase();if(t.startsWith("#"))return B(t)?w({value:{type:"color",value:t},type:"color",operands:[]}):D(`"${t}" is not a valid color`);let d=he(t);if(d!==void 0){let{number:a,unit:f}=d;return f===""?w({value:{type:"number",value:{value:a,unit:"-"}},type:"number",operands:[],zero:a===0}):f==="%"?w({value:{type:"percentage",value:{value:a,unit:"%"}},type:"percentage",operands:[]}):Ge.has(f)?w({value:{type:"length",value:{value:a,unit:f}},type:"length",operands:[]}):ge.has(f)?x(`"${t}" ${_}`):w({value:{type:"raw",value:t},type:"length",operands:[]})}return Xe.has(i)?w({value:{type:"font-family",value:t},type:"font-family",operands:[]}):B(t)?w({value:{type:"color",value:t},type:"color",operands:[]}):ye.has(i)?x(`"${t}" is a keyword; keywords are not supported as variable values`):s&&X.test(t)?w({value:{type:"font-family",value:t},type:"font-family",operands:[]}):x(be(t))}function nn(t,s){let i=[[]];for(let a of t)a.type==="div"&&a.value===","?i.push([]):i[i.length-1].push(a);return i.every(a=>a.length>0&&(a.length===1&&a[0].type==="string"?true:a.every(f=>f.type==="word"&&X.test(f.value))))?w({value:{type:"font-family",value:s},type:"font-family",operands:[]}):x(`"${s}" ${_}`)}function $e(t,{type:s}={}){let i=t.trim(),d=[],a=F(H(i).nodes);if(a.length===0)return D("the value is empty");if(a.length===1){let g=a[0];if(g.type==="string")return w({value:{type:"font-family",value:i},type:"font-family",operands:[]});if(g.type==="word")return en(g.value,s==="font-family");if(g.type==="function"){let h=g.value.toLowerCase();if(h==="var")return Ze(g,d);if(me.has(h)&&h!=="")return Je(g,i,d);if(pe.has(h)||Y.has(h))return Qe(g,i)}return x(`"${i}" ${_}`)}return a.some(g=>g.type==="div"&&g.value===",")?nn(a,i):a.every(g=>g.type==="word"&&X.test(g.value))?s==="font-family"?w({value:{type:"font-family",value:i},type:"font-family",operands:[]}):x(be(i)):x(`"${i}" ${_}`)}function Z(t,s){if(t.zero)return [...K];if(t.type!==void 0)return [t.type];let i=t.operands.map(s);if(i.some(a=>a===void 0))return;if(t.math===void 0)return [i[0]];let d=i.find(a=>a==="color"||a==="font-family");return d!==void 0?{error:`A ${d} variable cannot be used in a math expression`}:t.math.length||i.includes("length")?["length"]:t.math.percentage||i.includes("percentage")?["percentage"]:["number"]}function J(t,s){return t.zero?s==="length"?{type:"length",value:{value:0,unit:"px"}}:s==="percentage"?{type:"percentage",value:{value:0,unit:"%"}}:t.value:t.value}var R="mode",S="variable",ee="Base",M=[":root",":host"],Se=["color","length","number","percentage","font-family"],Le=new Map([["selector",[v,R]],["label",[S]],["type",[S]]]),T=t=>`${t.file}:${t.line}:${t.column}`,Re=(t,s)=>`Add type: "${s}" to @${S} ${t}`,Ce=t=>t.filter(s=>s.type!=="space"&&s.type!=="comment"),P=t=>{let s=t.trim().replace(/\s+/g," ").replace(/\s*,\s*/g,", ").replace(/'/g,'"'),i="",d=0,a=false;for(let f of s)f==='"'?a=!a:!a&&(f==="["||f==="(")?d++:!a&&(f==="]"||f===")")&&d--,!a&&d===0&&">+~".includes(f)?i=`${i.trimEnd()} ${f} `:f===" "&&i.endsWith(" ")||(i+=f);return i.trim()},Q=t=>t.length<2?t.join(""):`${t.slice(0,-1).join(", ")} or ${t[t.length-1]}`;function on(t){let s=[],i=new Map,d=new Map,a=new Set,f=new Set,g=new Set,h=new Map,V=new Map,$=new Map,L=0,C=(e,n,r)=>s.push({severity:e,message:r,file:n.file,line:n.line,column:n.column}),p=(e,n)=>C("error",e,n),I=(e,n)=>C("warning",e,n),k=(e,n)=>({file:n,line:e.source?.start?.line??1,column:e.source?.start?.column??1});function ne(e,n,r,o){n!==void 0&&(e.label===void 0?(e.label=n,e.labelLoc=r):e.label!==n&&p(r,`${o} has conflicting labels "${e.label}" (${T(e.labelLoc)}) and "${n}" (${T(r)})`));}function Ee(e,n,r,o){e.selector===void 0?(e.selector=n,e.selectorLoc=r):P(e.selector)!==P(n)&&p(r,`${o} has conflicting selectors "${e.selector}" (${T(e.selectorLoc)}) and "${n}" (${T(r)})`);}function Ne(e,n){let r=i.get(e);return r===void 0&&(r={id:e,loc:n,modes:new Map},i.set(e,r)),r}function te(e){let n=Ce(H(e.params).nodes),[r,o]=n;if(n.length===0)return {};if(!(r?.type!=="word"||n.length>2||o!==void 0&&o.type!=="string"))return {id:r.value,label:o?.value}}function z(e,n,r){let o=e.prop.toLowerCase(),l=Le.get(o);if(l===void 0){let c=[...Le].filter(([,u])=>u.includes(n)).map(([u])=>u).join(", ");p(r,`Unknown descriptor "${e.prop}" in @${n}; expected ${c}`);}else if(!l.includes(n))p(r,`"${o}" is not a descriptor of @${n}; it belongs in ${l.map(c=>`@${c}`).join(" or ")}`);else if(e.important)p(r,`${o}: !important is not supported on a descriptor`);else return o}function j(e){let n=Ce(H(e.value).nodes);return n.length===1&&n[0].type==="string"?n[0].value:void 0}function oe(e,n,r,o){let l=j(e);if(l===void 0||l.trim()===""){let c=e.value.trim().replace(/^(["'])(.*)\1$/,"$2"),u=c.includes('"')?"'":'"';return p(o,c===""?'selector needs a quoted selector string, e.g. selector: ":root"':`selector must be a quoted string; use selector: ${u}${c}${u}`)}Ee(n,l,o,r);}function xe(e,n,r){let o=k(e,r),l=e.params.trim();if(!/^--[\w\u0080-\uffff-]+$/.test(l))return p(o,`@${S} needs a custom property name, e.g. @${S} --brand`);let c,u,m=new Set;for(let y of e.nodes??[]){if(y.type==="comment")continue;if(y.type!=="decl"){p(k(y,r),`@${S} can hold only descriptors`);continue}let E=k(y,r),A=z(y,S,E);if(A!==void 0){if(m.has(A)){p(E,`Duplicate descriptor "${A}" in @${S} ${l}`);continue}if(m.add(A),A==="label")c=j(y),c===void 0&&p(E,'label must be a quoted string, e.g. label: "color/brand"');else {let de=j(y)??y.value.trim();u=Se.find(Me=>Me===de.toLowerCase()),u===void 0&&p(E,`Unknown type "${de}"; expected ${Se.join(", ")}`);}}}let b=d.get(l);if(b!==void 0)return p(o,`${l} is defined twice: ${T(b.loc)} and ${T(o)}`);d.set(l,{id:l,label:c??l.slice(2),type:u,loc:o,collection:n});}function Ie(e,n,r){let o=k(e,r);if(n.id===void 0)return p(o,`The base collection cannot have modes; give the collection an id with @${v} <id>`);let l=te(e);if(l?.id===void 0)return p(o,`@${R} needs a mode id, e.g. @${R} dark "Dark"`);if(e.nodes===void 0)return p(o,`@${R} needs a block with a selector, e.g. @${R} dark "Dark" { selector: "[data-theme='dark']"; }`);let c=l.id;if(c===O)return p(o,`Mode id "${O}" is reserved`);let u=n.modes.get(c);u===void 0&&(u={loc:o},n.modes.set(c,u));let m=`Mode "${c}" of collection "${n.id}"`;ne(u,l.label,o,m);for(let b of e.nodes){if(b.type==="comment")continue;if(b.type!=="decl"){p(k(b,r),`@${R} can hold only descriptors`);continue}let y=k(b,r);if(b.prop.startsWith("--")){p(y,`${b.prop}: values don't go in @${R}; declare it in a top-level rule with the mode's selector`);continue}z(b,R,y)==="selector"&&(g.add(u),oe(b,u,m,y));}}function Ae(e,n){let r=k(e,n),o=te(e);if(o===void 0)return p(r,`Invalid @${v} prelude "${e.params}"; expected an id and an optional quoted label: @${v} colors "Colors"`);if(e.nodes===void 0)return p(r,`@${v} needs a block with @${S} rules`);let l=o.id===void 0||o.id===O,c=Ne(l?void 0:o.id,r);l?o.label!==void 0&&o.label!==ee&&p(r,`The base collection is always named "${ee}"; remove the label "${o.label}"`):ne(c,o.label,r,`Collection "${o.id}"`);for(let u of e.nodes){if(u.type==="comment")continue;let m=k(u,n);if(u.type==="decl")u.prop.startsWith("--")?p(m,`${u.prop} can't be declared in @${v}; export it with @${S} ${u.prop} and declare its value in a top-level rule`):z(u,v,m)==="selector"&&oe(u,c,`Collection "${c.id??O}"`,m);else if(u.type==="atrule"){let b=u.name.toLowerCase();b===R?Ie(u,c,n):b===S?xe(u,c,n):b===v?p(m,`@${v} must be at the top level of a stylesheet`):p(m,`@${v} can hold only selector, @${R} and @${S}`);}else p(m,`@${v} can hold only selector, @${R} and @${S}`);}}function re(e,n,r){let o=new Set([e.selector,...e.selectors].map(P));e.each(l=>{if(l.type!=="decl"||!l.prop.startsWith("--"))return;let c={value:l.value,important:l.important===true,loc:k(l,n),order:L++};for(let u of o){let m=r.get(u)??new Map;m.set(l.prop,[...m.get(l.prop)??[],c]),r.set(u,m);}});}function Oe(e,n){e.each(r=>{r.type==="rule"?re(r,n,V):r.type==="atrule"&&r.name.toLowerCase()!==v&&r.walkRules(o=>re(o,n,$));});}function _e({file:e,css:n}){let r;try{r=tn.parse(n,{from:e});}catch(l){let c=l;p({file:e,line:c.line??1,column:c.column??1},c.reason??String(l));return}Oe(r,e);let o=new Set;r.walkAtRules(l=>{let c=l.name.toLowerCase();if(c!==v&&c!==R&&c!==S)return;for(let m=l.parent;m;m=m.parent)if(o.has(m))return;o.add(l);let u=k(l,e);c===v&&l.parent?.type==="root"?Ae(l,e):c===v?p(u,`@${v} must be at the top level of a stylesheet, not inside a rule or at-rule such as @media, @layer or @supports`):p(u,`@${c} must be directly inside @${v}`);});}t.forEach(_e);for(let e of i.values())for(let[n,r]of e.modes)g.has(r)||p(r.loc,`@${R} ${n} needs a selector, e.g. selector: "[data-theme='${n}']"`);function U(e,n,r=V){let o=new Set;for(let l of e)r.get(P(l))?.get(n)?.forEach(c=>o.add(c));return [...o].sort((l,c)=>l.order-c.order)}function ie(e,n,r){let o=U(n,e),l=o[o.length-1];if(l!==void 0&&o.length>1){let c=o.every(u=>u.loc.file===l.loc.file);I(l.loc,`${e} is declared more than once on ${r} (${o.map(u=>c?`${u.loc.line}:${u.loc.column}`:T(u.loc)).join(", ")}); the last declaration is used`);}return l}let ae=(e,n,r)=>{let o=$e(n.value,{type:r});return o.warnings.forEach(l=>I(n.loc,`${e}: ${l}`)),o};for(let e of d.values()){let{id:n,collection:r}=e,o=r.selector,l=o??M.join(" or ");if(o!==void 0&&!M.includes(P(o)))for(let y of U(M,n))I(y.loc,`${n} is declared on :root or :host, but collection "${r.id??O}" reads its values from ${o}; this declaration is ignored`);let c=ie(n,o?[o]:M,l);if(c===void 0){a.add(n);let[y]=U(o?[o]:M,n,$);p(e.loc,`${n} is exported but not declared on ${l}${y?`. It is declared inside an at-rule (${T(y.loc)}), and declarations inside @media, @layer or @supports are not read`:""}`);continue}if(c.important){a.add(n),p(c.loc,`${n}: !important is not supported on a variable value`);continue}let{inferred:u,error:m,unsupported:b}=ae(n,c,e.type);u!==void 0?h.set(n,{inferred:u,text:c.value.trim(),loc:c.loc}):m!==void 0?(a.add(n),p(c.loc,`${n}: ${m}`)):e.type!==void 0?(a.add(n),p(c.loc,`${n} has type: ${e.type}, but ${b}`)):(f.add(n),I(c.loc,`${n}: ${b}. It is left out of the catalog (code-only).`));}let se=(e,n)=>{let r=e.operands.filter(l=>!d.has(l)||f.has(l));if(r.length===0)return true;let o=r.find(l=>!a.has(l));return o!==void 0&&p(n,f.has(o)?`var(${o}) refers to a variable that is left out of the catalog (code-only)`:`var(${o}) is not a library variable; var() can only reference variables exported with @${S} in @${v} blocks`),false};function De(e,n,r){let{id:o,type:l}=e;if(r.length===1){let[c]=r;if(l!==void 0&&l!==c){p(n.loc,`${o} has type: ${l}, but its value ${n.text} is a ${c}`);return}return c}if(l===void 0)return I(n.loc,`${o}: ${n.text} can be a ${Q(r)}. Using number. ${Re(o,"<type>")} to choose.`),"number";if(r.includes(l))return l;p(n.loc,`${o} has type: ${l}, but its value ${n.text} can only be a ${Q(r)}`);}let le=new Map,W=[];function G(e){let n=le.get(e);if(n!==void 0)return n??void 0;let r=d.get(e),o=h.get(e);if(r===void 0||o===void 0)return;let l=W.indexOf(e);if(l!==-1){p(r.loc,`Circular reference: ${[...W.slice(l),e].join(" \u2192 ")}`);return}W.push(e);let c=se(o.inferred,o.loc)?Z(o.inferred,G):void 0;W.pop();let u;return c!==void 0&&!Array.isArray(c)?p(o.loc,`${e}: ${c.error}`):c!==void 0&&(u=De(r,o,c)),le.set(e,u??null),u}let ce=[];for(let e of d.values()){let n=G(e.id),r=h.get(e.id);if(n===void 0||r===void 0)continue;let o={};for(let[l,c]of e.collection.modes){if(c.selector===void 0)continue;let u=ie(e.id,[c.selector],c.selector);if(u===void 0){let[E]=U([c.selector],e.id,$);E!==void 0&&I(E.loc,`${e.id} in mode "${l}" (${c.selector}) is declared only inside an at-rule. Declarations inside @media, @layer or @supports are not read, so the mode uses the base value.`);continue}if(u.important){p(u.loc,`${e.id}: !important is not supported on a variable value`);continue}let m=(E,A="")=>I(u.loc,`${e.id} in mode "${l}" (${c.selector}, ${T(u.loc)})${E}. The mode value is ignored, and the mode uses the base value.${A}`),b=ae(e.id,u,n);if(b.error!==void 0){p(u.loc,`${e.id}: ${b.error}`);continue}if(b.inferred===void 0){m(`: ${b.unsupported}`);continue}if(!se(b.inferred,u.loc))continue;let y=Z(b.inferred,G);y!==void 0&&(Array.isArray(y)?y.includes(n)?o[l]=J(b.inferred,n):m(` ${y.length===1?"is":"can be"} a ${Q(y)}, but its base value is a ${n}`,r.inferred.zero&&y.length===1&&K.includes(y[0])?` ${Re(e.id,y[0])} to use the mode value.`:""):p(u.loc,`${e.id}: ${y.error}`));}ce.push({id:e.id,name:e.label,type:n,...e.collection.id===void 0?{}:{collectionId:e.collection.id},value:J(r.inferred,n),...Object.keys(o).length>0?{modes:o}:{}});}return rn(i,d,p),{catalog:{collections:[...i.values()].filter(e=>e.id!==void 0&&Te(e,d)).map(e=>({id:e.id,...e.label===void 0?{}:{name:e.label},modes:[...e.modes].map(([n,r])=>({id:n,...r.label===void 0?{}:{name:r.label}}))})),variables:ce},diagnostics:s}}function rn(t,s,i){let d=(a,f)=>{let g=new Map;for(let h of a){let V=ue(h.label);if(V===""){i(h.loc,`"${h.label}" has no characters usable in a CSS variable name`);continue}let $=g.get(V);$===void 0?g.set(V,h):i(h.loc,`"${$.label}" (${T($.loc)}) and "${h.label}" (${T(h.loc)}) both become "${V}" ${f}`);}};d([...t.values()].filter(a=>a.id!==void 0||Te(a,s)).map(a=>({label:a.label??a.id??ee,loc:a.labelLoc??a.loc})),"in this library");for(let a of t.values()){let f=`in collection "${a.id??O}"`;d([...a.modes].map(([g,h])=>({label:h.label??g,loc:h.labelLoc??h.loc})),f),d([...s.values()].filter(g=>g.collection===a).map(g=>({label:g.label,loc:g.loc})),f);}}function Te(t,s){return [...s.values()].some(i=>i.collection===t)}var ln=new RegExp(`^${v}$`,"i");function ke(t){try{return realpathSync.native(t)}catch{return resolve(t)}}var Ve=t=>{let s=new Set((t?.sources??[]).map(ke));return {postcssPlugin:"webflow-variables-strip-collections",Once(i){let d=false;i.walkAtRules(ln,f=>{f.remove(),d=true;});let a=i.source?.input.file;d&&a!==void 0&&!s.has(ke(a))&&t?.onUnlisted?.(a);}}};Ve.postcss=true;export{on as parseVariableSources,Ve as stripWebflowCollectionsPlugin};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webflow/variables",
3
- "version": "2.8.0",
3
+ "version": "2.9.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -14,8 +14,21 @@
14
14
  "require": "./dist/index.cjs",
15
15
  "default": "./dist/index.js"
16
16
  },
17
+ "./postcss": {
18
+ "types": "./dist/postcss.d.ts",
19
+ "import": "./dist/postcss.js",
20
+ "require": "./dist/postcss.cjs",
21
+ "default": "./dist/postcss.js"
22
+ },
17
23
  "./package.json": "./package.json"
18
24
  },
25
+ "typesVersions": {
26
+ "*": {
27
+ "postcss": [
28
+ "./dist/postcss.d.ts"
29
+ ]
30
+ }
31
+ },
19
32
  "files": [
20
33
  "CHANGELOG.md",
21
34
  "dist/**/*"
@@ -29,10 +42,14 @@
29
42
  "type-check": "tsc -p tsconfig.typecheck.json"
30
43
  },
31
44
  "dependencies": {
32
- "@webflow/data-types": "^2.8.0"
45
+ "@webflow/data-types": "^2.9.0",
46
+ "postcss": "^8.5.23",
47
+ "postcss-value-parser": "^4.2.0",
48
+ "tinycolor2": "1.4.0"
33
49
  },
34
50
  "devDependencies": {
35
51
  "@types/jest": "^30.0.0",
52
+ "@types/tinycolor2": "1.4.3",
36
53
  "eslint-config-custom": "*",
37
54
  "jest": "^30.4.2",
38
55
  "jest-config-custom": "*",