@zeroxsolutions/zaku-cli 0.0.0-stage → 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 zeroxsolutions
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,22 @@
1
- # Temporary Holding Version
1
+ # @zeroxsolutions/zaku-cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The `zaku` command: checks a product's committed design data (`docs/design`) against its code, and
4
+ prints the rules script a Figma write runs through Figma's MCP server. The zaku plugin in
5
+ [agent-plugins](https://github.com/zeroxsolutions/agent-plugins/tree/master/plugins/zaku) ships the
6
+ same build as `bin/zaku.mjs`; this package is for a harness without the plugin, and for CI.
7
+
8
+ ```sh
9
+ npx @zeroxsolutions/zaku-cli check
10
+ ```
11
+
12
+ | Command | What it does |
13
+ | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
14
+ | `zaku check` | runs every check over the committed design files; exits 0, 1 on a finding, 2 on an error |
15
+ | `zaku rules script --page <page>` | prints a `use_figma` body that runs the rules over one page |
16
+ | `zaku rules script --page <page> --after <f>` | prints one body that runs the write in `<f>`, then the rules, answering `{ value, rules }` |
17
+ | `zaku check --input <answer.json>` | reads what `use_figma` returned for either body |
18
+ | `zaku outline`, `zaku library` | read the product file and the library over Figma's REST API (`FIGMA_TOKEN`) |
19
+ | `zaku tokens`, `zaku recipe` | write what the code computes, for the checks to compare |
20
+ | `zaku mcp` | serves `use_figma` and `get_screenshot` over stdio, through the zaku Figma plugin, when Figma's MCP server drops a call |
21
+
22
+ `zaku recipe` drives a browser and needs `playwright`, an optional peer dependency. Node 22 or later.
package/dist/rules.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var zakuRulesLib=(()=>{var C=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var de=(e,t)=>{for(var n in t)C(e,n,{get:t[n],enumerable:!0})},pe=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of le(t))!ce.call(e,r)&&r!==n&&C(e,r,{get:()=>t[r],enumerable:!(a=se(t,r))||a.enumerable});return e};var ue=e=>pe(C({},"__esModule",{value:!0}),e);var et={};de(et,{REPLY_BYTES:()=>z,scopeNodes:()=>ae,zakuRules:()=>Qe});var L={locales:["en"],currencies:[]};var H=new Set(["characters","name","componentProperties","componentPropertyReferences","exposedInstances"]),_=new Set(["primaryAxisSizingMode","counterAxisSizingMode"]);function G(e,t,n){return!t||!n||e!=="width"&&e!=="height"?!1:Math.abs(t[e]-n[e])<.5}function B(e){return e.horizontal!=="FIXED"||e.vertical!=="FIXED"}var X="['\u2019]",U=[{pattern:/\bdelv(?:e|es|ed|ing)\b/iu,instead:'write "look at" or "read"'},{pattern:/\bleverag(?:e|es|ed|ing)\b/iu,instead:'write "use"'},{pattern:/\butili[sz](?:e|es|ed|ing|ation)\b/iu,instead:'write "use"'},{pattern:/\brobust(?:ly|ness)?\b/iu,instead:"write what it withstands"},{pattern:/\btapestr(?:y|ies)\b/iu,instead:'write "mix", or name the parts'},{pattern:/\btestaments?\b/iu,instead:'write "proof", or the fact itself'},{pattern:/\bvibrant(?:ly)?\b/iu,instead:'write "busy", or what is there'},{pattern:/\bempower(?:s|ed|ing|ment)?\b/iu,instead:'write "let" or "allow"'},{pattern:/\bunlock(?:s|ed|ing)?\b/iu,instead:'write "get" or "open"'},{pattern:/\bunleash(?:es|ed|ing)?\b/iu,instead:'write "use" or "start"'},{pattern:/\bgame[- ]?changers?\b/iu,instead:"write what it changes"},{pattern:/\bsupercharg(?:e|es|ed|ing)\b/iu,instead:'write "speed up", with the figure'},{pattern:new RegExp(`\\blet${X}s\\b`,"iu"),instead:'write the action itself, such as "Plan a trip"'},{pattern:new RegExp(`\\b(?:it${X}s|it is) (?:important|worth|crucial) (?:to note|noting)\\b`,"iu"),instead:"delete it"},{pattern:/\bin order to\b/iu,instead:'write "to"'},{pattern:/\bnot (?:just|only|merely)\b[^.!?]{0,80}?\bbut\b/iu,instead:"write the second half on its own"}];var j={en:U};var he=/^[\x20-\x7e]$/,fe=/^[\n\u2028]$/,ge=/^[\p{L}\p{M}]$/u,me=/^(?=\p{M})\p{Script=Inherited}$/u,we=/^\p{Extended_Pictographic}$/u,ye=/^[\u2190-\u21ff\u27f0-\u27ff\u2900-\u297f\u2b00-\u2b11]$/u,Ee=new Map([["\u2014",{name:"em dash",instead:'write "-", or two sentences'}],["\u2013",{name:"en dash",instead:'write "-", or two sentences'}],["\u2018",{name:"left single quotation mark",instead:"write '"}],["\u2019",{name:"right single quotation mark",instead:"write '"}],["\u201C",{name:"left double quotation mark",instead:'write "'}],["\u201D",{name:"right double quotation mark",instead:'write "'}],["\u2026",{name:"horizontal ellipsis",instead:'write "..."'}],["\xB7",{name:"middle dot",instead:'write "-", "," or ":"'}],["\u2022",{name:"bullet",instead:'write "-", "," or ":"'}],["\u2192",{name:"rightwards arrow",instead:'write "->"'}],["\u2190",{name:"leftwards arrow",instead:'write "<-"'}],["\xD7",{name:"multiplication sign",instead:'write "x"'}],["\xA0",{name:"no-break space",instead:"write a space"}],["\u200B",{name:"zero width space",instead:"write nothing"}],["\u200C",{name:"zero width non-joiner",instead:"write nothing"}],["\u200D",{name:"zero width joiner",instead:"write nothing"}],["\uFEFF",{name:"zero width no-break space",instead:"write nothing"}]]),Te={Jpan:["Han","Hiragana","Katakana"],Kore:["Hangul","Han"],Hans:["Han"],Hant:["Han"],Hanb:["Han","Bopomofo"]};function be(e,t){return e.flatMap(n=>["symbol","narrowSymbol"].flatMap(a=>new Intl.NumberFormat(n,{style:"currency",currency:t,currencyDisplay:a}).formatToParts(0).filter(r=>r.type==="currency").map(r=>r.value)))}function Ne(e){return{scripts:[...new Set(e.locales.flatMap(n=>{let a=new Intl.Locale(n).maximize().script??"";return Te[a]??[a]}))].filter(Boolean),symbols:[...new Set(e.currencies.flatMap(n=>be(e.locales,n)))],languages:[...new Set(e.locales.map(n=>new Intl.Locale(n).language))]}}function V(e,t){let n="scripts"in e?e:Ne(e);return{scripts:n.scripts.map(a=>new RegExp(`^\\p{Script_Extensions=${a}}$`,"u")),extra:new Set([...n.symbols,...t].flatMap(a=>[...a.normalize("NFC")])),tells:n.languages.flatMap(a=>j[a]??[])}}function Se(e,t){return he.test(e)||fe.test(e)||t.extra.has(e)?!0:ge.test(e)?me.test(e)||t.scripts.some(n=>n.test(e)):!1}function R(e){return`U+${(e.codePointAt(0)??0).toString(16).toUpperCase().padStart(4,"0")}`}function Ie(e){let t=Ee.get(e);return t?`${R(e)} ${t.name}: ${t.instead}`:we.test(e)?`${R(e)} emoji: write a word, or a library icon`:ye.test(e)?`${R(e)} arrow: write "->" or "<-"`:`${R(e)} is outside the locales and currencies copy names in zaku.yaml: write it in ASCII, or add its locale or currency there`}function $(e,t){let n=[],a=new Set;for(let r of e.normalize("NFC"))a.has(r)||Se(r,t)||(a.add(r),n.push({field:"characters",message:Ie(r)}));for(let r of t.tells){let i=r.pattern.exec(e);i&&n.push({field:"tone",message:`"${i[0]}": ${r.instead}`})}return n}var T={page:"Thumbnail",frame:"Thumbnail",width:1200,height:675,bleeds:"Glow",logo:"Logo",bleed:.25,margin:72},P="Component for Docs",E=(e,t,n)=>({mode:"VERTICAL",padding:e,gap:t,...n?{align:n}:{}}),N=(e,t,n)=>({mode:"HORIZONTAL",padding:e,gap:t,...n?{align:n}:{}}),y=[0,0,0,0],x=[{path:["DS/Header"],where:"components",type:"COMPONENT",at:{x:0,y:0},width:1440,sizing:{horizontal:"FIXED",vertical:"HUG"},layout:N([48,40,40,40],48,["SPACE_BETWEEN","MAX"]),properties:[{name:"Eyebrow",type:"TEXT",default:"Components"},{name:"Component name",type:"TEXT",default:"Button"},{name:"Show style",type:"BOOLEAN",default:!0},{name:"Definition",type:"TEXT",default:"Short description of the component and when to use it."}],paint:"fill color/background; bottom stroke 1 color/border"},{path:["DS/Header","Glow"],where:"components",type:"FRAME",at:{x:0,y:0},width:1440,height:193,paint:"no fill; absolute, not clipping; two radial ellipses, named and placed under the table"},{path:["DS/Header","Title block"],where:"components",type:"FRAME",sizing:{horizontal:"HUG",vertical:"HUG"},layout:E(y,12)},{path:["DS/Header","Title block","Eyebrow"],where:"components",type:"TEXT",font:{size:14,lineHeight:20,weight:"Regular"},text:"Components",paint:"color/muted-foreground"},{path:["DS/Header","Title block","Title"],where:"components",type:"TEXT",font:{size:36,lineHeight:40,weight:"ExtraBold"},text:"Button",paint:"color/foreground; tracking -2.5%"},{path:["DS/Header","Title block","Badges"],where:"components",type:"FRAME",sizing:{horizontal:"HUG",vertical:"HUG"},layout:N(y,8),paint:"no fill; holds one instance of the library's Badge, secondary, once it exists"},{path:["DS/Header","Description"],where:"components",type:"TEXT",width:480,font:{size:16,lineHeight:28,weight:"Regular"},text:"Short description of the component and when to use it.",paint:"color/muted-foreground"},{path:["DS/Section Heading"],where:"components",type:"COMPONENT",at:{x:0,y:273},width:1200,height:81,sizing:{horizontal:"FIXED",vertical:"HUG"},layout:E(y,8),properties:[{name:"Title",type:"TEXT",default:"Section title"},{name:"Description",type:"TEXT",default:"Section description."},{name:"Show description",type:"BOOLEAN",default:!0}],paint:"no fill"},{path:["DS/Section Heading","h2"],where:"components",type:"FRAME",width:1200,height:45,sizing:{horizontal:"FILL",vertical:"HUG"},layout:E([0,0,8,0],0),paint:"bottom stroke 1 color/border, counted in the layout"},{path:["DS/Section Heading","h2","Title"],where:"components",type:"TEXT",font:{size:30,lineHeight:36,weight:"SemiBold"},text:"Section title",paint:"color/foreground; tracking -2.5%"},{path:["DS/Section Heading","Description"],where:"components",type:"TEXT",width:1200,sizing:{horizontal:"FILL"},font:{size:16,lineHeight:28,weight:"Regular"},text:"Section description.",paint:"color/muted-foreground; visible bound to Show description"},{path:["DS/Table Head"],where:"components",type:"COMPONENT",at:{x:0,y:418},width:200,height:40,sizing:{horizontal:"FIXED",vertical:"FIXED"},layout:E([0,8,0,8],0,["CENTER","MIN"]),properties:[{name:"Text",type:"TEXT",default:"Head"}],paint:"no fill"},{path:["DS/Table Head","Text"],where:"components",type:"TEXT",sizing:{horizontal:"FILL"},font:{size:14,lineHeight:20,weight:"Medium"},text:"Head",paint:"color/foreground"},{path:["DS/Table Cell"],where:"components",type:"COMPONENT_SET",at:{x:0,y:522},width:500,height:84,sizing:{horizontal:"FIXED",vertical:"HUG"},layout:{mode:"HORIZONTAL",padding:[24,24,24,24],gap:24,crossGap:24,wrap:!0},properties:[{name:"Text",type:"TEXT",default:"Cell"},{name:"Emphasis",type:"VARIANT",default:"primary"}],paint:"radius 5; the dashed border Figma gives a set"},...["primary","muted"].flatMap((e,t)=>[{path:["DS/Table Cell",`Emphasis=${e}`],where:"components",type:"COMPONENT",at:{x:24+t*224,y:24},width:200,height:36,sizing:{horizontal:"FIXED",vertical:"HUG"},layout:E([8,8,8,8],0),paint:"no fill"},{path:["DS/Table Cell",`Emphasis=${e}`,"Text"],where:"components",type:"TEXT",sizing:{horizontal:"FILL"},font:{size:14,lineHeight:20,weight:e==="primary"?"Medium":"Regular"},text:"Cell",paint:e==="primary"?"color/foreground":"color/muted-foreground"}]),{path:["DS/List Item"],where:"components",type:"COMPONENT",at:{x:0,y:812},width:1176,height:28,sizing:{horizontal:"FIXED",vertical:"HUG"},layout:N(y,10),properties:[{name:"Text",type:"TEXT",default:"List item text."}],paint:"no fill"},{path:["DS/List Item","Bullet"],where:"components",type:"TEXT",sizing:{horizontal:"HUG"},font:{size:16,lineHeight:28,weight:"Regular"},text:"\u2022",paint:"color/foreground"},{path:["DS/List Item","Text"],where:"components",type:"TEXT",sizing:{horizontal:"FILL"},font:{size:16,lineHeight:28,weight:"Regular"},text:"List item text.",paint:"color/foreground"},{path:["DS/Matrix Head"],where:"components",type:"COMPONENT",at:{x:0,y:988},width:120,height:40,sizing:{horizontal:"FIXED",vertical:"FIXED"},layout:E([0,8,0,8],0,["CENTER","CENTER"]),properties:[{name:"Text",type:"TEXT",default:"Prop=value"}],paint:"no fill"},{path:["DS/Matrix Head","Text"],where:"components",type:"TEXT",sizing:{horizontal:"HUG"},font:{size:12,lineHeight:16,weight:"Medium"},text:"Prop=value",paint:"color/muted-foreground"},{path:["*"],where:"view",type:"FRAME",width:1440,layout:E(y,0),paint:"fill color/background"},{path:["*","*"],where:"view",type:"INSTANCE",main:"DS/Header",width:1440},{path:["*","Body"],where:"view",type:"FRAME",width:1440,layout:E([48,120,96,120],64),paint:"no fill"},{path:["*","Body","*"],where:"view",type:"FRAME",width:1200,layout:E(y,24),paint:"no fill"},{path:["*","Body","*","Heading"],where:"view",type:"INSTANCE",main:"DS/Section Heading",width:1200},{path:["*","Body","Component","Preview"],where:"view",type:"FRAME",width:1200,layout:[N(y,24),E(y,40)],paint:"fill color/background, radius 14, no stroke; vertical for a set of text styles"},{path:["*","Body","Matrix","Matrix"],where:"view",type:"FRAME",width:1200,layout:E(y,0),paint:"stroke 1 color/border, radius 8"},{path:["*","Body","Matrix","Matrix","TableHeader"],where:"view",type:"FRAME",height:40,layout:N(y,0)},{path:["*","Body","Example","Preview"],where:"view",type:"FRAME",width:1200,layout:{mode:"HORIZONTAL",padding:[40,40,40,40],gap:48,crossGap:24,wrap:!0},paint:"fill color/background, stroke 1 color/border, radius 14"},...["Variants","Sizes","Composition"].flatMap(e=>[{path:["*","Body",e,"Preview"],where:"view",type:"FRAME",width:1200,layout:N([40,40,40,40],24,["CENTER","CENTER"]),paint:"fill color/background, stroke 1 color/border, radius 14"},{path:["*","Body",e,"Preview",e],where:"view",type:"FRAME",sizing:{horizontal:"HUG",vertical:"HUG"},layout:{mode:"HORIZONTAL",padding:y,gap:12,crossGap:12,wrap:!0,align:["MIN","CENTER"]},paint:"centred in the preview, hugging its row of instances"}]),{path:["*","Body","Anatomy","Anatomy layout"],where:"view",type:"FRAME",width:1200,layout:N(y,16)},{path:["*","Body","Anatomy","Anatomy layout","Preview"],where:"view",type:"FRAME",width:744,sizing:{horizontal:"FILL",vertical:"FILL"},layout:N([24,24,24,24],24,["CENTER","CENTER"]),paint:"fill color/background, stroke 1 color/border, radius 14"},{path:["*","Body","Anatomy","Anatomy layout","Cards"],where:"view",type:"FRAME",width:440,sizing:{horizontal:"FIXED",vertical:"HUG"},layout:{mode:"GRID",padding:y,gap:16,crossGap:16},paint:"one column, one Card per part"},{path:["*","Body","*","Table"],where:"view",type:"FRAME",width:1200,layout:E(y,0),paint:"stroke 1 color/border, radius 8"},{path:["*","Body","*","Table","TableHeader"],where:"view",type:"FRAME",height:40,layout:N(y,0),paint:"bottom stroke 1 color/border"},{path:["*","Body","*","Table","TableRow"],where:"view",type:"FRAME",layout:N(y,0),paint:"bottom stroke 1 color/border, none on the last"},{path:["*","Body","*","List"],where:"view",type:"FRAME",width:1200,layout:E([0,0,0,24],8)},{path:["*","Body","*","List","li"],where:"view",type:"INSTANCE",main:"DS/List Item",width:1176},{path:["*","Body","*","Cards"],where:"view",type:"FRAME",width:1200,layout:{mode:"GRID",padding:y,gap:16,crossGap:16}},{path:["*","Body","*","Cards","Card"],where:"view",type:"INSTANCE",width:592,paint:"the library's Card"},{path:["*","Body","Preview","Theme Preview"],where:"view",type:"FRAME",width:1200,layout:N(y,16)},{path:["*","Body","Preview","Theme Preview","Preview"],where:"view",type:"FRAME",layout:E([40,40,40,40],20),paint:"fill color/background, stroke 1 color/border, radius 14; no mode of its own"}];var Ae="\u2756 ",S=.5;function Oe(e,t){let n=e.page;if(!n)return null;let a=n.name===P?"components":n.name.startsWith(Ae)?"view":null;if(a===null)return null;let r=[];for(let i=e;i;i=i.parentId?t.get(i.parentId):void 0)if(r.unshift(i.name),i.parentId===n.id)return a==="view"&&i.type!=="FRAME"?null:{node:e,path:r,where:a};return null}var Y=e=>e.path.filter(t=>t!=="*").length;function xe(e){return x.filter(n=>n.where!==e.where||n.path.length!==e.path.length||!n.path.every((r,i)=>r==="*"||r===e.path[i])?!1:!(n.main!==void 0&&n.path.at(-1)==="*")||e.node.main===n.main).sort((n,a)=>Y(a)-Y(n))[0]??null}var K=e=>e.replace(/\s+/g,"").toLowerCase(),A=(e,t)=>Math.abs(e-t)<=S,W=e=>e.join(" ");function Me(e,t){let n=[];return e.layout!==t.mode&&n.push(`layout ${e.layout}, not ${t.mode}`),e.padding.every((a,r)=>A(a,t.padding[r]??0))||n.push(`padding ${W(e.padding)}, not ${W(t.padding)}`),A(e.gap,t.gap)||n.push(`gap ${e.gap}, not ${t.gap}`),t.crossGap!==void 0&&!A(e.crossGap,t.crossGap)&&n.push(`row gap ${e.crossGap}, not ${t.crossGap}`),t.wrap!==void 0&&e.wrap!==t.wrap&&n.push(t.wrap?"does not wrap, and it wraps":"wraps, and it does not"),t.align&&(e.align[0]!==t.align[0]||e.align[1]!==t.align[1])&&n.push(`aligns ${e.align.join(" ")}, not ${t.align.join(" ")}`),n}function Re(e,t,n){let a=[],r=(c,p)=>{a.push({nodeId:e.id,field:c,message:`${n}: ${p}`})};e.type!==t.type&&r("type",`is a ${e.type}, and the documentation draws a ${t.type}`),t.main!==void 0&&t.path.at(-1)!=="*"&&e.main!==void 0&&e.main!==t.main&&r("main",`is an instance of ${e.main??"no component"}, not of ${t.main}`);let i=e.box;if(i){t.at&&(!A(i.x,t.at.x)||!A(i.y,t.at.y))&&r("at",`sits at ${i.x}, ${i.y}, not ${t.at.x}, ${t.at.y}`),t.width!==void 0&&!A(i.width,t.width)&&r("width",`is ${i.width} wide, not ${t.width}`),t.height!==void 0&&!A(i.height,t.height)&&r("height",`is ${i.height} high, not ${t.height}`);for(let c of["horizontal","vertical"]){let p=t.sizing?.[c];p!==void 0&&i.sizing[c]!==p&&r(`sizing.${c}`,`sizes ${i.sizing[c]} ${c}ly, not ${p}`)}if(t.layout){let p=(Array.isArray(t.layout)?t.layout:[t.layout]).map(o=>Me(i,o));p.every(o=>o.length>0)&&r("layout",(p[0]??[]).join("; "))}}if(t.font&&e.font){let{size:c,lineHeight:p,style:o}=e.font;(c!==t.font.size||p!==t.font.lineHeight)&&r("font",`is set ${c} / ${p}, not ${t.font.size} / ${t.font.lineHeight}`),K(o)!==K(t.font.weight)&&r("weight",`is ${o}, not ${t.font.weight}`)}if(t.text!==void 0&&e.characters!==void 0&&e.characters!==t.text&&r("text",`reads "${e.characters}", not "${t.text}"`),t.properties&&e.properties){let c=e.properties.map(o=>`${o.name} ${o.type} ${String(o.default)}`).sort(),p=t.properties.map(o=>`${o.name} ${o.type} ${String(o.default)}`).sort();c.join("|")!==p.join("|")&&r("properties",`has the properties [${c.join(", ")}], not [${p.join(", ")}]`)}return a}function Z(e){let t=new Map(e.map(i=>[i.id,i])),n=[],a=e.map(i=>Oe(i,t)).filter(i=>i!==null),r=new Map;for(let i of a){let c=xe(i),p=i.path.join(" / ");i.where==="components"&&i.path.length===1&&(r.set(i.node.name,[...r.get(i.node.name)??[],i.node]),!c&&(i.node.type==="COMPONENT"||i.node.type==="COMPONENT_SET")&&n.push({nodeId:i.node.id,field:"name",message:`${p}: is not one of the documentation components`})),c&&n.push(...Re(i.node,c,p))}for(let[i,c]of r)for(let p of c.slice(1))n.push({nodeId:p.id,field:"name",message:`${i}: a second component of that name`});for(let i of a)if(!(i.where!=="components"||i.path.length!==1||e.filter(p=>p.parentId===i.node.id).length===0))for(let p of x){if(p.where!=="components"||p.path[0]!==i.node.name||p.path.length<2)continue;a.some(h=>h.path.length===p.path.length&&h.path.every((g,s)=>g===p.path[s]))||n.push({nodeId:i.node.id,field:"layers",message:`${i.node.name}: holds no ${p.path.slice(1).join(" / ")}`})}return n.push(...ve(e,t)),n}function ve(e,t){let n=new Map,a=s=>{let m=n.get(s.id);if(m)return m;let l=t.get(s.parentId??"");if(!s.box||!l||l.type==="INSTANCE")return null;let d=s.box.x,f=s.box.y,w,u=[];if(l.parentId===s.page?.id){if(l.name!==T.frame||s.name===T.bleeds)return null;w=[l.name,s.name]}else{let I=a(l);if(!I)return null;d+=I.x,f+=I.y,w=[...I.path,s.name],u=[I,...I.above]}let M=s.type==="INSTANCE"||!e.some(I=>I.parentId===s.id),D={node:s,x:d,y:f,right:d+s.box.width,bottom:f+s.box.height,path:w,block:M,above:u};return n.set(s.id,D),D};for(let s of e)s.page?.name===T.page&&a(s);let r=[...n.values()],i=r.filter(s=>s.block),c=s=>s-T.width,p=s=>i.some(m=>Math.abs(m.x-s.x)<=S&&c(m.right)>S&&c(m.right)>=T.bleed*(m.node.box?.width??0)),o=[],h=(s,m,l)=>{o.push({nodeId:s.node.id,field:m,message:`${s.path.join(" / ")}: ${l}`})},g=s=>[["left",-s.x],["top",-s.y],["bottom",s.bottom-T.height]].filter(([,m])=>m>S).map(([m,l])=>`reaches ${Math.round(l)} past the cover's ${m} edge`);for(let s of r){let m=g(s);m.length>0&&!s.above.some(u=>g(u).length>0)&&h(s,"bounds",`${m.join(", ")}, which cuts it off`);let l=c(s.right);if(s.block){if(p(s))continue;let u=Math.round(s.node.box?.width??0);l>S?h(s,"bounds",`crosses the cover's right edge by ${Math.round(l)} of its ${u}; bleed a quarter of its width past it, or end it ${T.margin} inside`):c(s.right+T.margin)>S&&h(s,"bounds",`ends ${Math.round(-l)} inside the cover's right edge, within its ${T.margin} margin`);continue}if(l<=S)continue;let d=r.filter(u=>u.above.includes(s)),f=d.filter(u=>u.block&&c(u.right)>S&&p(u)),w=Math.max(T.width,...f.map(u=>u.right));s.right<=w+S||d.some(u=>Math.abs(u.right-s.right)<=S)||h(s,"bounds",f.length>0?`reaches ${Math.round(s.right-w)} past the layers that bleed from it at the cover's right edge`:`reaches ${Math.round(l)} past the cover's right edge, and nothing in it bleeds`)}return o}var q=new Set(x.filter(e=>e.where==="components"&&e.path.length===1).map(e=>e.path[0]??""));function J(e){return e.type!=="TEXT"||e.characters===void 0||e.page?.name!==P?!1:x.some(t=>t.where==="components"&&t.type==="TEXT"&&t.text===e.characters&&t.path[0]===e.frame&&t.path.at(-1)===e.name)}var Ce={FRAME:["Frame"],GROUP:["Group"],SECTION:["Section"],COMPONENT:["Component"],COMPONENT_SET:["Component"],RECTANGLE:["Rectangle"],ELLIPSE:["Ellipse"],LINE:["Line"],POLYGON:["Polygon"],STAR:["Star"],VECTOR:["Vector"],SLICE:["Slice"],BOOLEAN_OPERATION:["Union","Subtract","Intersect","Exclude"]};function Q(e,t){let n=/^(.+?)(?: \d+)?$/.exec(t);return n!==null&&(Ce[e]??[]).includes(n[1]??"")}var te="\u2756 ",$e=new Set(["Thumbnail","Component for Docs"]),O=.01,Pe=["data-entry","navigation","feedback","data-display","layout","general"],ke=new RegExp(`^(${Pe.join("|")}) / .+$`),ze="_components";function Fe(e){let t=e.page?.name;return t===void 0?!1:$e.has(t)?!0:e.componentSource!==!1?!1:t.startsWith(te)||ke.test(t)||e.frame===ze}var ee=(e,t)=>e.map(n=>n.variable??"").join()===t.map(n=>n.variable??"").join();function De(e,t){let n=Math.min(e.x+e.width,t.x+t.width)-Math.max(e.x,t.x),a=Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y);return n>O&&a>O}function Le(e){let t=e.box;return e.type!=="FRAME"||!t||t.children!==0||e.fills.length>0||e.strokes.length>0?!1:t.width>1&&t.height>1}function He(e,t,n){return e.x<-O||e.y<-O||e.x+e.width>t+O||e.y+e.height>n+O}function k(e,t=L){let n=V(t,e.flatMap(o=>o.main&&q.has(o.main)?[]:o.instance?.carried??[])),a=[],r=new Map(e.map(o=>[o.id,o])),i=new Set(e.flatMap(o=>o.instance?.overrides.map(h=>h.nodeId)??[])),c=o=>{if(o.page?.name!==T.page)return!1;for(let h=r.get(o.parentId??"");h;h=r.get(h.parentId??""))if(h.name===T.logo)return!0;return!1};for(let o of e){let h=`${o.name} (${o.type.toLowerCase()})`,g=(l,d,f,w=o.id)=>{a.push({check:l,nodeId:w,...d?{field:d}:{},...o.frame?{frame:o.frame}:{},message:f})},s=Fe(o),m=c(o);!m&&o.fills.some(l=>!l.bound)&&g("binding","fill",`${h}: fill is a raw value`),!m&&o.strokes.some(l=>!l.bound)&&g("binding","stroke",`${h}: stroke is a raw value`),o.type==="TEXT"&&o.textStyleId===null&&!s&&g("binding","textStyle",`${h}: text has no library text style`);for(let l of s?[]:o.spacing)l.value>0&&!l.bound&&g("binding",l.field,`${h}: ${l.field} ${l.value} is not a spacing variable`);if((o.type==="COMPONENT"||o.type==="COMPONENT_SET")&&o.page?.name.startsWith(te)&&o.parentId===o.page.id&&g("placement",void 0,`${h}: sits on the page, outside its entry's component view`),o.set){let{width:l,height:d,variants:f}=o.set;f.forEach((w,u)=>{for(let M of f.slice(u+1))De(w,M)&&g("overlap",void 0,`${o.name}: ${w.name} overlaps ${M.name}`,w.id);He(w,l,d)&&g("overlap",void 0,`${o.name}: ${w.name} reaches past the set, which cuts it off`,w.id)})}if(o.characters!==void 0&&!J(o))for(let l of $(o.characters,n))g("copy",l.field,`${h}: ${l.message}`);if(o.instance)for(let l of o.instance.overrides){if(l.characters!==void 0)for(let d of $(l.characters,n))g("copy",d.field,`${o.name}: ${d.message}`,l.nodeId);for(let d of l.fields){if(H.has(d)||d==="fills"&&l.picture)continue;let f=l.nodeId===o.id;if(!f&&(d==="fills"||d==="strokes")&&o.componentSource===!0)continue;let w=r.get(l.nodeId);!f&&(d==="fills"||d==="strokes")&&w?.source&&ee(w[d],w.source[d])||f&&(d==="width"||d==="height")&&s||f&&(d==="width"||d==="height")&&o.componentSource===!0||f&&d==="width"&&o.instance.sizing.horizontal!=="FIXED"||f&&d==="height"&&o.instance.sizing.vertical!=="FIXED"||f&&_.has(d)&&B(o.instance.sizing)||f&&G(d,o.box,o.instance.main)||g("overrides",d,`${d} overridden inside an instance of ${o.name}`,l.nodeId)}}if(Le(o)&&g("empty",void 0,`${o.name}: an empty frame ${Math.round(o.box?.width??0)}x${Math.round(o.box?.height??0)} that shows nothing; it holds no layer, so remove it or put in what it was made for`),Q(o.type,o.name)&&g("naming",void 0,`${o.name} keeps a default name`),o.source){let l=["fills","strokes"].filter(d=>!ee(o[d],o.source?.[d]??[]));l.length>0&&!i.has(o.id)&&g("binding",l[0]==="fills"?"fill":"stroke",`${h}: paints with another colour than the same layer in its component (${(o.source[l[0]??"fills"]??[]).map(d=>d.variable??"raw").join(", ")}), which an icon swap dropped`)}}let p=new Map(e.map(o=>[o.id,o.frame]));for(let{nodeId:o,field:h,message:g}of Z(e)){let s=p.get(o);a.push({check:"documentation",nodeId:o,field:h,...s?{frame:s}:{},message:g})}return a}var z=18e3;function ne(e){return encodeURIComponent(JSON.stringify(e)).replace(/%[0-9A-F]{2}/g,"x").length}function F(e,t,n=18e3){let a={};for(let c of t)a[c.check]=(a[c.check]??0)+1;let r={checked:e,total:t.length,counts:a,findings:[],cut:!1},i=ne(r);for(let c of t){if(i+=ne(c)+1,i>n){r.cut=!0;break}r.findings.push(c)}return r}var _e=["paddingTop","paddingRight","paddingBottom","paddingLeft","itemSpacing"];function v(e){return Array.isArray(e)?e.filter(t=>t.type==="SOLID"&&t.visible!==!1&&(t.opacity??1)>0).map(t=>{let n=t.boundVariables?.color?.id;return{bound:!!t.boundVariables?.color,...typeof n=="string"?{variable:n}:{}}}):[]}function ie(e,t){if(e.id===t)return e;let n=e.findOne;return n?n.call(e,a=>a.id===t):null}function oe(e,t){let n=t.get(e.id);if(n)return n;let a=e.parent??null,r=a?oe(a,t):null,i={frame:a?.type==="PAGE"?e.name:r?.frame??null,page:e.type==="PAGE"?{id:e.id,name:e.name}:r?.page??null,componentSource:e.type==="COMPONENT"||e.type==="COMPONENT_SET"||(r?.componentSource??!1),insideInstance:a?.type==="INSTANCE"||(r?.insideInstance??!1)};return t.set(e.id,i),i}var Ge=new Set(["VECTOR","BOOLEAN_OPERATION","ELLIPSE","RECTANGLE","LINE","STAR","POLYGON"]);function Be(e){if(!e.startsWith("I"))return null;let t=e.slice(1).split(";").slice(1);return t.length===0?null:t.length===1?t[0]??null:`I${t.join(";")}`}function Xe(e){let t=e.children??[];return{width:Number(e.width??0),height:Number(e.height??0),variants:t.map(({id:n,name:a,x:r,y:i,width:c,height:p})=>({id:n,name:a,x:r,y:i,width:c,height:p}))}}function Ue(e,t){let n=e.findAll;return n?n.call(e,a=>a.type==="TEXT"&&!t.has(a.id)).map(a=>typeof a.characters=="string"?a.characters:""):[]}function je(e){let t=e?.fills;return Array.isArray(t)&&t.some(n=>n.type==="IMAGE")}var Ve=new Set(["FRAME","COMPONENT","COMPONENT_SET","INSTANCE","TEXT"]),b=e=>typeof e=="number"?e:0;function Ye(e){let t=typeof e.layoutMode=="string"?e.layoutMode:"NONE",n=t==="GRID";return{x:b(e.x),y:b(e.y),width:b(e.width),height:b(e.height),sizing:{horizontal:String(e.layoutSizingHorizontal??"FIXED"),vertical:String(e.layoutSizingVertical??"FIXED")},layout:t,wrap:e.layoutWrap==="WRAP",padding:[b(e.paddingTop),b(e.paddingRight),b(e.paddingBottom),b(e.paddingLeft)],gap:b(n?e.gridColumnGap:e.itemSpacing),crossGap:b(n?e.gridRowGap:e.counterAxisSpacing),align:[String(e.primaryAxisAlignItems??"MIN"),String(e.counterAxisAlignItems??"MIN")],children:Array.isArray(e.children)?e.children.length:0}}function Ke(e,t){let n=e.fontSize,a=e.lineHeight,r=e.fontName,i=typeof n=="number"?n:0;return{size:n===t?"mixed":i,lineHeight:a===t||typeof a!="object"?"mixed":a.unit==="AUTO"?"auto":a.unit==="PERCENT"?i*b(a.value)/100:b(a.value),style:r===t||typeof r!="object"?"mixed":String(r.style??"")}}function We(e){if(e.type!=="COMPONENT_SET"&&(e.type!=="COMPONENT"||e.parent?.type==="COMPONENT_SET"))return;let t=e.componentPropertyDefinitions;if(t)return Object.entries(t).map(([n,{type:a,defaultValue:r}])=>({name:n.split("#")[0]??n,type:a,default:r}))}async function Ze(e){let t=e.getMainComponentAsync;return t?await t.call(e):null}function qe(e){return e?e.parent?.type==="COMPONENT_SET"?e.parent.name:e.name:null}function Je(e,t,n){return n.find(r=>r.id===e)?.overriddenFields.some(r=>r==="width"||r==="height")&&typeof t?.width=="number"&&typeof t.height=="number"?{width:t.width,height:t.height}:null}async function re(e,t,n=typeof figma>"u"?Symbol("mixed"):figma.mixed,a=new Map,r=i=>figma.getNodeByIdAsync(i)){let i=e,c=i.textStyleId,p=i.overrides??[],o=new Set(p.filter(u=>u.overriddenFields.includes("characters")).map(u=>u.id)),h=e.type==="INSTANCE"?Ue(e,o):[],g=typeof i.layoutMode=="string"&&i.layoutMode!=="NONE",s=oe(e,a),m=Ge.has(e.type)&&s.insideInstance&&!s.componentSource?Be(e.id):null,l=m?await r(m):null,d=e.type==="INSTANCE"?await Ze(i):null,f=e.type==="INSTANCE"?Je(e.id,d,p):null,w=We(i);return{id:e.id,name:e.name,type:e.type,parentId:i.parent?.id??null,frame:s.frame,created:t,fills:v(i.fills),strokes:v(i.strokes),textStyleId:e.type!=="TEXT"?null:c===n?"mixed":typeof c=="string"&&c?c:null,...e.type==="TEXT"&&!s.insideInstance?{characters:String(i.characters??"")}:{},instance:e.type==="INSTANCE"?{overrides:p.map(u=>({nodeId:u.id,fields:u.overriddenFields,...u.overriddenFields.includes("fills")&&je(ie(e,u.id))?{picture:!0}:{},...o.has(u.id)?{characters:String(ie(e,u.id)?.characters??"")}:{}})),...h.length>0?{carried:h}:{},sizing:{horizontal:String(i.layoutSizingHorizontal??"FIXED"),vertical:String(i.layoutSizingVertical??"FIXED")},...f?{main:f}:{}}:null,spacing:g?_e.map(u=>({field:u,value:Number(i[u]??0),bound:!!i.boundVariables?.[u]})):[],...l?{source:{fills:v(l.fills),strokes:v(l.strokes)}}:{},page:s.page,componentSource:s.componentSource,...Ve.has(e.type)?{box:Ye(i)}:{},...e.type==="TEXT"?{font:Ke(i,n)}:{},...w?{properties:w}:{},...e.type==="INSTANCE"?{main:qe(d)}:{},...e.type==="COMPONENT_SET"?{set:Xe(i)}:{}}}async function ae(e,t){if("nodeId"in t){let n=await e.getNodeByIdAsync(t.nodeId);return!n||n.type==="PAGE"||n.type==="DOCUMENT"?[]:"findAll"in n?[n,...n.findAll()]:[n]}if(t.page!==!0){let n=t.page,a=e.root.children,r=a.find(i=>i.id===n||i.name===n);if(!r)throw new Error(`no page ${n}; the pages are ${a.map(i=>i.name).join(", ")}`);r!==e.currentPage&&await e.setCurrentPageAsync(r)}return e.currentPage.findAll()}async function Qe(e,t){let n=await ae(e,t.scope),a=new Map,r=await Promise.all(n.map(i=>re(i,!1,e.mixed,a)));return F(r.length,k(r,t.copy))}return ue(et);})();