aem-eds-kit 0.4.25 → 0.4.26

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/dist/bin/eds.js CHANGED
@@ -1,20 +1,16 @@
1
1
  #!/usr/bin/env node
2
- var ds=Object.defineProperty;var b=(e,t)=>()=>(e&&(t=e(e=0)),t);var U=(e,t)=>{for(var n in t)ds(e,n,{get:t[n],enumerable:!0})};import rd from"path";import{fileURLToPath as ad}from"url";var p=b(()=>{"use strict"});import D from"chalk";function ft(e){return G[e]}function Po(e){return e.replace(ps,"").length}function Ue(e,t){let n=t-Po(e);return n>0?e+" ".repeat(n):e}function us(){return D.bgHex("#ff5a36").hex("#0d0d0c").bold(" >_ ")}function fs(){return`${us()} ${D.bold("aem-eds-kit")}`}function gt(){return Array.from({length:ut},()=>L.accent("\u25CF")).join(" ")}function Ao(e){let t=ut*2-2,n=e%t,o=n<ut?n:t-n;return Array.from({length:ut},(r,s)=>{let a=Math.abs(s-o);return a===0?D.hex("#ff8a66").bold("\u25CF"):a===1?L.accent("\u25CF"):D.hex("#7a3a2a")("\u25CF")}).join(" ")}function Ie(e,t){return`${fs()} ${e} ${D.dim(t)}`}function Eo(e){let t=e.replace("#","");return[Number.parseInt(t.slice(0,2),16),Number.parseInt(t.slice(2,4),16),Number.parseInt(t.slice(4,6),16)]}function gs(e,t,n){let[o,r,s]=Eo(e),[a,d,c]=Eo(t),l=Math.round(o+(a-o)*n),u=Math.round(r+(d-r)*n),m=Math.round(s+(c-s)*n);return`#${[l,u,m].map(f=>f.toString(16).padStart(2,"0")).join("")}`}function hs(e,t,n){let o=[...e],r=Math.max(n-1,1);return o.map((s,a)=>{if(s===" ")return s;let d=a/r*(t.length-1),c=Math.min(Math.floor(d),t.length-2);return D.hex(gs(t[c],t[c+1],d-c))(s)}).join("")}function Vt(){let e=M(Co);return Co.map(t=>` ${hs(t,bs,e)}`).join(`
2
+ var _a=Object.defineProperty;var w=(e,t)=>()=>(e&&(t=e(e=0)),t);var N=(e,t)=>{for(var n in t)_a(e,n,{get:t[n],enumerable:!0})};import np from"path";import{fileURLToPath as ip}from"url";var m=w(()=>{"use strict"});import F from"chalk";function vt(e){return J[e]}function Io(e){return e.replace(Ua,"").length}function Xe(e,t){let n=t-Io(e);return n>0?e+" ".repeat(n):e}function Ba(){return F.bgHex("#ff5a36").hex("#0d0d0c").bold(" >_ ")}function Mo(){return`${Ba()} ${F.bold("aem-eds-kit")}`}function Ga(){return Array.from({length:Ha},()=>_.accent("\u25CF")).join(" ")}function za(e,t=""){return t?`${Mo()} ${e} ${F.dim(t)}`:`${Mo()} ${e}`}function No(e){let t=e.replace("#","");return[Number.parseInt(t.slice(0,2),16),Number.parseInt(t.slice(2,4),16),Number.parseInt(t.slice(4,6),16)]}function Ja(e,t,n){let[o,r,a]=No(e),[s,d,l]=No(t),c=Math.round(o+(s-o)*n),u=Math.round(r+(d-r)*n),p=Math.round(a+(l-a)*n);return`#${[c,u,p].map(f=>f.toString(16).padStart(2,"0")).join("")}`}function Wa(e,t,n){let o=[...e],r=Math.max(n-1,1);return o.map((a,s)=>{if(a===" ")return a;let d=s/r*(t.length-1),l=Math.min(Math.floor(d),t.length-2);return F.hex(Ja(t[l],t[l+1],d-l))(a)}).join("")}function Ka(){let e=O(_o);return _o.map(t=>` ${Wa(t,qa,e)}`).join(`
3
3
  `)}function P(e="AEM Edge Delivery Services"){return`
4
- ${Vt()}
4
+ ${Ka()}
5
5
 
6
- ${Ie(gt(),e)}
7
- `}function j(e,t){let n=L.red("\u258A"),o=t?` ${D.dim(t)}`:"";return`
8
- ${n} ${D.bold(e)}${o}
9
- `}function R(e,t,n,o=0){let r=o?Ue(t,o):t,s=n?` ${D.dim(n)}`:"";return` ${G[e]} ${r}${s}`}function k(e,t,n=0){let o=n?Ue(e,n):e,r=t?` ${D.dim(t)}`:"";return` ${L.accent("\u2714")} ${o}${r}`}function M(e){return e.reduce((t,n)=>Math.max(t,Po(n)),0)}function O(e,t=L.red){let n=M(e),o=t(`\u256D${"\u2500".repeat(n+2)}\u256E`),r=t(`\u2570${"\u2500".repeat(n+2)}\u256F`),s=e.map(a=>`${t("\u2502")} ${Ue(a,n)} ${t("\u2502")}`).join(`
6
+ ${za(Ga(),e)}
7
+ `}function j(e,t){let n=_.red("\u258A"),o=t?` ${F.dim(t)}`:"";return`
8
+ ${n} ${F.bold(e)}${o}
9
+ `}function D(e,t,n,o=0){let r=o?Xe(t,o):t,a=n?` ${F.dim(n)}`:"";return` ${J[e]} ${r}${a}`}function $(e,t,n=0){let o=n?Xe(e,n):e,r=t?` ${F.dim(t)}`:"";return` ${_.accent("\u2714")} ${o}${r}`}function O(e){return e.reduce((t,n)=>Math.max(t,Io(n)),0)}function L(e,t=_.red){let n=O(e),o=t(`\u256D${"\u2500".repeat(n+2)}\u256E`),r=t(`\u2570${"\u2500".repeat(n+2)}\u256F`),a=e.map(s=>`${t("\u2502")} ${Xe(s,n)} ${t("\u2502")}`).join(`
10
10
  `);return`${o}
11
- ${s}
12
- ${r}`}function oe(e){let t=[];return e.pass&&t.push(`${G.pass} ${e.pass} passed`),e.warn&&t.push(`${G.warn} ${e.warn} ${ws(e.warn,"warning")}`),e.fail&&t.push(`${G.fail} ${e.fail} failed`),e.info&&t.push(`${G.info} ${e.info} info`),t.join(D.dim(" "))}function ws(e,t){return e===1?t:`${t}s`}var L,G,ps,ut,Co,bs,I=b(()=>{"use strict";p();L={red:D.hex("#FA0F00"),ember:D.hex("#FF4B1F"),orange:D.hex("#FF7B00"),blue:D.hex("#2680EB"),accent:D.hex("#ff5a36"),dotOrange:D.hex("#F24E1E"),dotPurple:D.hex("#A259FF"),dotBlue:D.hex("#1ABCFE"),dotGreen:D.hex("#0ACF83"),dotPink:D.hex("#FF7262"),ok:D.hex("#2D9D78"),warn:D.hex("#E68619"),err:D.hex("#D7373F"),info:D.hex("#2680EB")},G={pass:L.ok("\u2713"),warn:L.warn("\u26A0"),fail:L.err("\u2717"),info:L.info("\u2139"),bullet:D.dim("\u2022"),arrow:D.dim("\u21B3"),figma:L.dotPurple("\u25C6")};ps=/\[[0-9;]*m/g;ut=5;Co=["\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588","\u2588 \u2588 \u2588 \u2588 ","\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588\u2588\u2588\u2588\u2588","\u2588 \u2588 \u2588 \u2588","\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"],bs=["#ff3b1e","#ff5a36","#ff7d52"]});import Be from"chalk";function ys(){let e=process.env.EDS_LOG_LEVEL?.toLowerCase();return e&&e in Yt?e:"info"}function me(e){return Fo?e==="error":Yt[e]>=Yt[To]}var Yt,To,Fo,ht,i,F=b(()=>{"use strict";p();I();Yt={debug:0,info:1,warn:2,error:3,silent:4};To=ys(),Fo=!1,ht=!1;i={setLevel(e){To=e},setQuiet(e){Fo=e},debug(...e){me("debug")&&console.error(Be.gray("[debug]"),...e)},info(...e){me("info")&&console.error(...e)},logoOnce(e){ht||(ht=!0,me("info")&&console.error(e))},async logoOnceAnimated(e){if(ht||(ht=!0,!me("info")))return;let t=process.stderr;if(!t.isTTY||Be.level===0){console.error(P(e));return}t.write(`
13
- ${Vt()}
14
-
15
- `);let n=r=>r?L.accent("\u258C"):" ",o=14;for(let r=0;r<o;r++)t.write(`\r\x1B[K ${Ie(Ao(r),e)} ${n(r%2===0)}`),await new Promise(s=>setTimeout(s,70));for(let r=0;r<4;r++)t.write(`\r\x1B[K ${Ie(gt(),e)} ${n(r%2===0)}`),await new Promise(s=>setTimeout(s,200));t.write(`\r\x1B[K ${Ie(gt(),e)}
16
- `)},success(...e){me("info")&&console.error(Be.green("\u2713"),...e)},warn(...e){me("warn")&&console.error(Be.yellow("\u26A0"),...e)},error(...e){me("error")&&console.error(Be.red("\u2717"),...e)}}});function Ee(e){return{Authorization:`Bearer ${e}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"aem-eds-kit","Content-Type":"application/json"}}function vs(e){return`${$e}/repos/${e}/generate`}async function bt(e){let t=await fetch(`${$e}/user`,{headers:Ee(e)});if(!t.ok)throw new Error(`GitHub auth failed: ${t.status}`);return(await t.json()).login}async function Do(e,t,n){let o=await fetch(`${$e}/repos/${t}/${n}`,{headers:Ee(e)});if(o.status===404)return!1;if(o.ok)return!0;throw new Error(`existence check failed: ${o.status} ${await o.text()}`)}async function Lo(e,t,n){let o=await fetch(vs(t),{method:"POST",headers:Ee(e),body:JSON.stringify({owner:n.owner,name:n.name,private:!!n.private,include_all_branches:!1})});if(!o.ok)throw new Error(`create failed: ${o.status} ${await o.text()}`);let r=await o.json();return{fullName:r.full_name,htmlUrl:r.html_url,cloneUrl:r.clone_url}}async function Ro(e,t,n,o){await fetch(`${$e}/repos/${t}/${n}/topics`,{method:"PUT",headers:Ee(e),body:JSON.stringify({names:o})})}async function Oo(e,t,n){let o=await fetch(`${$e}/repos/${t}/${n}`,{method:"DELETE",headers:Ee(e)});if(!o.ok&&o.status!==204)throw new Error(`delete failed: ${o.status} ${await o.text()}`)}async function Mo(e,t,n){let o=encodeURIComponent(`user:${t} topic:${n} fork:true`),r=await fetch(`${$e}/search/repositories?q=${o}&per_page=100`,{headers:Ee(e)});if(!r.ok)throw new Error(`search failed: ${r.status}`);return(await r.json()).items.map(a=>a.full_name)}var $e,_o=b(()=>{"use strict";p();$e="https://api.github.com"});import{existsSync as No}from"fs";import{mkdir as ks,readFile as xs,rm as Ss,writeFile as js}from"fs/promises";import $s from"os";import Uo from"path";async function Bo(){let e=process.env.GITHUB_TOKEN||process.env.GH_TOKEN;if(e)return e;if(No(He))try{return JSON.parse(await xs(He,"utf-8")).token??null}catch{return null}return null}async function Qt(e){await ks(Io,{recursive:!0,mode:448}),await js(He,`${JSON.stringify({token:e},null,2)}
17
- `,{mode:384})}async function Ho(){No(He)&&await Ss(He)}async function Go(e){let t=await fetch("https://github.com/login/device/code",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({client_id:wt,scope:e.join(" ")})});if(!t.ok)throw new Error(`device code request failed: ${t.status}`);return await t.json()}async function Jo(e,t,n){let o=Math.max(t,1),r=Date.now()+n*1e3;for(;Date.now()<r;){await new Promise(d=>setTimeout(d,o*1e3));let a=await(await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({client_id:wt,device_code:e,grant_type:"urn:ietf:params:oauth:grant-type:device_code"})})).json();if(a.access_token)return a.access_token;if(a.error==="slow_down")o+=5;else if(a.error!=="authorization_pending")throw new Error(a.error??"device flow failed")}throw new Error("device flow timed out")}var Io,He,wt,Wo=b(()=>{"use strict";p();Io=Uo.join($s.homedir(),".eds"),He=Uo.join(Io,"github.json"),wt=process.env.EDS_GITHUB_CLIENT_ID??""});function Zt(e,t,n="main"){return`https://${n}--${t}--${e}.aem.page/`}function en(){return"https://github.com/apps/aem-code-sync/installations/new"}function zo(e,t){return["repo","create",e,"--template",t.template,t.private?"--private":"--public",...t.clone?["--clone"]:[]]}var Ce,Ge,qo=b(()=>{"use strict";p();Ce="eds-sandbox",Ge={document:"adobe/aem-boilerplate",ue:"adobe/aem-boilerplate-xwalk"}});import{z as T}from"zod";var Ed,tn,Ko,Cd,pe,Pe=b(()=>{"use strict";p();Ed=T.object({fileKey:T.string().min(1),nodeId:T.string().optional(),fileName:T.string().optional()}),tn=T.object({agent:T.enum(["claude","cursor","codex"]).optional(),figma:T.object({mcpEndpoint:T.string().url().optional(),token:T.string().optional()}).optional(),admin:T.object({org:T.string().optional(),site:T.string().optional(),ref:T.string().default("main")}).optional()}),Ko=T.object({root:T.string(),hasFstab:T.boolean(),hasBlocks:T.boolean(),hasHeadHtml:T.boolean()}),Cd=T.object({figmaFileKey:T.string(),figmaNodeId:T.string().optional(),lastSyncedAt:T.string().datetime(),promptVersion:T.string(),agentUsed:T.string().optional(),breakpoints:T.array(T.object({width:T.number(),label:T.string().optional(),source:T.enum(["figma","default"]).optional()})).optional()}),pe=/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/});import{existsSync as Je}from"fs";import ie from"path";function E(e=process.cwd()){let t=ie.resolve(e),{root:n}=ie.parse(t);for(;t!==n;){if(Xo.some(o=>Je(ie.join(t,o))))return t;t=ie.dirname(t)}if(Xo.some(o=>Je(ie.join(n,o))))return n}function Vo(e){return Ko.parse({root:e,hasFstab:Je(ie.join(e,"fstab.yaml")),hasBlocks:Je(ie.join(e,"blocks")),hasHeadHtml:Je(ie.join(e,"head.html"))})}var Xo,H=b(()=>{"use strict";p();Pe();Xo=["fstab.yaml","head.html","helix-query.yaml","component-definition.json","paths.json","scripts/scripts.js","scripts/aem.js"]});import{existsSync as Es}from"fs";import{mkdir as Cs,writeFile as Ps}from"fs/promises";import Yo from"path";async function yt(e){let t=Yo.join(e,".github","workflows","eds.yml");return Es(t)?{path:Qo,created:!1}:(await Cs(Yo.dirname(t),{recursive:!0}),await Ps(t,As),{path:Qo,created:!0})}var Qo,As,nn=b(()=>{"use strict";p();Qo=".github/workflows/eds.yml",As=`name: EDS checks
11
+ ${a}
12
+ ${r}`}function de(e){let t=[];return e.pass&&t.push(`${J.pass} ${e.pass} passed`),e.warn&&t.push(`${J.warn} ${e.warn} ${Xa(e.warn,"warning")}`),e.fail&&t.push(`${J.fail} ${e.fail} failed`),e.info&&t.push(`${J.info} ${e.info} info`),t.join(F.dim(" "))}function Xa(e,t){return e===1?t:`${t}s`}var _,J,Ua,Ha,Uo,_o,qa,I=w(()=>{"use strict";m();_={red:F.hex("#FA0F00"),ember:F.hex("#FF4B1F"),orange:F.hex("#FF7B00"),blue:F.hex("#2680EB"),accent:F.hex("#ff5a36"),dotOrange:F.hex("#F24E1E"),dotPurple:F.hex("#A259FF"),dotBlue:F.hex("#1ABCFE"),dotGreen:F.hex("#0ACF83"),dotPink:F.hex("#FF7262"),ok:F.hex("#2D9D78"),warn:F.hex("#E68619"),err:F.hex("#D7373F"),info:F.hex("#2680EB")},J={pass:_.ok("\u2713"),warn:_.warn("\u26A0"),fail:_.err("\u2717"),info:_.info("\u2139"),bullet:F.dim("\u2022"),arrow:F.dim("\u21B3"),figma:_.dotPurple("\u25C6")};Ua=/\[[0-9;]*m/g;Ha=5;Uo={prefix:"",style:{highlight:e=>F.hex("#ff5a36").bold(e)}};_o=["\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588","\u2588 \u2588 \u2588 \u2588 ","\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588\u2588\u2588\u2588\u2588","\u2588 \u2588 \u2588 \u2588","\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"],qa=["#ff3b1e","#ff5a36","#ff7d52"]});import kt from"chalk";function Va(){let e=process.env.EDS_LOG_LEVEL?.toLowerCase();return e&&e in nn?e:"info"}function we(e){return Ho?e==="error":nn[e]>=nn[Bo]}var nn,Bo,Ho,xt,i,R=w(()=>{"use strict";m();I();nn={debug:0,info:1,warn:2,error:3,silent:4};Bo=Va(),Ho=!1,xt=!1;i={setLevel(e){Bo=e},setQuiet(e){Ho=e},debug(...e){we("debug")&&console.error(kt.gray("[debug]"),...e)},info(...e){we("info")&&console.error(...e)},logoOnce(e){xt||(xt=!0,we("info")&&console.error(e))},async logoOnceAnimated(e){xt||(xt=!0,we("info")&&console.error(P(e)))},success(...e){we("info")&&console.error(kt.green("\u2713"),...e)},warn(...e){we("warn")&&console.error(kt.yellow("\u26A0"),...e)},error(...e){we("error")&&console.error(kt.red("\u2717"),...e)}}});function Le(e){return{Authorization:`Bearer ${e}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"aem-eds-kit","Content-Type":"application/json"}}function Ya(e){return`${Fe}/repos/${e}/generate`}async function $t(e){let t=await fetch(`${Fe}/user`,{headers:Le(e)});if(!t.ok)throw new Error(`GitHub auth failed: ${t.status}`);return(await t.json()).login}async function Go(e,t,n){let o=await fetch(`${Fe}/repos/${t}/${n}`,{headers:Le(e)});if(o.status===404)return!1;if(o.ok)return!0;throw new Error(`existence check failed: ${o.status} ${await o.text()}`)}async function zo(e,t,n){let o=await fetch(Ya(t),{method:"POST",headers:Le(e),body:JSON.stringify({owner:n.owner,name:n.name,private:!!n.private,include_all_branches:!1})});if(!o.ok)throw new Error(`create failed: ${o.status} ${await o.text()}`);let r=await o.json();return{fullName:r.full_name,htmlUrl:r.html_url,cloneUrl:r.clone_url}}async function Jo(e,t,n,o){await fetch(`${Fe}/repos/${t}/${n}/topics`,{method:"PUT",headers:Le(e),body:JSON.stringify({names:o})})}async function Wo(e,t,n){let o=await fetch(`${Fe}/repos/${t}/${n}`,{method:"DELETE",headers:Le(e)});if(!o.ok&&o.status!==204)throw new Error(`delete failed: ${o.status} ${await o.text()}`)}async function qo(e,t,n){let o=encodeURIComponent(`user:${t} topic:${n} fork:true`),r=await fetch(`${Fe}/search/repositories?q=${o}&per_page=100`,{headers:Le(e)});if(!r.ok)throw new Error(`search failed: ${r.status}`);return(await r.json()).items.map(s=>s.full_name)}var Fe,Ko=w(()=>{"use strict";m();Fe="https://api.github.com"});import{existsSync as Xo}from"fs";import{mkdir as Qa,readFile as Za,rm as es,writeFile as ts}from"fs/promises";import ns from"os";import Vo from"path";async function Qo(){let e=process.env.GITHUB_TOKEN||process.env.GH_TOKEN;if(e)return e;if(Xo(Ve))try{return JSON.parse(await Za(Ve,"utf-8")).token??null}catch{return null}return null}async function on(e){await Qa(Yo,{recursive:!0,mode:448}),await ts(Ve,`${JSON.stringify({token:e},null,2)}
13
+ `,{mode:384})}async function Zo(){Xo(Ve)&&await es(Ve)}async function ei(e){let t=await fetch("https://github.com/login/device/code",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({client_id:St,scope:e.join(" ")})});if(!t.ok)throw new Error(`device code request failed: ${t.status}`);return await t.json()}async function ti(e,t,n){let o=Math.max(t,1),r=Date.now()+n*1e3;for(;Date.now()<r;){await new Promise(d=>setTimeout(d,o*1e3));let s=await(await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({client_id:St,device_code:e,grant_type:"urn:ietf:params:oauth:grant-type:device_code"})})).json();if(s.access_token)return s.access_token;if(s.error==="slow_down")o+=5;else if(s.error!=="authorization_pending")throw new Error(s.error??"device flow failed")}throw new Error("device flow timed out")}var Yo,Ve,St,ni=w(()=>{"use strict";m();Yo=Vo.join(ns.homedir(),".eds"),Ve=Vo.join(Yo,"github.json"),St=process.env.EDS_GITHUB_CLIENT_ID??""});function rn(e,t,n="main"){return`https://${n}--${t}--${e}.aem.page/`}function an(){return"https://github.com/apps/aem-code-sync/installations/new"}function oi(e,t){return["repo","create",e,"--template",t.template,t.private?"--private":"--public",...t.clone?["--clone"]:[]]}var Oe,Ye,ii=w(()=>{"use strict";m();Oe="eds-sandbox",Ye={document:"adobe/aem-boilerplate",ue:"adobe/aem-boilerplate-xwalk"}});var U={};N(U,{checkbox:()=>ds,confirm:()=>ls,input:()=>cs,select:()=>ss});import{checkbox as os,confirm as is,input as rs,select as as}from"@inquirer/prompts";function jt(e){let t={...Uo,...e.theme??{}};return{...e,theme:t}}var ss,cs,ls,ds,B=w(()=>{"use strict";m();I();ss=(e,t)=>as(jt(e),t),cs=(e,t)=>rs(jt(e),t),ls=(e,t)=>is(jt(e),t),ds=(e,t)=>os(jt(e),t)});import{z as A}from"zod";var Ep,sn,ri,Pp,ye,Me=w(()=>{"use strict";m();Ep=A.object({fileKey:A.string().min(1),nodeId:A.string().optional(),fileName:A.string().optional()}),sn=A.object({agent:A.enum(["claude","cursor","codex"]).optional(),model:A.string().optional(),figma:A.object({mcpEndpoint:A.string().url().optional(),token:A.string().optional()}).optional(),admin:A.object({org:A.string().optional(),site:A.string().optional(),ref:A.string().default("main")}).optional()}),ri=A.object({root:A.string(),hasFstab:A.boolean(),hasBlocks:A.boolean(),hasHeadHtml:A.boolean()}),Pp=A.object({figmaFileKey:A.string(),figmaNodeId:A.string().optional(),lastSyncedAt:A.string().datetime(),promptVersion:A.string(),agentUsed:A.string().optional(),breakpoints:A.array(A.object({width:A.number(),label:A.string().optional(),source:A.enum(["figma","default"]).optional()})).optional()}),ye=/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/});import{existsSync as Qe}from"fs";import pe from"path";function E(e=process.cwd()){let t=pe.resolve(e),{root:n}=pe.parse(t);for(;t!==n;){if(ai.some(o=>Qe(pe.join(t,o))))return t;t=pe.dirname(t)}if(ai.some(o=>Qe(pe.join(n,o))))return n}function si(e){return ri.parse({root:e,hasFstab:Qe(pe.join(e,"fstab.yaml")),hasBlocks:Qe(pe.join(e,"blocks")),hasHeadHtml:Qe(pe.join(e,"head.html"))})}var ai,z=w(()=>{"use strict";m();Me();ai=["fstab.yaml","head.html","helix-query.yaml","component-definition.json","paths.json","scripts/scripts.js","scripts/aem.js"]});import{existsSync as ps}from"fs";import{mkdir as ms,writeFile as us}from"fs/promises";import ci from"path";async function Et(e){let t=ci.join(e,".github","workflows","eds.yml");return ps(t)?{path:li,created:!1}:(await ms(ci.dirname(t),{recursive:!0}),await us(t,fs),{path:li,created:!0})}var li,fs,cn=w(()=>{"use strict";m();li=".github/workflows/eds.yml",fs=`name: EDS checks
18
14
 
19
15
  # Generated by aem-eds-kit (\`eds scaffold ci\`). Runs the project's own
20
16
  # lint/build plus the eds audits as a gatekeeper on every PR and push to main.
@@ -57,18 +53,18 @@ jobs:
57
53
  run: npx --yes aem-eds-kit@latest audit loading
58
54
  - name: Security & exploit scan
59
55
  run: npx --yes aem-eds-kit@latest audit security
60
- `});import{existsSync as Zo}from"fs";import{readFile as Ts,writeFile as ei}from"fs/promises";import ti from"path";function Fs(e={}){let t=e.open??"/",n=e.port??3007,o=e.pagesUrl??"";return`AEM_OPEN=${t}
56
+ `});import{existsSync as di}from"fs";import{readFile as gs,writeFile as pi}from"fs/promises";import mi from"path";function hs(e={}){let t=e.open??"/",n=e.port??3007,o=e.pagesUrl??"";return`AEM_OPEN=${t}
61
57
  AEM_PORT=${n}
62
58
  AEM_PAGES_URL=${o}
63
- `}async function Ds(e){let t=ti.join(e,".gitignore"),n="";if(Zo(t)&&(n=await Ts(t,"utf-8")),n.split(/\r?\n/).some(r=>r.trim()===".env"))return!1;let o=n&&!n.endsWith(`
59
+ `}async function bs(e){let t=mi.join(e,".gitignore"),n="";if(di(t)&&(n=await gs(t,"utf-8")),n.split(/\r?\n/).some(r=>r.trim()===".env"))return!1;let o=n&&!n.endsWith(`
64
60
  `)?`
65
- `:"";return await ei(t,`${n}${o}.env
66
- `),!0}async function vt(e,t={}){let n=ti.join(e,".env"),o=!Zo(n);o&&await ei(n,Fs(t));let r=await Ds(e);return{path:".env",created:o,gitignoreUpdated:r}}var on=b(()=>{"use strict";p()});import{writeFile as ni}from"fs/promises";import oi from"path";function kt(e){return e!=="ue"}function ii(e,t){return`https://content.da.live/${e}/${t}/`}function Ls(e){return`mountpoints:
61
+ `:"";return await pi(t,`${n}${o}.env
62
+ `),!0}async function Pt(e,t={}){let n=mi.join(e,".env"),o=!di(n);o&&await pi(n,hs(t));let r=await bs(e);return{path:".env",created:o,gitignoreUpdated:r}}var ln=w(()=>{"use strict";m()});import{writeFile as ui}from"fs/promises";import fi from"path";function Ct(e){return e!=="ue"}function gi(e,t){return`https://content.da.live/${e}/${t}/`}function ws(e){return`mountpoints:
67
63
  /: ${e}
68
- `}async function ri(e,t){return await ni(oi.join(e,"fstab.yaml"),Ls(t)),"fstab.yaml"}function Rs(e){return`${JSON.stringify({mappings:[`/content/${e}/:/`],includes:[`/content/${e}/`]},null,2)}
69
- `}async function si(e,t){return await ni(oi.join(e,"paths.json"),Rs(t)),"paths.json"}var ue,ai=b(()=>{"use strict";p();ue={ue:"Universal Editor (crosswalk)",da:"Document Authoring (da.live)",gdrive:"Document Authoring (Google Drive)",sharepoint:"Document Authoring (SharePoint)"}});import{existsSync as Os}from"fs";import{writeFile as Ms}from"fs/promises";import _s from"path";function Us(){return`${JSON.stringify(Ns,null,2)}
70
- `}async function xt(e){let t=_s.join(e,"xwalk.json");return Os(t)?{path:"xwalk.json",created:!1}:(await Ms(t,Us()),{path:"xwalk.json",created:!0})}var Ns,rn=b(()=>{"use strict";p();Ns={public:{xwalk:{"multi-field":{enabled:!0}}}}});function Ae(e){let t=e.trim().match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?\/?$/i);return t?{owner:t[1],repo:t[2]}:null}function Te(e,t,n="main"){return`${n}--${t}--${e}.aem.page`}function ci({host:e,path:t="/",org:n}){let o=e.replace(/^https?:\/\//,"").replace(/\/+$/,""),r=t.startsWith("/")?t:`/${t}`;return`https://experience.adobe.com/#/${n?`@${n}/`:""}aem/editor/canvas/${o}${r}`}var St=b(()=>{"use strict";p()});function We(e){return`${JSON.stringify(e,null,2)}
71
- `}function an(e){return fe.find(t=>t.id===e)}var sn,li,di,fe,cn=b(()=>{"use strict";p();sn=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:e,model:n}}}}}),li=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:e,filter:n}}}}}),di=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block/item",template:{name:e,model:n}}}}}),fe=[{id:"hero",title:"Hero",js:`// Block: hero
64
+ `}async function hi(e,t){return await ui(fi.join(e,"fstab.yaml"),ws(t)),"fstab.yaml"}function ys(e){return`${JSON.stringify({mappings:[`/content/${e}/:/`],includes:[`/content/${e}/`]},null,2)}
65
+ `}async function bi(e,t){return await ui(fi.join(e,"paths.json"),ys(t)),"paths.json"}var ve,wi=w(()=>{"use strict";m();ve={ue:"Universal Editor (crosswalk)",da:"Document Authoring (da.live)",gdrive:"Document Authoring (Google Drive)",sharepoint:"Document Authoring (SharePoint)"}});import{existsSync as vs}from"fs";import{writeFile as ks}from"fs/promises";import xs from"path";function Ss(){return`${JSON.stringify($s,null,2)}
66
+ `}async function At(e){let t=xs.join(e,"xwalk.json");return vs(t)?{path:"xwalk.json",created:!1}:(await ks(t,Ss()),{path:"xwalk.json",created:!0})}var $s,dn=w(()=>{"use strict";m();$s={public:{xwalk:{"multi-field":{enabled:!0}}}}});function Ne(e){let t=e.trim().match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?\/?$/i);return t?{owner:t[1],repo:t[2]}:null}function _e(e,t,n="main"){return`${n}--${t}--${e}.aem.page`}function yi({host:e,path:t="/",org:n}){let o=e.replace(/^https?:\/\//,"").replace(/\/+$/,""),r=t.startsWith("/")?t:`/${t}`;return`https://experience.adobe.com/#/${n?`@${n}/`:""}aem/editor/canvas/${o}${r}`}var Tt=w(()=>{"use strict";m()});function Ze(e){return`${JSON.stringify(e,null,2)}
67
+ `}function mn(e){return ke.find(t=>t.id===e)}var pn,vi,ki,ke,un=w(()=>{"use strict";m();pn=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:e,model:n}}}}}),vi=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:e,filter:n}}}}}),ki=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block/item",template:{name:e,model:n}}}}}),ke=[{id:"hero",title:"Hero",js:`// Block: hero
72
68
  export default function decorate(block) {
73
69
  block.classList.add('hero');
74
70
  const picture = block.querySelector('picture');
@@ -97,7 +93,7 @@ export default function decorate(block) {
97
93
  margin: 0 auto;
98
94
  padding: 0 var(--spacing-m, 16px);
99
95
  }
100
- `,model:We({definitions:[sn("Hero","hero","hero")],models:[{id:"hero",fields:[{component:"reference",valueType:"string",name:"image",label:"Image"},{component:"text",valueType:"string",name:"imageAlt",label:"Alt"},{component:"text",valueType:"string",name:"title",label:"Title"},{component:"richtext",valueType:"string",name:"text",value:"",label:"Text"}]}],filters:[]})},{id:"cards",title:"Cards",js:`// Block: cards
96
+ `,model:Ze({definitions:[pn("Hero","hero","hero")],models:[{id:"hero",fields:[{component:"reference",valueType:"string",name:"image",label:"Image"},{component:"text",valueType:"string",name:"imageAlt",label:"Alt"},{component:"text",valueType:"string",name:"title",label:"Title"},{component:"richtext",valueType:"string",name:"text",value:"",label:"Text"}]}],filters:[]})},{id:"cards",title:"Cards",js:`// Block: cards
101
97
  export default function decorate(block) {
102
98
  const ul = document.createElement('ul');
103
99
  [...block.children].forEach((row) => {
@@ -136,7 +132,7 @@ export default function decorate(block) {
136
132
  .cards .cards-card-body {
137
133
  padding: var(--spacing-m, 16px);
138
134
  }
139
- `,model:We({definitions:[li("Cards","cards","cards"),di("Card","card","card")],models:[{id:"card",fields:[{component:"reference",valueType:"string",name:"image",label:"Image"},{component:"text",valueType:"string",name:"imageAlt",label:"Alt"},{component:"text",valueType:"string",name:"title",label:"Title"},{component:"richtext",valueType:"string",name:"text",value:"",label:"Text"},{component:"aem-content",name:"link",label:"Link"}]}],filters:[{id:"cards",components:["card"]}]})},{id:"columns",title:"Columns",js:`// Block: columns
135
+ `,model:Ze({definitions:[vi("Cards","cards","cards"),ki("Card","card","card")],models:[{id:"card",fields:[{component:"reference",valueType:"string",name:"image",label:"Image"},{component:"text",valueType:"string",name:"imageAlt",label:"Alt"},{component:"text",valueType:"string",name:"title",label:"Title"},{component:"richtext",valueType:"string",name:"text",value:"",label:"Text"},{component:"aem-content",name:"link",label:"Link"}]}],filters:[{id:"cards",components:["card"]}]})},{id:"columns",title:"Columns",js:`// Block: columns
140
136
  export default function decorate(block) {
141
137
  const cols = [...block.firstElementChild.children];
142
138
  block.classList.add(\`columns-\${cols.length}-cols\`);
@@ -163,7 +159,7 @@ export default function decorate(block) {
163
159
  }
164
160
 
165
161
  .columns img { width: 100%; height: auto; }
166
- `,model:We({definitions:[sn("Columns","columns","columns")],models:[{id:"columns",fields:[{component:"richtext",valueType:"string",name:"content",value:"",label:"Content"}]}],filters:[]})},{id:"accordion",title:"Accordion",js:`// Block: accordion
162
+ `,model:Ze({definitions:[pn("Columns","columns","columns")],models:[{id:"columns",fields:[{component:"richtext",valueType:"string",name:"content",value:"",label:"Content"}]}],filters:[]})},{id:"accordion",title:"Accordion",js:`// Block: accordion
167
163
  export default function decorate(block) {
168
164
  [...block.children].forEach((row) => {
169
165
  const [label, body] = row.children;
@@ -196,7 +192,7 @@ export default function decorate(block) {
196
192
  .accordion .accordion-item-body {
197
193
  padding-bottom: var(--spacing-m, 16px);
198
194
  }
199
- `,model:We({definitions:[li("Accordion","accordion","accordion"),di("Accordion Item","accordion-item","accordion-item")],models:[{id:"accordion-item",fields:[{component:"text",valueType:"string",name:"label",label:"Label"},{component:"richtext",valueType:"string",name:"body",value:"",label:"Body"}]}],filters:[{id:"accordion",components:["accordion-item"]}]})},{id:"embed",title:"Embed",js:`// Block: embed
195
+ `,model:Ze({definitions:[vi("Accordion","accordion","accordion"),ki("Accordion Item","accordion-item","accordion-item")],models:[{id:"accordion-item",fields:[{component:"text",valueType:"string",name:"label",label:"Label"},{component:"richtext",valueType:"string",name:"body",value:"",label:"Body"}]}],filters:[{id:"accordion",components:["accordion-item"]}]})},{id:"embed",title:"Embed",js:`// Block: embed
200
196
  export default function decorate(block) {
201
197
  const link = block.querySelector('a');
202
198
  const url = link?.href;
@@ -225,12 +221,12 @@ export default function decorate(block) {
225
221
  height: 100%;
226
222
  border: 0;
227
223
  }
228
- `,model:We({definitions:[sn("Embed","embed","embed")],models:[{id:"embed",fields:[{component:"aem-content",name:"link",label:"Embed URL"}]}],filters:[]})}]});import{existsSync as Is}from"fs";import{mkdir as Bs,writeFile as Hs}from"fs/promises";import mi from"path";function ui(e){return ze.find(t=>t.id===e)}function fi(e){let t=new Set,n=o=>{if(t.has(o))return;let r=ui(o);if(r){for(let s of r.deps??[])n(s);t.add(o)}};for(let o of e)n(o);return ze.filter(o=>t.has(o.id)).map(o=>o.id)}function Gs(e){return`// scripts/utils.js - common EDS helpers (generated by \`eds scaffold helpers\`).
224
+ `,model:Ze({definitions:[pn("Embed","embed","embed")],models:[{id:"embed",fields:[{component:"aem-content",name:"link",label:"Embed URL"}]}],filters:[]})}]});import{existsSync as js}from"fs";import{mkdir as Es,writeFile as Ps}from"fs/promises";import xi from"path";function Si(e){return et.find(t=>t.id===e)}function ji(e){let t=new Set,n=o=>{if(t.has(o))return;let r=Si(o);if(r){for(let a of r.deps??[])n(a);t.add(o)}};for(let o of e)n(o);return et.filter(o=>t.has(o.id)).map(o=>o.id)}function Cs(e){return`// scripts/utils.js - common EDS helpers (generated by \`eds scaffold helpers\`).
229
225
 
230
- ${fi(e).map(o=>ui(o)).filter(o=>!!o).map(o=>o.code).join(`
226
+ ${ji(e).map(o=>Si(o)).filter(o=>!!o).map(o=>o.code).join(`
231
227
 
232
228
  `)}
233
- `}async function gi(e,t=ln){let n=fi(t),o=mi.join(e,"scripts","utils.js");return Is(o)?{path:pi,created:!1,helpers:n}:(await Bs(mi.dirname(o),{recursive:!0}),await Hs(o,Gs(t)),{path:pi,created:!0,helpers:n})}var pi,ze,ln,hi=b(()=>{"use strict";p();pi="scripts/utils.js",ze=[{id:"getMetadata",label:"getMetadata (read a page meta value)",code:`/**
229
+ `}async function Ei(e,t=fn){let n=ji(t),o=xi.join(e,"scripts","utils.js");return js(o)?{path:$i,created:!1,helpers:n}:(await Es(xi.dirname(o),{recursive:!0}),await Ps(o,Cs(t)),{path:$i,created:!0,helpers:n})}var $i,et,fn,Pi=w(()=>{"use strict";m();$i="scripts/utils.js",et=[{id:"getMetadata",label:"getMetadata (read a page meta value)",code:`/**
234
230
  * Reads a page metadata value by name (meta[name] or meta[property]).
235
231
  * @param {string} name The metadata name.
236
232
  * @returns {string} The value, or an empty string.
@@ -327,8 +323,8 @@ export function isUEPreview() {
327
323
  */
328
324
  export function isUE() {
329
325
  return isUEEdit() || isUEPreview();
330
- }`}],ln=ze.map(e=>e.id)});function Js(){return[{component:"tab",name:"basics",label:"Basics"},{component:"text",valueType:"string",name:"text",label:"Text (single line)"},{component:"textarea",valueType:"string",name:"textarea",label:"Textarea (multi-line)"},{component:"richtext",valueType:"string",name:"richtext",value:"",label:"Rich text"},{component:"number",valueType:"number",name:"number",label:"Number"},{component:"boolean",valueType:"boolean",name:"boolean",value:!1,label:"Boolean"},{component:"date-time",valueType:"date",name:"date",label:"Date / time"},{component:"tab",name:"selection",label:"Selection"},{component:"select",valueType:"string",name:"select",label:"Select",value:"a",options:[{name:"Option A",value:"a"},{name:"Option B",value:"b"}]},{component:"radio-group",valueType:"string",name:"radio",label:"Radio group",value:"x",options:[{name:"X",value:"x"},{name:"Y",value:"y"}]},{component:"multiselect",valueType:"string",name:"classes",label:"Multiselect (CSS classes)",options:[{name:"Highlight",value:"highlight"},{name:"Dark",value:"dark"}]},{component:"checkbox-group",valueType:"string[]",name:"toggles",label:"Checkbox group",options:[{name:"Show title",value:"show-title"},{name:"Show image",value:"show-image"}]},{component:"tab",name:"media",label:"Media & content"},{component:"reference",valueType:"string",name:"image",label:"Image (DAM asset)"},{component:"text",valueType:"string",name:"imageAlt",label:"Image alt"},{component:"aem-content",name:"link",label:"Link (page / URL)"},{component:"aem-content-fragment",name:"contentFragment",label:"Content Fragment"},{component:"aem-experience-fragment",name:"experienceFragment",label:"Experience Fragment"},{component:"aem-tag",valueType:"string",name:"tags",label:"Tags"},{component:"tab",name:"repeatable",label:"Multifield"},{component:"container",name:"items",label:"Items (repeatable)",multi:!0,collapsible:!0,fields:[{component:"text",valueType:"string",name:"itemTitle",label:"Title"},{component:"richtext",valueType:"string",name:"itemText",value:"",label:"Text"},{component:"aem-content",name:"itemLink",label:"Link"}]}]}function dn(){let e={definitions:[{title:"Field Reference",id:"field-reference",plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:"Field Reference",model:"field-reference"}}}}}],models:[{id:"field-reference",fields:Js()}],filters:[]};return`${JSON.stringify(e,null,2)}
331
- `}function mn(e,t){let n=new Set(e.map(o=>o.id));return[...e,...t.filter(o=>!n.has(o.id))]}function ki(e,t,n){let o=e?.groups?[...e.groups]:[],r=(s,a,d)=>{let c=o.find(l=>l.id===s);c||(c={id:s,title:a,components:[]},o.push(c)),c.components=mn(c.components,d)};return r("default","Default Content",t),r("blocks","Blocks",n),{groups:o}}function qe(e,t){let n=e?[...e]:[],o=n.find(r=>r.id==="section");return o||(o={id:"section",components:["text","image","button","title"]},n.push(o)),o.components=[...new Set([...o.components,...t])],n}var bi,wi,yi,vi,pn=b(()=>{"use strict";p();bi=[{title:"Text",id:"text",plugins:{xwalk:{page:{resourceType:"core/franklin/components/text/v1/text",template:{text:"<p>Text</p>"}}}}},{title:"Image",id:"image",plugins:{xwalk:{page:{resourceType:"core/franklin/components/image/v1/image",template:{image:"",imageAlt:""}}}}},{title:"Button",id:"button",plugins:{xwalk:{page:{resourceType:"core/franklin/components/button/v1/button",template:{text:"Button",href:"",type:""}}}}},{title:"Title",id:"title",plugins:{xwalk:{page:{resourceType:"core/franklin/components/title/v1/title",template:{title:"Title",type:"h2"}}}}}],wi=[{id:"title",fields:[{component:"text",valueType:"string",name:"title",label:"Title"},{component:"select",valueType:"string",name:"type",label:"Type",value:"h2",options:[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"},{name:"H5",value:"h5"},{name:"H6",value:"h6"}]}]},{id:"image",fields:[{component:"reference",valueType:"string",name:"image",label:"Image",multi:!1},{component:"text",valueType:"string",name:"imageAlt",label:"Alt Text"}]},{id:"button",fields:[{component:"text",valueType:"string",name:"text",label:"Text"},{component:"aem-content",name:"href",label:"Link"},{component:"select",valueType:"string",name:"type",label:"Type",options:[{name:"Default",value:""},{name:"Primary",value:"primary"},{name:"Secondary",value:"secondary"}]}]}];yi=`// Block: field-reference
326
+ }`}],fn=et.map(e=>e.id)});function As(){return[{component:"tab",name:"basics",label:"Basics"},{component:"text",valueType:"string",name:"text",label:"Text (single line)"},{component:"textarea",valueType:"string",name:"textarea",label:"Textarea (multi-line)"},{component:"richtext",valueType:"string",name:"richtext",value:"",label:"Rich text"},{component:"number",valueType:"number",name:"number",label:"Number"},{component:"boolean",valueType:"boolean",name:"boolean",value:!1,label:"Boolean"},{component:"date-time",valueType:"date",name:"date",label:"Date / time"},{component:"tab",name:"selection",label:"Selection"},{component:"select",valueType:"string",name:"select",label:"Select",value:"a",options:[{name:"Option A",value:"a"},{name:"Option B",value:"b"}]},{component:"radio-group",valueType:"string",name:"radio",label:"Radio group",value:"x",options:[{name:"X",value:"x"},{name:"Y",value:"y"}]},{component:"multiselect",valueType:"string",name:"classes",label:"Multiselect (CSS classes)",options:[{name:"Highlight",value:"highlight"},{name:"Dark",value:"dark"}]},{component:"checkbox-group",valueType:"string[]",name:"toggles",label:"Checkbox group",options:[{name:"Show title",value:"show-title"},{name:"Show image",value:"show-image"}]},{component:"tab",name:"media",label:"Media & content"},{component:"reference",valueType:"string",name:"image",label:"Image (DAM asset)"},{component:"text",valueType:"string",name:"imageAlt",label:"Image alt"},{component:"aem-content",name:"link",label:"Link (page / URL)"},{component:"aem-content-fragment",name:"contentFragment",label:"Content Fragment"},{component:"aem-experience-fragment",name:"experienceFragment",label:"Experience Fragment"},{component:"aem-tag",valueType:"string",name:"tags",label:"Tags"},{component:"tab",name:"repeatable",label:"Multifield"},{component:"container",name:"items",label:"Items (repeatable)",multi:!0,collapsible:!0,fields:[{component:"text",valueType:"string",name:"itemTitle",label:"Title"},{component:"richtext",valueType:"string",name:"itemText",value:"",label:"Text"},{component:"aem-content",name:"itemLink",label:"Link"}]}]}function gn(){let e={definitions:[{title:"Field Reference",id:"field-reference",plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:"Field Reference",model:"field-reference"}}}}}],models:[{id:"field-reference",fields:As()}],filters:[]};return`${JSON.stringify(e,null,2)}
327
+ `}function hn(e,t){let n=new Set(e.map(o=>o.id));return[...e,...t.filter(o=>!n.has(o.id))]}function Di(e,t,n){let o=e?.groups?[...e.groups]:[],r=(a,s,d)=>{let l=o.find(c=>c.id===a);l||(l={id:a,title:s,components:[]},o.push(l)),l.components=hn(l.components,d)};return r("default","Default Content",t),r("blocks","Blocks",n),{groups:o}}function tt(e,t){let n=e?[...e]:[],o=n.find(r=>r.id==="section");return o||(o={id:"section",components:["text","image","button","title"]},n.push(o)),o.components=[...new Set([...o.components,...t])],n}var Ci,Ai,Ti,Ri,bn=w(()=>{"use strict";m();Ci=[{title:"Text",id:"text",plugins:{xwalk:{page:{resourceType:"core/franklin/components/text/v1/text",template:{text:"<p>Text</p>"}}}}},{title:"Image",id:"image",plugins:{xwalk:{page:{resourceType:"core/franklin/components/image/v1/image",template:{image:"",imageAlt:""}}}}},{title:"Button",id:"button",plugins:{xwalk:{page:{resourceType:"core/franklin/components/button/v1/button",template:{text:"Button",href:"",type:""}}}}},{title:"Title",id:"title",plugins:{xwalk:{page:{resourceType:"core/franklin/components/title/v1/title",template:{title:"Title",type:"h2"}}}}}],Ai=[{id:"title",fields:[{component:"text",valueType:"string",name:"title",label:"Title"},{component:"select",valueType:"string",name:"type",label:"Type",value:"h2",options:[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"},{name:"H5",value:"h5"},{name:"H6",value:"h6"}]}]},{id:"image",fields:[{component:"reference",valueType:"string",name:"image",label:"Image",multi:!1},{component:"text",valueType:"string",name:"imageAlt",label:"Alt Text"}]},{id:"button",fields:[{component:"text",valueType:"string",name:"text",label:"Text"},{component:"aem-content",name:"href",label:"Link"},{component:"select",valueType:"string",name:"type",label:"Type",options:[{name:"Default",value:""},{name:"Primary",value:"primary"},{name:"Secondary",value:"secondary"}]}]}];Ti=`// Block: field-reference
332
328
  // A living reference of every Universal Editor field type (see _field-reference.json).
333
329
  // Authors use it to see what's available; delete it before launch.
334
330
  export default function decorate(block) {
@@ -337,29 +333,29 @@ export default function decorate(block) {
337
333
  // are what you drop and edit.
338
334
  block.classList.add('field-reference');
339
335
  }
340
- `,vi=`/* Block: field-reference */
336
+ `,Ri=`/* Block: field-reference */
341
337
  .field-reference {
342
338
  display: grid;
343
339
  gap: var(--spacing-m, 16px);
344
340
  padding: var(--spacing-l, 32px) 0;
345
341
  }
346
- `});var ee={};U(ee,{scaffoldBlocks:()=>ji,scaffoldCi:()=>$i,scaffoldEnv:()=>Ci,scaffoldHelpers:()=>Ei,scaffoldInteractive:()=>zs,scaffoldUe:()=>Et,scaffoldXwalk:()=>Pi});import{existsSync as xi}from"fs";import{mkdir as Si,readFile as Ws,writeFile as ge}from"fs/promises";import V from"path";async function jt(e){if(!xi(e))return null;try{return JSON.parse(await Ws(e,"utf-8"))}catch{return null}}async function $t(e,t){await ge(e,`${JSON.stringify(t,null,2)}
347
- `)}async function Et(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - Universal Editor"));let t=[],n=V.join(e,"blocks","field-reference");await Si(n,{recursive:!0}),await ge(V.join(n,"field-reference.js"),yi),await ge(V.join(n,"field-reference.css"),vi),await ge(V.join(n,"_field-reference.json"),dn()),t.push("blocks/field-reference/ (all 17 fields + multifield)");let o=V.join(e,"component-definition.json"),r=V.join(e,"component-models.json"),s=V.join(e,"component-filters.json"),a=[{title:"Field Reference",id:"field-reference",plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:"Field Reference",model:"field-reference"}}}}}],d=ki(await jt(o),bi,a);await $t(o,d),t.push("component-definition.json (default content + field-reference)");let c=await jt(r)??[],l=JSON.parse(dn()).models[0],u=mn(c,[...wi,l]);await $t(r,u),t.push("component-models.json (title / image / button / field-reference)");let m=qe(await jt(s),["field-reference"]);await $t(s,m),t.push("component-filters.json (section filter)"),i.info(j("Created / merged"));let f=t.map(v=>v.split(" ")[0]),$=M(f);for(let v of t){let[x,...g]=v.split(" ");i.info(k(x,g.join(" ").replace(/^\((.*)\)$/,"$1"),$))}i.info(""),i.info(O(["Universal Editor scaffold ready"]))}async function ji(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold \u2014 standard blocks"));let n;if(e?.length){n=e.map(l=>an(l.trim())).filter(l=>!!l);let c=e.filter(l=>!an(l.trim()));c.length&&i.warn(`Unknown block(s): ${c.join(", ")}. Available: ${fe.map(l=>l.id).join(", ")}`)}else n=fe;let o=[],r=[];for(let c of n){let l=V.join(t,"blocks",c.id);if(xi(l)){r.push(c.id);continue}await Si(l,{recursive:!0}),await ge(V.join(l,`${c.id}.js`),c.js),await ge(V.join(l,`${c.id}.css`),c.css),await ge(V.join(l,`_${c.id}.json`),c.model),o.push(c.id)}let s=V.join(t,"component-filters.json"),a=qe(await jt(s),n.map(c=>c.id));await $t(s,a),i.info(j("Blocks"));let d=M([...o,...r,"component-filters"]);for(let c of o)i.info(k(c,"created",d));for(let c of r)i.info(R("warn",c,"already exists \u2014 skipped",d));i.info(""),i.info(O([`${o.length} block(s) scaffolded + registered`]))}async function $i(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - CI workflow"));let t=await yt(e);i.info(j("GitHub Actions")),t.created?i.info(k(t.path,"doctor + audit loading + audit security + lint/build")):i.info(R("warn",t.path,"already exists - skipped")),i.info(""),i.info(O([t.created?"CI workflow scaffolded - commit it and it runs on every PR":"CI workflow left untouched"]))}async function Ei(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - helpers"));let n=e?.length?e:void 0;if(!n)if(process.stdout.isTTY){let{checkbox:r}=await import("@inquirer/prompts");n=await r({message:"Which helpers?",choices:ze.map(s=>({name:s.label,value:s.id,checked:!0}))})}else n=ln;if(!n.length){i.info("Nothing selected.");return}let o=await gi(t,n);i.info(j("Helpers")),o.created?i.info(k(o.path,o.helpers.join(", "))):i.info(R("warn",o.path,"already exists - skipped")),i.info(""),i.info(O([o.created?`${o.helpers.length} helper(s) -> scripts/utils.js`:"Helpers left untouched"]))}async function Ci(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - .env"));let n=e.pagesUrl;if(n===void 0)try{let{execa:a}=await import("execa"),d=await a("git",["remote","get-url","origin"],{cwd:t}),c=Ae(d.stdout.trim());n=c?`https://${Te(c.owner,c.repo)}`:""}catch{n=""}let o=e.open??"/",r=e.port??"3007";if(!e.yes&&process.stdout.isTTY){let{input:a}=await import("@inquirer/prompts");o=await a({message:"AEM_OPEN (path opened on start)",default:o}),r=await a({message:"AEM_PORT",default:String(r)}),n=await a({message:"AEM_PAGES_URL (content origin)",default:n})}let s=await vt(t,{open:o,port:r,pagesUrl:n});i.info(j(".env")),s.created?i.info(k(s.path,`AEM_OPEN=${o} AEM_PORT=${r}`)):i.info(R("warn",s.path,"already exists - left untouched")),s.gitignoreUpdated&&i.info(k(".gitignore","added .env")),i.info(""),i.info(O([s.created?".env ready for `aem up`":".env left untouched"]))}async function Pi(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - xwalk.json"));let t=await xt(e);i.info(j("xwalk.json")),t.created?i.info(k(t.path,"multi-field enabled")):i.info(R("warn",t.path,"already exists - left untouched")),i.info(""),i.info(O([t.created?"xwalk.json ready (UE multi-field)":"xwalk.json left untouched"]))}async function zs(){let{select:e,checkbox:t}=await import("@inquirer/prompts");i.logoOnce(P("Scaffold"));let n=await e({message:"What do you want to scaffold?",choices:[{name:"Universal Editor config + field-reference (all 17 field types)",value:"ue"},{name:"Standard blocks (hero, cards, columns, accordion, embed)",value:"blocks"},{name:"GitHub Actions CI (doctor + audits + lint/build)",value:"ci"},{name:"Helper functions (scripts/utils.js)",value:"helpers"},{name:"Local-dev .env (aem up: port / open / pages URL)",value:"env"},{name:"xwalk.json (enable Universal Editor multi-field)",value:"xwalk"},{name:"UE config + standard blocks",value:"both"}]});if(n==="env")return Ci();if(n==="xwalk")return Pi();if((n==="ue"||n==="both")&&await Et(),n==="blocks"||n==="both"){let o=await t({message:"Which blocks?",choices:fe.map(r=>({name:r.title,value:r.id,checked:!0}))});await ji(o)}n==="ci"&&await $i(),n==="helpers"&&await Ei()}var Z=b(()=>{"use strict";p();F();H();cn();nn();on();hi();pn();rn();St();I()});var Pt={};U(Pt,{initProject:()=>Ys});import{existsSync as fn}from"fs";import{readFile as gn,writeFile as Ai}from"fs/promises";import Ct from"path";import un from"chalk";async function qs(e){try{let{execa:t}=await import("execa"),n=await t("git",["remote","get-url","origin"],{cwd:e}),o=Ae(n.stdout.trim());return o?`https://${Te(o.owner,o.repo)}`:""}catch{return""}}async function Ks(e,t){let n=Ct.join(e,"package.json");if(!fn(n))return!1;try{let o=JSON.parse(await gn(n,"utf-8"));return o.name=t,await Ai(n,`${JSON.stringify(o,null,2)}
348
- `),!0}catch{return!1}}async function Xs(e,t){let n=[];for(let o of["README.md","index.html","head.html"]){let r=Ct.join(e,o);if(fn(r))try{let s=await gn(r,"utf-8"),a=s.replace(/aem-boilerplate/gi,t);a!==s&&(await Ai(r,a),n.push(o))}catch{}}return n}async function Vs(e){let{confirm:t}=await import("@inquirer/prompts"),n=[{title:"Install the AEM Code Sync GitHub app",url:"https://github.com/apps/aem-code-sync/installations/new",note:"Connects your repo to the Edge Delivery pipeline (preview/publish)."}];e==="gdrive"&&n.push({title:"Share your content folder",note:"Share the Google Drive folder with the AEM service and set it as the mountpoint."}),e==="sharepoint"&&n.push({title:"Share your content folder",note:"Grant the SharePoint/OneDrive folder to the AEM service account."}),e==="da"&&n.push({title:"Author in DA",url:"https://da.live",note:"Create documents at da.live."}),e==="ue"&&n.push({title:"Open the Universal Editor",url:"https://experience.adobe.com",note:"Author in-context once the repo is connected to AEM."}),n.push({title:"Install the AEM Sidekick extension",url:"https://chromewebstore.google.com/detail/aem-sidekick/igkmdomcgoebiipaifhmpfjhbjccggml",note:"Preview and publish from the browser."}),n.push({title:"Run the local dev server",note:"npm install, then `aem up` (from @adobe/aem-cli)."}),i.info(j("Next steps (outside the repo)"));for(let o=0;o<n.length;o++){let r=n[o];i.info(` ${L.accent(String(o+1))} ${un.bold(r.title)}`),r.url&&i.info(` ${un.cyan(r.url)}`),i.info(` ${un.dim(r.note)}`),await t({message:" Done / skip?",default:!0})}}async function Ys(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found). Clone an EDS boilerplate first, then run this from its root."),process.exitCode=1;return}await i.logoOnceAnimated("Project setup");let{input:n,select:o,confirm:r}=await import("@inquirer/prompts"),s=!e.yes,a=Ct.basename(t),d=Ct.join(t,"package.json");if(fn(d))try{a=JSON.parse(await gn(d,"utf-8")).name||a}catch{}let c=e.name&&Ke(e.name)||Ke(await n({message:"1/4 Project name",default:Ke(a),validate:x=>!!Ke(x)||"Use letters, numbers and dashes"})),l=e.authoring??await o({message:"2/4 Authoring model",choices:[{name:ue.ue,value:"ue"},{name:ue.da,value:"da"},{name:ue.gdrive,value:"gdrive"},{name:ue.sharepoint,value:"sharepoint"}]}),u=e.mountpoint;if(kt(l)&&!u)if(l==="da"&&(e.org||s)){let x=e.org??await n({message:" DA org",validate:h=>!!h.trim()||"Required"}),g=e.site??(s?await n({message:" DA site",default:c}):c);u=ii(x.trim(),Ke(g))}else l!=="da"&&s&&(u=(await n({message:` ${l==="gdrive"?"Google Drive folder URL":"SharePoint folder URL"}`,validate:g=>/^https?:\/\//.test(g.trim())||"Paste the folder URL"})).trim());let m=e.ci??(s?await r({message:"4/4 Add GitHub Actions CI (audits gatekeeper)?",default:!0}):!0);i.info(j("Summary"));let f=M(["name","authoring","mountpoint","ci"]);if(i.info(k("name",c,f)),i.info(k("authoring",ue[l],f)),u?i.info(k("mountpoint",u,f)):kt(l)&&i.info(k("mountpoint","(skipped - set it in fstab.yaml later)",f)),i.info(k("ci",m?"yes":"no",f)),i.info(""),s&&!await r({message:"Apply this setup?",default:!0})){i.info("Cancelled.");return}let $=[];await Ks(t,c)&&$.push("package.json (name)");for(let x of await Xs(t,c))$.push(`${x} (renamed)`);if(kt(l)&&u&&$.push(await ri(t,u)),l==="ue"&&(await Et(),$.push(await si(t,c))),m){let x=await yt(t);$.push(x.created?x.path:`${x.path} (exists, skipped)`)}if(e.env!==!1){let x=await vt(t,{pagesUrl:await qs(t)});$.push(x.created?".env (aem up config)":".env (exists, skipped)")}if(e.xwalk!==!1&&l==="ue"){let x=await xt(t);$.push(x.created?`${x.path} (UE multi-field)`:`${x.path} (exists, skipped)`)}i.info(j("Configured"));let v=M($.map(x=>x.split(" ")[0]));for(let x of $){let[g,...h]=x.split(" ");i.info(k(g,h.join(" ").replace(/^\((.*)\)$/,"$1"),v))}i.info(""),s&&await Vs(l),i.info(O([`"${c}" set up for ${ue[l]}`]))}var Ke,At=b(()=>{"use strict";p();F();H();nn();on();ai();rn();St();I();Z();Ke=e=>e.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")});var he={};U(he,{sandboxList:()=>ia,sandboxLogin:()=>ta,sandboxLogout:()=>na,sandboxNew:()=>oa,sandboxRm:()=>ra});import Qs from"path";import q from"chalk";async function te(e,t,n={}){let{execa:o}=await import("execa");return((await o(e,t,n)).stdout??"").toString().trim()}async function hn(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{await te(t,[e],{stdio:"ignore"})}catch{}}async function Zs(){try{return await te("gh",["auth","status"]),await te("gh",["api","user","-q",".login"])}catch{return null}}async function bn(){let e=await Bo();if(e)try{return{mode:"api",token:e,login:await bt(e)}}catch{}let t=await Zs();return t?{mode:"gh",login:t}:null}async function ea(e,t,n){if(e.mode==="api")return Do(e.token,t,n);try{return await te("gh",["repo","view",`${t}/${n}`,"--json","name"]),!0}catch{return!1}}function wn(){i.error("Not authenticated with GitHub."),i.info(" Run `eds sandbox login` to authorize GitHub, or install + `gh auth login`."),process.exitCode=1}async function ta(){await i.logoOnceAnimated("Sandbox - GitHub login");let{input:e}=await import("@inquirer/prompts");if(wt){let n=await Go(["repo","delete_repo"]);i.info(j("Authorize GitHub")),i.info(k("code",n.user_code)),i.info(k("open",n.verification_uri)),i.info(""),await hn(n.verification_uri),i.info(q.dim(" Waiting for you to authorize in the browser..."));try{let o=await Jo(n.device_code,n.interval,n.expires_in);await Qt(o),i.success(`Authorized as ${await bt(o)}.`)}catch(o){i.error(`Device flow failed: ${o.message}`),process.exitCode=1}return}i.info(j("Authorize GitHub (least-privilege token)")),i.info(" Create a fine-grained token limited to your sandboxes only:"),i.info(` ${q.cyan("https://github.com/settings/personal-access-tokens/new")}`),i.info(q.dim(" - Resource owner: a dedicated sandbox org (recommended) or your account")),i.info(q.dim(" - Repository access: All repositories in that org (to create new sandboxes),")),i.info(q.dim(" or Only select repositories to manage existing ones")),i.info(q.dim(" - Permissions: Administration = Read and write, Contents = Read and write,")),i.info(q.dim(" Metadata = Read. Set a short expiry.")),i.info(q.dim(" Tip: `eds sandbox new --org <sandbox-org>` so nothing in your personal account is touched.")),i.info(""),await(await import("@inquirer/prompts")).confirm({message:"Open the token page?",default:!0})&&await hn("https://github.com/settings/personal-access-tokens/new");let t=(await e({message:"Paste the token",validate:n=>!!n.trim()||"Required"})).trim();try{let n=await bt(t);await Qt(t),i.success(`Authorized as ${n}.`)}catch{i.error("That token didn't work (check the scopes)."),process.exitCode=1}}async function na(){await Ho(),i.success("Signed out (stored GitHub token removed).")}async function oa(e,t={}){let n=await bn();if(!n)return wn();await i.logoOnceAnimated("Sandbox");let o=!t.yes,{select:r,confirm:s}=await import("@inquirer/prompts"),a=t.boilerplate;a||(t.ue?a=Ge.ue:o?a=await r({message:"Which boilerplate?",choices:[{name:"Document Authoring (adobe/aem-boilerplate)",value:Ge.document},{name:"Universal Editor / crosswalk (adobe/aem-boilerplate-xwalk)",value:Ge.ue}]}):a=Ge.document);let d=t.private??!1;t.private===void 0&&o&&(d=await r({message:"Visibility?",choices:[{name:"Public",value:!1},{name:"Private",value:!0}],default:!1}));let c=t.org??n.login;if(await ea(n,c,e)){i.error(`A repository ${c}/${e} already exists - refusing to touch it.`),i.info(q.dim(" Pick another name, or remove it first (e.g. `eds sandbox rm` for a sandbox).")),process.exitCode=1;return}i.info(j("Creating sandbox",`${c}/${e} \xB7 ${a}`));try{if(n.mode==="api"){let l=await Lo(n.token,a,{owner:c,name:e,private:d});await Ro(n.token,c,e,[Ce]),i.info(q.dim(" Cloning...")),await te("git",["clone",l.cloneUrl,e],{stdio:"inherit"})}else{let l=t.org?`${t.org}/${e}`:e;await te("gh",zo(l,{template:a,private:d,clone:!0}),{stdio:"inherit"});try{await te("gh",["repo","edit",`${c}/${e}`,"--add-topic",Ce])}catch{}}}catch(l){i.error(`Create failed: ${l.message}`),process.exitCode=1;return}if(i.info(""),i.info(j("Sandbox ready")),i.info(k("repo",`https://github.com/${c}/${e}`)),i.info(k("preview",Zt(c,e))),i.info(""),o){if(await s({message:"Open the AEM Code Sync install page now?",default:!0})&&await hn(en()),await s({message:`Configure authoring now (eds init in ./${e})?`,default:!0})){let l=process.cwd();try{process.chdir(Qs.join(l,e));let{initProject:u}=await Promise.resolve().then(()=>(At(),Pt));await u({})}finally{process.chdir(l)}}}else i.info(q.dim(` Install AEM Code Sync: ${en()}`)),i.info(q.dim(` Configure authoring: cd ${e} && eds init`));i.info(""),i.info(O([`Sandbox "${e}" ready - tear down with \`eds sandbox rm ${e}\``]))}async function ia(){let e=await bn();if(!e)return wn();let t=[];try{if(e.mode==="api")t=await Mo(e.token,e.login,Ce);else{let o=await te("gh",["repo","list","--topic",Ce,"--limit","100","--json","nameWithOwner","-q",".[].nameWithOwner"]);t=o?o.split(`
349
- `).filter(Boolean):[]}}catch(o){i.error(`List failed: ${o.message}`),process.exitCode=1;return}if(i.info(j("Sandboxes",`${t.length} tagged ${Ce}`)),t.length===0){i.info(q.dim(" None yet. Create one with `eds sandbox new <name>`."));return}let n=M(t);for(let o of t){let[r,s]=o.split("/");i.info(k(o,Zt(r,s),n))}}async function ra(e,t={}){let n=await bn();if(!n)return wn();let o=t.org??n.login,r=`${o}/${e}`;if(!t.yes){let{confirm:s}=await import("@inquirer/prompts");if(!await s({message:`Permanently delete ${r}? This cannot be undone.`,default:!1})){i.info("Cancelled.");return}}try{n.mode==="api"?await Oo(n.token,o,e):await te("gh",["repo","delete",r,"--yes"])}catch(s){i.error(`Delete failed: ${s.message}`),i.info(q.dim(" Deleting needs the delete_repo scope (re-run `eds sandbox login`, or `gh auth refresh -s delete_repo`).")),process.exitCode=1;return}i.info(j("Deleted")),i.info(k(r,"removed"))}var be=b(()=>{"use strict";p();F();_o();Wo();qo();I()});import{existsSync as sa}from"fs";import{readFile as aa}from"fs/promises";import ca from"path";import{parse as la}from"yaml";async function Ti(e){let t=ca.join(e,"fstab.yaml");if(sa(t))try{let o=(la(await aa(t,"utf-8"))??{}).mountpoints?.["/"],r=typeof o=="string"?o:o?.url??"",s=r.match(/content\.da\.live\/([^/]+)\/([^/]+)/);return s?{model:"da",org:s[1],site:s[2],mountpoint:r}:/drive\.google\.com/.test(r)?{model:"gdrive",mountpoint:r}:/sharepoint\.com|-my\.sharepoint/.test(r)?{model:"sharepoint",mountpoint:r}:{model:"document",mountpoint:r}}catch{}return{model:"ue"}}var Fi=b(()=>{"use strict";p()});function da(e,t,n){let o=n.replace(/^\/+/,"").replace(/\.html$/i,"");return`https://admin.da.live/source/${e}/${t}/${o}.html`}function Di(e,t,n){let o=n.replace(/^\/+/,"").replace(/\.html$/i,"");return`https://da.live/edit#/${e}/${t}/${o}`}async function Li(e,t,n,o,r){let s=da(e,t,n),a=new FormData;a.append("data",new Blob([o],{type:"text/html"}),"content.html");let d={};r&&(d.Authorization=`Bearer ${r}`);let c=await fetch(s,{method:"POST",body:a,headers:d});if(!c.ok)throw new Error(`DA push failed: ${c.status} ${c.statusText}`);return s}var Ri=b(()=>{"use strict";p()});function ma(e){return` <div class="${e}">
342
+ `});var ce={};N(ce,{scaffoldBlocks:()=>Oi,scaffoldCi:()=>Mi,scaffoldEnv:()=>_i,scaffoldHelpers:()=>Ni,scaffoldInteractive:()=>Rs,scaffoldUe:()=>Ft,scaffoldXwalk:()=>Ii});import{existsSync as Fi}from"fs";import{mkdir as Li,readFile as Ts,writeFile as xe}from"fs/promises";import te from"path";async function Rt(e){if(!Fi(e))return null;try{return JSON.parse(await Ts(e,"utf-8"))}catch{return null}}async function Dt(e,t){await xe(e,`${JSON.stringify(t,null,2)}
343
+ `)}async function Ft(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - Universal Editor"));let t=[],n=te.join(e,"blocks","field-reference");await Li(n,{recursive:!0}),await xe(te.join(n,"field-reference.js"),Ti),await xe(te.join(n,"field-reference.css"),Ri),await xe(te.join(n,"_field-reference.json"),gn()),t.push("blocks/field-reference/ (all 17 fields + multifield)");let o=te.join(e,"component-definition.json"),r=te.join(e,"component-models.json"),a=te.join(e,"component-filters.json"),s=[{title:"Field Reference",id:"field-reference",plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:"Field Reference",model:"field-reference"}}}}}],d=Di(await Rt(o),Ci,s);await Dt(o,d),t.push("component-definition.json (default content + field-reference)");let l=await Rt(r)??[],c=JSON.parse(gn()).models[0],u=hn(l,[...Ai,c]);await Dt(r,u),t.push("component-models.json (title / image / button / field-reference)");let p=tt(await Rt(a),["field-reference"]);await Dt(a,p),t.push("component-filters.json (section filter)"),i.info(j("Created / merged"));let f=t.map(y=>y.split(" ")[0]),g=O(f);for(let y of t){let[h,...b]=y.split(" ");i.info($(h,b.join(" ").replace(/^\((.*)\)$/,"$1"),g))}i.info(""),i.info(L(["Universal Editor scaffold ready"]))}async function Oi(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold \u2014 standard blocks"));let n;if(e?.length){n=e.map(c=>mn(c.trim())).filter(c=>!!c);let l=e.filter(c=>!mn(c.trim()));l.length&&i.warn(`Unknown block(s): ${l.join(", ")}. Available: ${ke.map(c=>c.id).join(", ")}`)}else n=ke;let o=[],r=[];for(let l of n){let c=te.join(t,"blocks",l.id);if(Fi(c)){r.push(l.id);continue}await Li(c,{recursive:!0}),await xe(te.join(c,`${l.id}.js`),l.js),await xe(te.join(c,`${l.id}.css`),l.css),await xe(te.join(c,`_${l.id}.json`),l.model),o.push(l.id)}let a=te.join(t,"component-filters.json"),s=tt(await Rt(a),n.map(l=>l.id));await Dt(a,s),i.info(j("Blocks"));let d=O([...o,...r,"component-filters"]);for(let l of o)i.info($(l,"created",d));for(let l of r)i.info(D("warn",l,"already exists \u2014 skipped",d));i.info(""),i.info(L([`${o.length} block(s) scaffolded + registered`]))}async function Mi(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - CI workflow"));let t=await Et(e);i.info(j("GitHub Actions")),t.created?i.info($(t.path,"doctor + audit loading + audit security + lint/build")):i.info(D("warn",t.path,"already exists - skipped")),i.info(""),i.info(L([t.created?"CI workflow scaffolded - commit it and it runs on every PR":"CI workflow left untouched"]))}async function Ni(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - helpers"));let n=e?.length?e:void 0;if(!n)if(process.stdout.isTTY){let{checkbox:r}=await Promise.resolve().then(()=>(B(),U));n=await r({message:"Which helpers?",choices:et.map(a=>({name:a.label,value:a.id,checked:!0}))})}else n=fn;if(!n.length){i.info("Nothing selected.");return}let o=await Ei(t,n);i.info(j("Helpers")),o.created?i.info($(o.path,o.helpers.join(", "))):i.info(D("warn",o.path,"already exists - skipped")),i.info(""),i.info(L([o.created?`${o.helpers.length} helper(s) -> scripts/utils.js`:"Helpers left untouched"]))}async function _i(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - .env"));let n=e.pagesUrl;if(n===void 0)try{let{execa:s}=await import("execa"),d=await s("git",["remote","get-url","origin"],{cwd:t}),l=Ne(d.stdout.trim());n=l?`https://${_e(l.owner,l.repo)}`:""}catch{n=""}let o=e.open??"/",r=e.port??"3007";if(!e.yes&&process.stdout.isTTY){let{input:s}=await Promise.resolve().then(()=>(B(),U));o=await s({message:"AEM_OPEN (path opened on start)",default:o}),r=await s({message:"AEM_PORT",default:String(r)}),n=await s({message:"AEM_PAGES_URL (content origin)",default:n})}let a=await Pt(t,{open:o,port:r,pagesUrl:n});i.info(j(".env")),a.created?i.info($(a.path,`AEM_OPEN=${o} AEM_PORT=${r}`)):i.info(D("warn",a.path,"already exists - left untouched")),a.gitignoreUpdated&&i.info($(".gitignore","added .env")),i.info(""),i.info(L([a.created?".env ready for `aem up`":".env left untouched"]))}async function Ii(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Scaffold - xwalk.json"));let t=await At(e);i.info(j("xwalk.json")),t.created?i.info($(t.path,"multi-field enabled")):i.info(D("warn",t.path,"already exists - left untouched")),i.info(""),i.info(L([t.created?"xwalk.json ready (UE multi-field)":"xwalk.json left untouched"]))}async function Rs(){let{select:e,checkbox:t}=await Promise.resolve().then(()=>(B(),U));i.logoOnce(P("Scaffold"));let n=await e({message:"What do you want to scaffold?",choices:[{name:"Universal Editor config + field-reference (all 17 field types)",value:"ue"},{name:"Standard blocks (hero, cards, columns, accordion, embed)",value:"blocks"},{name:"GitHub Actions CI (doctor + audits + lint/build)",value:"ci"},{name:"Helper functions (scripts/utils.js)",value:"helpers"},{name:"Local-dev .env (aem up: port / open / pages URL)",value:"env"},{name:"xwalk.json (enable Universal Editor multi-field)",value:"xwalk"},{name:"UE config + standard blocks",value:"both"}]});if(n==="env")return _i();if(n==="xwalk")return Ii();if((n==="ue"||n==="both")&&await Ft(),n==="blocks"||n==="both"){let o=await t({message:"Which blocks?",choices:ke.map(r=>({name:r.title,value:r.id,checked:!0}))});await Oi(o)}n==="ci"&&await Mi(),n==="helpers"&&await Ni()}var re=w(()=>{"use strict";m();R();z();un();cn();ln();Pi();bn();dn();Tt();I()});var Ot={};N(Ot,{initProject:()=>Ms});import{existsSync as yn}from"fs";import{readFile as vn,writeFile as Ui}from"fs/promises";import Lt from"path";import wn from"chalk";async function Ds(e){try{let{execa:t}=await import("execa"),n=await t("git",["remote","get-url","origin"],{cwd:e}),o=Ne(n.stdout.trim());return o?`https://${_e(o.owner,o.repo)}`:""}catch{return""}}async function Fs(e,t){let n=Lt.join(e,"package.json");if(!yn(n))return!1;try{let o=JSON.parse(await vn(n,"utf-8"));return o.name=t,await Ui(n,`${JSON.stringify(o,null,2)}
344
+ `),!0}catch{return!1}}async function Ls(e,t){let n=[];for(let o of["README.md","index.html","head.html"]){let r=Lt.join(e,o);if(yn(r))try{let a=await vn(r,"utf-8"),s=a.replace(/aem-boilerplate/gi,t);s!==a&&(await Ui(r,s),n.push(o))}catch{}}return n}async function Os(e){let{confirm:t}=await Promise.resolve().then(()=>(B(),U)),n=[{title:"Install the AEM Code Sync GitHub app",url:"https://github.com/apps/aem-code-sync/installations/new",note:"Connects your repo to the Edge Delivery pipeline (preview/publish)."}];e==="gdrive"&&n.push({title:"Share your content folder",note:"Share the Google Drive folder with the AEM service and set it as the mountpoint."}),e==="sharepoint"&&n.push({title:"Share your content folder",note:"Grant the SharePoint/OneDrive folder to the AEM service account."}),e==="da"&&n.push({title:"Author in DA",url:"https://da.live",note:"Create documents at da.live."}),e==="ue"&&n.push({title:"Open the Universal Editor",url:"https://experience.adobe.com",note:"Author in-context once the repo is connected to AEM."}),n.push({title:"Install the AEM Sidekick extension",url:"https://chromewebstore.google.com/detail/aem-sidekick/igkmdomcgoebiipaifhmpfjhbjccggml",note:"Preview and publish from the browser."}),n.push({title:"Run the local dev server",note:"npm install, then `aem up` (from @adobe/aem-cli)."}),i.info(j("Next steps (outside the repo)"));for(let o=0;o<n.length;o++){let r=n[o];i.info(` ${_.accent(String(o+1))} ${wn.bold(r.title)}`),r.url&&i.info(` ${wn.cyan(r.url)}`),i.info(` ${wn.dim(r.note)}`),await t({message:" Done / skip?",default:!0})}}async function Ms(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found). Clone an EDS boilerplate first, then run this from its root."),process.exitCode=1;return}await i.logoOnceAnimated("Project setup");let{input:n,select:o,confirm:r}=await Promise.resolve().then(()=>(B(),U)),a=!e.yes,s=Lt.basename(t),d=Lt.join(t,"package.json");if(yn(d))try{s=JSON.parse(await vn(d,"utf-8")).name||s}catch{}let l=e.name&&nt(e.name)||nt(await n({message:"1/4 Project name",default:nt(s),validate:h=>!!nt(h)||"Use letters, numbers and dashes"})),c=e.authoring??await o({message:"2/4 Authoring model",choices:[{name:ve.ue,value:"ue"},{name:ve.da,value:"da"},{name:ve.gdrive,value:"gdrive"},{name:ve.sharepoint,value:"sharepoint"}]}),u=e.mountpoint;if(Ct(c)&&!u)if(c==="da"&&(e.org||a)){let h=e.org??await n({message:" DA org",validate:S=>!!S.trim()||"Required"}),b=e.site??(a?await n({message:" DA site",default:l}):l);u=gi(h.trim(),nt(b))}else c!=="da"&&a&&(u=(await n({message:` ${c==="gdrive"?"Google Drive folder URL":"SharePoint folder URL"}`,validate:b=>/^https?:\/\//.test(b.trim())||"Paste the folder URL"})).trim());let p=e.ci??(a?await r({message:"4/4 Add GitHub Actions CI (audits gatekeeper)?",default:!0}):!0);i.info(j("Summary"));let f=O(["name","authoring","mountpoint","ci"]);if(i.info($("name",l,f)),i.info($("authoring",ve[c],f)),u?i.info($("mountpoint",u,f)):Ct(c)&&i.info($("mountpoint","(skipped - set it in fstab.yaml later)",f)),i.info($("ci",p?"yes":"no",f)),i.info(""),a&&!await r({message:"Apply this setup?",default:!0})){i.info("Cancelled.");return}let g=[];await Fs(t,l)&&g.push("package.json (name)");for(let h of await Ls(t,l))g.push(`${h} (renamed)`);if(Ct(c)&&u&&g.push(await hi(t,u)),c==="ue"&&(await Ft(),g.push(await bi(t,l))),p){let h=await Et(t);g.push(h.created?h.path:`${h.path} (exists, skipped)`)}if(e.env!==!1){let h=await Pt(t,{pagesUrl:await Ds(t)});g.push(h.created?".env (aem up config)":".env (exists, skipped)")}if(e.xwalk!==!1&&c==="ue"){let h=await At(t);g.push(h.created?`${h.path} (UE multi-field)`:`${h.path} (exists, skipped)`)}i.info(j("Configured"));let y=O(g.map(h=>h.split(" ")[0]));for(let h of g){let[b,...S]=h.split(" ");i.info($(b,S.join(" ").replace(/^\((.*)\)$/,"$1"),y))}i.info(""),a&&await Os(c),i.info(L([`"${l}" set up for ${ve[c]}`]))}var nt,Mt=w(()=>{"use strict";m();R();z();cn();ln();wi();dn();Tt();I();re();nt=e=>e.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")});var $e={};N($e,{sandboxList:()=>Gs,sandboxLogin:()=>Us,sandboxLogout:()=>Bs,sandboxNew:()=>Hs,sandboxRm:()=>zs});import Ns from"path";import Z from"chalk";async function le(e,t,n={}){let{execa:o}=await import("execa");return((await o(e,t,n)).stdout??"").toString().trim()}async function kn(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{await le(t,[e],{stdio:"ignore"})}catch{}}async function _s(){try{return await le("gh",["auth","status"]),await le("gh",["api","user","-q",".login"])}catch{return null}}async function xn(){let e=await Qo();if(e)try{return{mode:"api",token:e,login:await $t(e)}}catch{}let t=await _s();return t?{mode:"gh",login:t}:null}async function Is(e,t,n){if(e.mode==="api")return Go(e.token,t,n);try{return await le("gh",["repo","view",`${t}/${n}`,"--json","name"]),!0}catch{return!1}}function $n(){i.error("Not authenticated with GitHub."),i.info(" Run `eds sandbox login` to authorize GitHub, or install + `gh auth login`."),process.exitCode=1}async function Us(){await i.logoOnceAnimated("Sandbox - GitHub login");let{input:e}=await Promise.resolve().then(()=>(B(),U));if(St){let n=await ei(["repo","delete_repo"]);i.info(j("Authorize GitHub")),i.info($("code",n.user_code)),i.info($("open",n.verification_uri)),i.info(""),await kn(n.verification_uri),i.info(Z.dim(" Waiting for you to authorize in the browser..."));try{let o=await ti(n.device_code,n.interval,n.expires_in);await on(o),i.success(`Authorized as ${await $t(o)}.`)}catch(o){i.error(`Device flow failed: ${o.message}`),process.exitCode=1}return}i.info(j("Authorize GitHub (least-privilege token)")),i.info(" Create a fine-grained token limited to your sandboxes only:"),i.info(` ${Z.cyan("https://github.com/settings/personal-access-tokens/new")}`),i.info(Z.dim(" - Resource owner: a dedicated sandbox org (recommended) or your account")),i.info(Z.dim(" - Repository access: All repositories in that org (to create new sandboxes),")),i.info(Z.dim(" or Only select repositories to manage existing ones")),i.info(Z.dim(" - Permissions: Administration = Read and write, Contents = Read and write,")),i.info(Z.dim(" Metadata = Read. Set a short expiry.")),i.info(Z.dim(" Tip: `eds sandbox new --org <sandbox-org>` so nothing in your personal account is touched.")),i.info(""),await(await Promise.resolve().then(()=>(B(),U))).confirm({message:"Open the token page?",default:!0})&&await kn("https://github.com/settings/personal-access-tokens/new");let t=(await e({message:"Paste the token",validate:n=>!!n.trim()||"Required"})).trim();try{let n=await $t(t);await on(t),i.success(`Authorized as ${n}.`)}catch{i.error("That token didn't work (check the scopes)."),process.exitCode=1}}async function Bs(){await Zo(),i.success("Signed out (stored GitHub token removed).")}async function Hs(e,t={}){let n=await xn();if(!n)return $n();await i.logoOnceAnimated("Sandbox");let o=!t.yes,{select:r,confirm:a}=await Promise.resolve().then(()=>(B(),U)),s=t.boilerplate;s||(t.ue?s=Ye.ue:o?s=await r({message:"Which boilerplate?",choices:[{name:"Document Authoring (adobe/aem-boilerplate)",value:Ye.document},{name:"Universal Editor / crosswalk (adobe/aem-boilerplate-xwalk)",value:Ye.ue}]}):s=Ye.document);let d=t.private??!1;t.private===void 0&&o&&(d=await r({message:"Visibility?",choices:[{name:"Public",value:!1},{name:"Private",value:!0}],default:!1}));let l=t.org??n.login;if(await Is(n,l,e)){i.error(`A repository ${l}/${e} already exists - refusing to touch it.`),i.info(Z.dim(" Pick another name, or remove it first (e.g. `eds sandbox rm` for a sandbox).")),process.exitCode=1;return}i.info(j("Creating sandbox",`${l}/${e} \xB7 ${s}`));try{if(n.mode==="api"){let c=await zo(n.token,s,{owner:l,name:e,private:d});await Jo(n.token,l,e,[Oe]),i.info(Z.dim(" Cloning...")),await le("git",["clone",c.cloneUrl,e],{stdio:"inherit"})}else{let c=t.org?`${t.org}/${e}`:e;await le("gh",oi(c,{template:s,private:d,clone:!0}),{stdio:"inherit"});try{await le("gh",["repo","edit",`${l}/${e}`,"--add-topic",Oe])}catch{}}}catch(c){i.error(`Create failed: ${c.message}`),process.exitCode=1;return}if(i.info(""),i.info(j("Sandbox ready")),i.info($("repo",`https://github.com/${l}/${e}`)),i.info($("preview",rn(l,e))),i.info(""),o){if(await a({message:"Open the AEM Code Sync install page now?",default:!0})&&await kn(an()),await a({message:`Configure authoring now (eds init in ./${e})?`,default:!0})){let c=process.cwd();try{process.chdir(Ns.join(c,e));let{initProject:u}=await Promise.resolve().then(()=>(Mt(),Ot));await u({})}finally{process.chdir(c)}}}else i.info(Z.dim(` Install AEM Code Sync: ${an()}`)),i.info(Z.dim(` Configure authoring: cd ${e} && eds init`));i.info(""),i.info(L([`Sandbox "${e}" ready - tear down with \`eds sandbox rm ${e}\``]))}async function Gs(){let e=await xn();if(!e)return $n();let t=[];try{if(e.mode==="api")t=await qo(e.token,e.login,Oe);else{let o=await le("gh",["repo","list","--topic",Oe,"--limit","100","--json","nameWithOwner","-q",".[].nameWithOwner"]);t=o?o.split(`
345
+ `).filter(Boolean):[]}}catch(o){i.error(`List failed: ${o.message}`),process.exitCode=1;return}if(i.info(j("Sandboxes",`${t.length} tagged ${Oe}`)),t.length===0){i.info(Z.dim(" None yet. Create one with `eds sandbox new <name>`."));return}let n=O(t);for(let o of t){let[r,a]=o.split("/");i.info($(o,rn(r,a),n))}}async function zs(e,t={}){let n=await xn();if(!n)return $n();let o=t.org??n.login,r=`${o}/${e}`;if(!t.yes){let{confirm:a}=await Promise.resolve().then(()=>(B(),U));if(!await a({message:`Permanently delete ${r}? This cannot be undone.`,default:!1})){i.info("Cancelled.");return}}try{n.mode==="api"?await Wo(n.token,o,e):await le("gh",["repo","delete",r,"--yes"])}catch(a){i.error(`Delete failed: ${a.message}`),i.info(Z.dim(" Deleting needs the delete_repo scope (re-run `eds sandbox login`, or `gh auth refresh -s delete_repo`).")),process.exitCode=1;return}i.info(j("Deleted")),i.info($(r,"removed"))}var Se=w(()=>{"use strict";m();R();Ko();ni();ii();I()});import{existsSync as Js}from"fs";import{readFile as Ws}from"fs/promises";import qs from"path";import{parse as Ks}from"yaml";async function Bi(e){let t=qs.join(e,"fstab.yaml");if(Js(t))try{let o=(Ks(await Ws(t,"utf-8"))??{}).mountpoints?.["/"],r=typeof o=="string"?o:o?.url??"",a=r.match(/content\.da\.live\/([^/]+)\/([^/]+)/);return a?{model:"da",org:a[1],site:a[2],mountpoint:r}:/drive\.google\.com/.test(r)?{model:"gdrive",mountpoint:r}:/sharepoint\.com|-my\.sharepoint/.test(r)?{model:"sharepoint",mountpoint:r}:{model:"document",mountpoint:r}}catch{}return{model:"ue"}}var Hi=w(()=>{"use strict";m()});function Xs(e,t,n){let o=n.replace(/^\/+/,"").replace(/\.html$/i,"");return`https://admin.da.live/source/${e}/${t}/${o}.html`}function Gi(e,t,n){let o=n.replace(/^\/+/,"").replace(/\.html$/i,"");return`https://da.live/edit#/${e}/${t}/${o}`}async function zi(e,t,n,o,r){let a=Xs(e,t,n),s=new FormData;s.append("data",new Blob([o],{type:"text/html"}),"content.html");let d={};r&&(d.Authorization=`Bearer ${r}`);let l=await fetch(a,{method:"POST",body:s,headers:d});if(!l.ok)throw new Error(`DA push failed: ${l.status} ${l.statusText}`);return a}var Ji=w(()=>{"use strict";m()});function Vs(e){return` <div class="${e}">
350
346
  <div>
351
347
  <div>${e} content</div>
352
348
  </div>
353
- </div>`}function pa(e){let t=[` <div><div>Title</div><div>${e.title}</div></div>`,` <div><div>Description</div><div>${e.description??""}</div></div>`];return e.area&&t.push(` <div><div>Template</div><div>${e.area}</div></div>`),` <div class="metadata">
349
+ </div>`}function Ys(e){let t=[` <div><div>Title</div><div>${e.title}</div></div>`,` <div><div>Description</div><div>${e.description??""}</div></div>`];return e.area&&t.push(` <div><div>Template</div><div>${e.area}</div></div>`),` <div class="metadata">
354
350
  ${t.join(`
355
351
  `)}
356
- </div>`}function Oi(e){let t=e.blocks??[],n=` <div>
352
+ </div>`}function Wi(e){let t=e.blocks??[],n=` <div>
357
353
  <h1>${e.title}</h1>
358
354
  <p>${e.description??"Intro copy goes here."}</p>
359
- </div>`,o=t.map(s=>` <div>
360
- ${ma(s)}
355
+ </div>`,o=t.map(a=>` <div>
356
+ ${Vs(a)}
361
357
  </div>`),r=` <div>
362
- ${pa(e)}
358
+ ${Ys(e)}
363
359
  </div>`;return`<body>
364
360
  <header></header>
365
361
  <main>
@@ -368,13 +364,13 @@ ${[n,...o,r].join(`
368
364
  </main>
369
365
  <footer></footer>
370
366
  </body>
371
- `}var Mi=b(()=>{"use strict";p()});import{existsSync as ua}from"fs";import{readFile as fa}from"fs/promises";import ga from"path";function ha(e){if(e.value!==void 0)return e.value;switch(e.valueType){case"boolean":return!1;case"number":return 0;case"string[]":return[];default:return""}}async function ba(e,t){let n=ga.join(e,"blocks",t,`_${t}.json`);if(!ua(n))return{};try{let o=JSON.parse(await fa(n,"utf-8")),r=Array.isArray(o.models)?o.models:[],a=(r.find(c=>c.id===t)??r[0])?.fields??[],d={};for(let c of a)c.component!=="tab"&&(d[c.name]=c.component==="container"?[]:ha(c));return d}catch{return{}}}async function _i(e,t){let n=[];for(let r of t.blocks)n.push({name:r,model:r,fields:await ba(e,r)});let o={title:t.title,template:t.name,components:n};return`${JSON.stringify(o,null,2)}
372
- `}var Ni=b(()=>{"use strict";p()});var kn={};U(kn,{templateNew:()=>ja});import{existsSync as vn}from"fs";import{mkdir as wa,readFile as Ui,readdir as ya,writeFile as yn}from"fs/promises";import re from"path";import Xe from"chalk";async function ka(e){let t=re.join(e,"blocks");return vn(t)?(await ya(t,{withFileTypes:!0})).filter(n=>n.isDirectory()).map(n=>n.name):[]}async function xa(e){let t=re.join(e,".edsrc.json");if(!vn(t))return{};try{return JSON.parse(await Ui(t,"utf-8")).admin??{}}catch{return{}}}async function Sa(e,t){if(!t.length)return!1;let n=re.join(e,"component-filters.json"),o=null;if(vn(n))try{o=JSON.parse(await Ui(n,"utf-8"))}catch{o=null}let r=qe(o,t);return await yn(n,`${JSON.stringify(r,null,2)}
373
- `),!0}async function ja(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await i.logoOnceAnimated("Page template");let{input:o,select:r,confirm:s}=await import("@inquirer/prompts"),a=!t.yes,d=await Ti(n),c=t.authoring??d.model,l=va(e),u=t.title??(a?await o({message:"Page title",default:e}):e),m=t.description??(a?await o({message:"Description (optional)"}):""),f=t.path??`/templates/${l}`,$=t.blocks;if(!$&&a){let h=await ka(n),S=h.length?h:fe.map(C=>C.id),A=[],Y=!0;for(;Y;){let C=await r({message:`Add a block in order (${A.length} so far)`,choices:[...S.map(X=>({name:X,value:X})),{name:A.length?"- done -":"- done (empty page) -",value:"__done"}]});C==="__done"?Y=!1:A.push(C)}$=A}let v=$??[],x=Oi({title:u,description:m||void 0,blocks:v,area:t.area}),g=re.join("templates",`${l}.html`);if(await wa(re.join(n,"templates"),{recursive:!0}),await yn(re.join(n,g),x),i.info(j("Page template",`${f} \xB7 ${c}`)),i.info(k(g,`${v.length} block(s) + metadata`)),c==="da"){let h=await xa(n),S=t.org??h.org??d.org,A=t.site??h.site??d.site;if(t.push??(a?await s({message:"Push to DA (da.live)?",default:!0}):!0))if(!S||!A)i.warn("No DA org/site. Pass --org/--site or set admin in .edsrc.json.");else try{await Li(S,A,f,x,process.env.DA_TOKEN),i.info(k("pushed to DA",Di(S,A,f)))}catch(C){i.error(`DA push failed: ${C.message}`),i.info(Xe.dim(" Open projects allow anonymous writes; others need DA_TOKEN."))}}else if(c==="gdrive"||c==="sharepoint"){let h=c==="gdrive"?"a Google Doc":"a Word doc";i.info(""),i.info(Xe.dim(` Document model: import ${g} into ${h} in your mounted folder,`)),i.info(Xe.dim(" then preview/publish. (Share the folder + install aem-code-sync first.)"))}else if(c==="ue"){let h=re.join("templates",`${l}.json`);await yn(re.join(n,h),await _i(n,{title:u,name:l,blocks:v})),i.info(k(h,`initial content (${v.length} component(s), in order)`)),await Sa(n,v)&&i.info(k("component-filters.json","seeded blocks allowed in Universal Editor")),i.info(""),i.info(Xe.dim(" Universal Editor: use the template JSON as the page's initial content, then")),i.info(Xe.dim(" author it in the Universal Editor (wire the repo to AEM)."))}i.info(""),i.info(O([`"${l}" template (${c}) - preview with \`eds preview ${f}\``]))}var va,xn=b(()=>{"use strict";p();F();H();cn();pn();Fi();Ri();Mi();Ni();I();va=e=>e.trim().toLowerCase().replace(/[^a-z0-9-/]+/g,"-").replace(/^-+|-+$/g,"")});import{existsSync as Tt}from"fs";import{readFile as Ii,readdir as Bi}from"fs/promises";import we from"path";async function $a(e){let t=[],n=async o=>{for(let r of await Bi(o,{withFileTypes:!0})){let s=we.join(o,r.name);r.isDirectory()?await n(s):t.push(s)}};return Tt(e)&&await n(e),t}async function Hi(e){if(!Tt(e))return null;let t=await Bi(e,{withFileTypes:!0}),n=t.find(r=>r.isDirectory()&&/clientlib/i.test(r.name));return n?we.join(e,n.name):t.some(r=>r.isFile()&&r.name.endsWith(".css"))?e:null}async function Gi(e){let t=await $a(e),n=t.filter(a=>/\.(less|scss|sass)$/i.test(a)).map(a=>we.relative(e,a)),o,r=we.join(e,"css.txt");if(Tt(r)){let a=(await Ii(r,"utf-8")).split(`
374
- `).map(l=>l.trim()),d=e,c=[];for(let l of a){if(!l)continue;let u=l.match(/^#base\s*=\s*(.+)$/);u?d=we.join(e,u[1].trim()):l.startsWith("#")||c.push(l)}o=c.map(l=>we.join(d,l)).filter(l=>Tt(l)&&l.endsWith(".css"))}else o=t.filter(a=>a.endsWith(".css"));let s=[];for(let a of o)s.push(await Ii(a,"utf-8"));return{css:s.join(`
367
+ `}var qi=w(()=>{"use strict";m()});import{existsSync as Qs}from"fs";import{readFile as Zs}from"fs/promises";import ec from"path";function tc(e){if(e.value!==void 0)return e.value;switch(e.valueType){case"boolean":return!1;case"number":return 0;case"string[]":return[];default:return""}}async function nc(e,t){let n=ec.join(e,"blocks",t,`_${t}.json`);if(!Qs(n))return{};try{let o=JSON.parse(await Zs(n,"utf-8")),r=Array.isArray(o.models)?o.models:[],s=(r.find(l=>l.id===t)??r[0])?.fields??[],d={};for(let l of s)l.component!=="tab"&&(d[l.name]=l.component==="container"?[]:tc(l));return d}catch{return{}}}async function Ki(e,t){let n=[];for(let r of t.blocks)n.push({name:r,model:r,fields:await nc(e,r)});let o={title:t.title,template:t.name,components:n};return`${JSON.stringify(o,null,2)}
368
+ `}var Xi=w(()=>{"use strict";m()});var En={};N(En,{templateNew:()=>lc});import{existsSync as jn}from"fs";import{mkdir as oc,readFile as Vi,readdir as ic,writeFile as Sn}from"fs/promises";import me from"path";import ot from"chalk";async function ac(e){let t=me.join(e,"blocks");return jn(t)?(await ic(t,{withFileTypes:!0})).filter(n=>n.isDirectory()).map(n=>n.name):[]}async function sc(e){let t=me.join(e,".edsrc.json");if(!jn(t))return{};try{return JSON.parse(await Vi(t,"utf-8")).admin??{}}catch{return{}}}async function cc(e,t){if(!t.length)return!1;let n=me.join(e,"component-filters.json"),o=null;if(jn(n))try{o=JSON.parse(await Vi(n,"utf-8"))}catch{o=null}let r=tt(o,t);return await Sn(n,`${JSON.stringify(r,null,2)}
369
+ `),!0}async function lc(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await i.logoOnceAnimated("Page template");let{input:o,select:r,confirm:a}=await Promise.resolve().then(()=>(B(),U)),s=!t.yes,d=await Bi(n),l=t.authoring??d.model,c=rc(e),u=t.title??(s?await o({message:"Page title",default:e}):e),p=t.description??(s?await o({message:"Description (optional)"}):""),f=t.path??`/templates/${c}`,g=t.blocks;if(!g&&s){let S=await ac(n),x=S.length?S:ke.map(H=>H.id),T=[],oe=!0;for(;oe;){let H=await r({message:`Add a block in order (${T.length} so far)`,choices:[...x.map(q=>({name:q,value:q})),{name:T.length?"- done -":"- done (empty page) -",value:"__done"}]});H==="__done"?oe=!1:T.push(H)}g=T}let y=g??[],h=Wi({title:u,description:p||void 0,blocks:y,area:t.area}),b=me.join("templates",`${c}.html`);if(await oc(me.join(n,"templates"),{recursive:!0}),await Sn(me.join(n,b),h),i.info(j("Page template",`${f} \xB7 ${l}`)),i.info($(b,`${y.length} block(s) + metadata`)),l==="da"){let S=await sc(n),x=t.org??S.org??d.org,T=t.site??S.site??d.site;if(t.push??(s?await a({message:"Push to DA (da.live)?",default:!0}):!0))if(!x||!T)i.warn("No DA org/site. Pass --org/--site or set admin in .edsrc.json.");else try{await zi(x,T,f,h,process.env.DA_TOKEN),i.info($("pushed to DA",Gi(x,T,f)))}catch(H){i.error(`DA push failed: ${H.message}`),i.info(ot.dim(" Open projects allow anonymous writes; others need DA_TOKEN."))}}else if(l==="gdrive"||l==="sharepoint"){let S=l==="gdrive"?"a Google Doc":"a Word doc";i.info(""),i.info(ot.dim(` Document model: import ${b} into ${S} in your mounted folder,`)),i.info(ot.dim(" then preview/publish. (Share the folder + install aem-code-sync first.)"))}else if(l==="ue"){let S=me.join("templates",`${c}.json`);await Sn(me.join(n,S),await Ki(n,{title:u,name:c,blocks:y})),i.info($(S,`initial content (${y.length} component(s), in order)`)),await cc(n,y)&&i.info($("component-filters.json","seeded blocks allowed in Universal Editor")),i.info(""),i.info(ot.dim(" Universal Editor: use the template JSON as the page's initial content, then")),i.info(ot.dim(" author it in the Universal Editor (wire the repo to AEM)."))}i.info(""),i.info(L([`"${c}" template (${l}) - preview with \`eds preview ${f}\``]))}var rc,Pn=w(()=>{"use strict";m();R();z();un();bn();Hi();Ji();qi();Xi();I();rc=e=>e.trim().toLowerCase().replace(/[^a-z0-9-/]+/g,"-").replace(/^-+|-+$/g,"")});import{existsSync as Nt}from"fs";import{readFile as Yi,readdir as Qi}from"fs/promises";import je from"path";async function dc(e){let t=[],n=async o=>{for(let r of await Qi(o,{withFileTypes:!0})){let a=je.join(o,r.name);r.isDirectory()?await n(a):t.push(a)}};return Nt(e)&&await n(e),t}async function Zi(e){if(!Nt(e))return null;let t=await Qi(e,{withFileTypes:!0}),n=t.find(r=>r.isDirectory()&&/clientlib/i.test(r.name));return n?je.join(e,n.name):t.some(r=>r.isFile()&&r.name.endsWith(".css"))?e:null}async function er(e){let t=await dc(e),n=t.filter(s=>/\.(less|scss|sass)$/i.test(s)).map(s=>je.relative(e,s)),o,r=je.join(e,"css.txt");if(Nt(r)){let s=(await Yi(r,"utf-8")).split(`
370
+ `).map(c=>c.trim()),d=e,l=[];for(let c of s){if(!c)continue;let u=c.match(/^#base\s*=\s*(.+)$/);u?d=je.join(e,u[1].trim()):c.startsWith("#")||l.push(c)}o=l.map(c=>je.join(d,c)).filter(c=>Nt(c)&&c.endsWith(".css"))}else o=t.filter(s=>s.endsWith(".css"));let a=[];for(let s of o)a.push(await Yi(s,"utf-8"));return{css:a.join(`
375
371
 
376
- `),files:o.map(a=>we.relative(e,a)),preprocessed:n}}var Ji=b(()=>{"use strict";p()});import{XMLParser as Ea}from"fast-xml-parser";function Ve(e){return Object.keys(e).find(t=>t!==":@")??""}function se(e){let t=Ve(e),n=e[t];return Array.isArray(n)?n:[]}function Ca(e){return e[":@"]??{}}function Pa(e){return typeof e=="string"?e.replace(/^\{[^}]+\}/,""):e}function z(e,t){return Pa(Ca(e)[`@_${t}`])}function Aa(e,t){let n=z(t,"multiple")==="true"||z(t,"multiple")==="{Boolean}true";return e.endsWith("/form/textfield")?"text":e.endsWith("/form/textarea")?"textarea":e.includes("/richtext")?"richtext":e.endsWith("/form/numberfield")?"number":e.endsWith("/form/checkbox")?"boolean":e.endsWith("/form/radiogroup")?"radio-group":e.endsWith("/form/select")?n?"multiselect":"select":e.endsWith("/form/datepicker")?"date-time":e.endsWith("/form/pathfield")||e.endsWith("/form/pathbrowser")?"aem-content":e.includes("/fileupload")||e.endsWith("/form/fileupload")?"reference":e.includes("tagfield")||e.includes("tagpicker")||e.includes("tagbrowser")?"aem-tag":e.includes("contentfragment")?"aem-content-fragment":e.includes("experiencefragment")?"aem-experience-fragment":null}function Ta(e){return e.includes("/foundation/container")||e.includes("/foundation/fixedcolumns")||e.includes("/foundation/well")||e.includes("/foundation/tabs")||e.includes("/foundation/form/fieldset")||e.includes("/foundation/accordion")}function Fa(e){switch(e){case"number":return"number";case"boolean":return"boolean";case"date-time":return"date";case"checkbox-group":return"string[]";case"aem-content":case"aem-content-fragment":case"aem-experience-fragment":return;default:return"string"}}function Sn(e,t){return(e??"").replace(/^\.\//,"").trim()||t}function Da(e){let t=se(e).find(n=>Ve(n)==="items");return t?se(t).map(n=>{let o=z(n,"value")??"";return{name:z(n,"text")??z(n,"jcr:title")??o,value:o}}):[]}function Ft(e,t,n,o){for(let r of e){let s=z(r,"sling:resourceType")??"";if(s.endsWith("/foundation/tabs")){let d=se(r).find(c=>Ve(c)==="items");for(let c of d?se(d):[]){let l=z(c,"jcr:title");t.push({component:"tab",name:Sn(void 0,Ve(c)),label:l}),Ft(se(c),t,n,o)}continue}if(s.endsWith("/form/multifield")){let d=[];Ft(se(r),d,n,o);let c=Sn(z(r,"name"),`items${o.i++}`);t.push({component:"container",name:c,label:z(r,"fieldLabel")??"Items",multi:!0,collapsible:!0,fields:d});continue}let a=s?Aa(s,r):null;if(a){let d=Sn(z(r,"name"),`field${o.i++}`),c={component:a,name:d},l=Fa(a);l&&(c.valueType=l);let u=z(r,"fieldLabel")??z(r,"text");if(u&&(c.label=u),a==="select"||a==="radio-group"||a==="multiselect"){let f=Da(r);f.length&&(c.options=f)}let m=z(r,"value")??(a==="boolean"?z(r,"checked"):void 0);m!==void 0&&m!==""&&(c.value=a==="boolean"?m==="true":m),t.push(c);continue}s&&z(r,"name")&&!Ta(s)&&n.add(s),Ft(se(r),t,n,o)}}function Wi(e){let o=new Ea({ignoreAttributes:!1,attributeNamePrefix:"@_",preserveOrder:!0,removeNSPrefix:!1,trimValues:!0}).parse(e).find(a=>Ve(a)==="jcr:root"),r=[],s=new Set;return o&&Ft(se(o),r,s,{i:1}),{fields:r,unmapped:[...s]}}var zi=b(()=>{"use strict";p()});import{existsSync as qi}from"fs";import{readFile as Ki}from"fs/promises";import Dt from"path";import{XMLParser as La}from"fast-xml-parser";function jn(e){return[Dt.join(e,"_cq_dialog",".content.xml"),Dt.join(e,"_cq_dialog.xml"),Dt.join(e,"cq:dialog",".content.xml")].find(n=>qi(n))??null}async function Xi(e){let t=Dt.join(e,".content.xml");if(qi(t))try{let s=(new La({ignoreAttributes:!1,attributeNamePrefix:"@_"}).parse(await Ki(t,"utf-8"))["jcr:root"]??{})["@_jcr:title"];return typeof s=="string"?s.replace(/^\{[^}]+\}/,""):void 0}catch{return}}async function Vi(e){let t=jn(e);return t?Wi(await Ki(t,"utf-8")):null}function Yi(e,t,n){return`${JSON.stringify({definitions:[{title:t,id:e,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:t,model:e}}}}}],models:[{id:e,fields:n}],filters:[]},null,2)}
377
- `}function Qi(e,t){let o=t.some(r=>r.component==="container"&&r.multi)?` // This block was migrated from a classic AEM component with a multifield.
372
+ `),files:o.map(s=>je.relative(e,s)),preprocessed:n}}var tr=w(()=>{"use strict";m()});import{XMLParser as pc}from"fast-xml-parser";function it(e){return Object.keys(e).find(t=>t!==":@")??""}function ue(e){let t=it(e),n=e[t];return Array.isArray(n)?n:[]}function mc(e){return e[":@"]??{}}function uc(e){return typeof e=="string"?e.replace(/^\{[^}]+\}/,""):e}function Y(e,t){return uc(mc(e)[`@_${t}`])}function fc(e,t){let n=Y(t,"multiple")==="true"||Y(t,"multiple")==="{Boolean}true";return e.endsWith("/form/textfield")?"text":e.endsWith("/form/textarea")?"textarea":e.includes("/richtext")?"richtext":e.endsWith("/form/numberfield")?"number":e.endsWith("/form/checkbox")?"boolean":e.endsWith("/form/radiogroup")?"radio-group":e.endsWith("/form/select")?n?"multiselect":"select":e.endsWith("/form/datepicker")?"date-time":e.endsWith("/form/pathfield")||e.endsWith("/form/pathbrowser")?"aem-content":e.includes("/fileupload")||e.endsWith("/form/fileupload")?"reference":e.includes("tagfield")||e.includes("tagpicker")||e.includes("tagbrowser")?"aem-tag":e.includes("contentfragment")?"aem-content-fragment":e.includes("experiencefragment")?"aem-experience-fragment":null}function gc(e){return e.includes("/foundation/container")||e.includes("/foundation/fixedcolumns")||e.includes("/foundation/well")||e.includes("/foundation/tabs")||e.includes("/foundation/form/fieldset")||e.includes("/foundation/accordion")}function hc(e){switch(e){case"number":return"number";case"boolean":return"boolean";case"date-time":return"date";case"checkbox-group":return"string[]";case"aem-content":case"aem-content-fragment":case"aem-experience-fragment":return;default:return"string"}}function Cn(e,t){return(e??"").replace(/^\.\//,"").trim()||t}function bc(e){let t=ue(e).find(n=>it(n)==="items");return t?ue(t).map(n=>{let o=Y(n,"value")??"";return{name:Y(n,"text")??Y(n,"jcr:title")??o,value:o}}):[]}function _t(e,t,n,o){for(let r of e){let a=Y(r,"sling:resourceType")??"";if(a.endsWith("/foundation/tabs")){let d=ue(r).find(l=>it(l)==="items");for(let l of d?ue(d):[]){let c=Y(l,"jcr:title");t.push({component:"tab",name:Cn(void 0,it(l)),label:c}),_t(ue(l),t,n,o)}continue}if(a.endsWith("/form/multifield")){let d=[];_t(ue(r),d,n,o);let l=Cn(Y(r,"name"),`items${o.i++}`);t.push({component:"container",name:l,label:Y(r,"fieldLabel")??"Items",multi:!0,collapsible:!0,fields:d});continue}let s=a?fc(a,r):null;if(s){let d=Cn(Y(r,"name"),`field${o.i++}`),l={component:s,name:d},c=hc(s);c&&(l.valueType=c);let u=Y(r,"fieldLabel")??Y(r,"text");if(u&&(l.label=u),s==="select"||s==="radio-group"||s==="multiselect"){let f=bc(r);f.length&&(l.options=f)}let p=Y(r,"value")??(s==="boolean"?Y(r,"checked"):void 0);p!==void 0&&p!==""&&(l.value=s==="boolean"?p==="true":p),t.push(l);continue}a&&Y(r,"name")&&!gc(a)&&n.add(a),_t(ue(r),t,n,o)}}function nr(e){let o=new pc({ignoreAttributes:!1,attributeNamePrefix:"@_",preserveOrder:!0,removeNSPrefix:!1,trimValues:!0}).parse(e).find(s=>it(s)==="jcr:root"),r=[],a=new Set;return o&&_t(ue(o),r,a,{i:1}),{fields:r,unmapped:[...a]}}var or=w(()=>{"use strict";m()});import{existsSync as ir}from"fs";import{readFile as rr}from"fs/promises";import It from"path";import{XMLParser as wc}from"fast-xml-parser";function An(e){return[It.join(e,"_cq_dialog",".content.xml"),It.join(e,"_cq_dialog.xml"),It.join(e,"cq:dialog",".content.xml")].find(n=>ir(n))??null}async function ar(e){let t=It.join(e,".content.xml");if(ir(t))try{let a=(new wc({ignoreAttributes:!1,attributeNamePrefix:"@_"}).parse(await rr(t,"utf-8"))["jcr:root"]??{})["@_jcr:title"];return typeof a=="string"?a.replace(/^\{[^}]+\}/,""):void 0}catch{return}}async function sr(e){let t=An(e);return t?nr(await rr(t,"utf-8")):null}function cr(e,t,n){return`${JSON.stringify({definitions:[{title:t,id:e,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:t,model:e}}}}}],models:[{id:e,fields:n}],filters:[]},null,2)}
373
+ `}function lr(e,t){let o=t.some(r=>r.component==="container"&&r.multi)?` // This block was migrated from a classic AEM component with a multifield.
378
374
  // Each child row is one repeated item - enhance them here.
379
375
  [...block.children].forEach((row) => {
380
376
  row.classList.add('${e}-item');
@@ -386,25 +382,25 @@ export default function decorate(block) {
386
382
  block.classList.add('${e}');
387
383
  ${o}
388
384
  }
389
- `}function Zi(e){return`/* Block: ${e} */
385
+ `}function dr(e){return`/* Block: ${e} */
390
386
  /* Migrated from a classic AEM component. Bring the component's styles here */
391
387
  /* (from its clientlib or the rendered page) and keep them scoped to the block. */
392
388
  .${e} {
393
389
  }
394
- `}var er=b(()=>{"use strict";p();zi()});function Ra(e,t,n){let o=[` // --- ${nr} ---`];return n.click&&o.push(` ${t}.addEventListener('click', (ev) => {`," const el = ev.target.closest('a, button');"," if (!el) return;",` trackEvent({ event: 'block_click', block: '${e}', label: el.dataset.track || el.textContent.trim() });`," });"),n.submit&&o.push(` ${t}.addEventListener('submit', () => {`,` trackEvent({ event: 'form_submit', block: '${e}' });`," });"),o.join(`
395
- `)}function or(e,t,n){if(e.includes(nr))return{js:e,changed:!1,reason:"already instrumented"};if(!n.click&&!n.submit)return{js:e,changed:!1,reason:"no events selected"};let o=e.match(/export default (?:async )?function decorate\s*\(\s*([A-Za-z_$][\w$]*)?[^)]*\)\s*\{/);if(!o||o.index===void 0)return{js:e,changed:!1,reason:"no `export default function decorate(...)` found"};let r=o[1]||"block",s=e;if(!s.includes("scripts/analytics.js")){let l=[...s.matchAll(/^import .*$/gm)];if(l.length){let u=l[l.length-1],m=(u.index??0)+u[0].length;s=`${s.slice(0,m)}
396
- ${tr}${s.slice(m)}`}else s=`${tr}
390
+ `}var pr=w(()=>{"use strict";m();or()});function yc(e,t,n){let o=[` // --- ${ur} ---`];return n.click&&o.push(` ${t}.addEventListener('click', (ev) => {`," const el = ev.target.closest('a, button');"," if (!el) return;",` trackEvent({ event: 'block_click', block: '${e}', label: el.dataset.track || el.textContent.trim() });`," });"),n.submit&&o.push(` ${t}.addEventListener('submit', () => {`,` trackEvent({ event: 'form_submit', block: '${e}' });`," });"),o.join(`
391
+ `)}function fr(e,t,n){if(e.includes(ur))return{js:e,changed:!1,reason:"already instrumented"};if(!n.click&&!n.submit)return{js:e,changed:!1,reason:"no events selected"};let o=e.match(/export default (?:async )?function decorate\s*\(\s*([A-Za-z_$][\w$]*)?[^)]*\)\s*\{/);if(!o||o.index===void 0)return{js:e,changed:!1,reason:"no `export default function decorate(...)` found"};let r=o[1]||"block",a=e;if(!a.includes("scripts/analytics.js")){let c=[...a.matchAll(/^import .*$/gm)];if(c.length){let u=c[c.length-1],p=(u.index??0)+u[0].length;a=`${a.slice(0,p)}
392
+ ${mr}${a.slice(p)}`}else a=`${mr}
397
393
 
398
- ${s}`}let a=s.match(/export default (?:async )?function decorate\s*\(\s*([A-Za-z_$][\w$]*)?[^)]*\)\s*\{/);if(!a||a.index===void 0)return{js:s,changed:!1,reason:"decorate not found"};let d=a.index+a[0].length,c=Ra(t,r,n);return s=`${s.slice(0,d)}
399
- ${c}
400
- ${s.slice(d)}`,{js:s,changed:!0}}var nr,tr,ir=b(()=>{"use strict";p();nr="analytics (eds track)",tr="import { trackEvent } from '../../scripts/analytics.js';"});var Ye={};U(Ye,{trackBlock:()=>Na});import{existsSync as rr}from"fs";import{readFile as Oa,writeFile as Ma}from"fs/promises";import sr from"path";import _a from"chalk";async function Na(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Track block"));let o=sr.join(n,"blocks",e,`${e}.js`);if(!rr(o)){i.error(`Block "${e}" not found (no blocks/${e}/${e}.js).`),process.exitCode=1;return}let r={click:t.click!==!1,submit:t.submit!==!1},s=or(await Oa(o,"utf-8"),e,r);if(!s.changed){i.warn(`Not instrumented: ${s.reason}.`);return}await Ma(o,s.js),i.info(j("Instrumented"));let a=[r.click?"block_click":null,r.submit?"form_submit":null].filter(Boolean);i.info(k(`blocks/${e}/${e}.js`,a.join(" + "))),rr(sr.join(n,"scripts","analytics.js"))||(i.info(""),i.warn("scripts/analytics.js is missing - run `eds integrate gtm` to create it.")),i.info(""),i.info(_a.dim(" Events push to window.dataLayer via trackEvent - GTM picks them up."))}var Qe=b(()=>{"use strict";p();F();H();ir();I()});var Cn={};U(Cn,{migrateComponent:()=>Ba});import{existsSync as $n}from"fs";import{mkdir as Ua,writeFile as En}from"fs/promises";import ye from"path";function Ia(e,t,n){return`/* Block: ${e} */
394
+ ${a}`}let s=a.match(/export default (?:async )?function decorate\s*\(\s*([A-Za-z_$][\w$]*)?[^)]*\)\s*\{/);if(!s||s.index===void 0)return{js:a,changed:!1,reason:"decorate not found"};let d=s.index+s[0].length,l=yc(t,r,n);return a=`${a.slice(0,d)}
395
+ ${l}
396
+ ${a.slice(d)}`,{js:a,changed:!0}}var ur,mr,gr=w(()=>{"use strict";m();ur="analytics (eds track)",mr="import { trackEvent } from '../../scripts/analytics.js';"});var rt={};N(rt,{trackBlock:()=>$c});import{existsSync as hr}from"fs";import{readFile as vc,writeFile as kc}from"fs/promises";import br from"path";import xc from"chalk";async function $c(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Track block"));let o=br.join(n,"blocks",e,`${e}.js`);if(!hr(o)){i.error(`Block "${e}" not found (no blocks/${e}/${e}.js).`),process.exitCode=1;return}let r={click:t.click!==!1,submit:t.submit!==!1},a=fr(await vc(o,"utf-8"),e,r);if(!a.changed){i.warn(`Not instrumented: ${a.reason}.`);return}await kc(o,a.js),i.info(j("Instrumented"));let s=[r.click?"block_click":null,r.submit?"form_submit":null].filter(Boolean);i.info($(`blocks/${e}/${e}.js`,s.join(" + "))),hr(br.join(n,"scripts","analytics.js"))||(i.info(""),i.warn("scripts/analytics.js is missing - run `eds integrate gtm` to create it.")),i.info(""),i.info(xc.dim(" Events push to window.dataLayer via trackEvent - GTM picks them up."))}var at=w(()=>{"use strict";m();R();z();gr();I()});var Dn={};N(Dn,{migrateComponent:()=>Ec});import{existsSync as Tn}from"fs";import{mkdir as Sc,writeFile as Rn}from"fs/promises";import Ee from"path";function jc(e,t,n){return`/* Block: ${e} */
401
397
  /* Migrated from the component clientlib: ${n.join(", ")}. */
402
398
  /* TODO: review selectors and scope them under .${e} (and port any LESS/SCSS). */
403
399
 
404
400
  ${t.trim()}
405
- `}function ar(e,t=0){let n=[];for(let o of e){let r=" ".repeat(t);if(o.component==="tab")n.push(`${r}${L.blue("\u25B8")} ${o.label??o.name}`);else{let s=o.options?.length?` (${o.options.length} options)`:"",a=o.multi?" \xB7multi":"",d=o.label?`- ${o.label}`:"";n.push(`${r}${L.accent(o.component)}${a} ${o.name}${s} ${d}`),o.fields?.length&&n.push(...ar(o.fields,t+1))}}return n}function cr(e){let t=0;for(let n of e)n.component!=="tab"&&(t+=1,n.fields&&(t+=cr(n.fields)));return t}async function Ba(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await i.logoOnceAnimated("Migrate component");let{input:o,confirm:r}=await import("@inquirer/prompts"),s=!t.yes,a=e;if(!a&&s&&(a=await o({message:"Path to the classic component folder",validate:h=>$n(h.trim())||"Folder not found"})),!a){i.error("Provide the path to the classic component folder."),process.exitCode=1;return}if(a=ye.resolve(a.trim()),!jn(a)){i.error(`No Touch UI dialog (_cq_dialog/.content.xml) found in ${a}.`),process.exitCode=1;return}let d=await Vi(a);if(!d||d.fields.length===0){i.warn("Dialog found but no mappable fields were detected."),d?.unmapped.length&&i.info(`Unmapped resourceTypes: ${d.unmapped.join(", ")}`),process.exitCode=1;return}let c=await Xi(a)??ye.basename(a),l=t.name&&Lt(t.name)||Lt(s?await o({message:"Block name",default:Lt(c)}):c);i.info(j("Mapped fields",`${cr(d.fields)} from dialog`));for(let h of ar(d.fields))i.info(` ${h}`);if(d.unmapped.length&&(i.info(""),i.warn(`Skipped (unrecognised): ${d.unmapped.join(", ")}`)),i.info(""),s&&!await r({message:`Generate block "${l}"?`,default:!0})){i.info("Cancelled.");return}let u=ye.join(n,"blocks",l);if($n(u)){i.error(`Block "${l}" already exists at blocks/${l}. Use --name to pick another.`),process.exitCode=1;return}let m=t.clientlib?ye.resolve(t.clientlib.trim()):await Hi(a),f=Zi(l),$="empty - add styles from clientlib / rendered CSS",v=[];if(m&&$n(m)){let h=await Gi(m);h.css.trim()&&(f=Ia(l,h.css,h.files),$=`from clientlib (${h.files.length} file(s)) - review & scope`),v=h.preprocessed}await Ua(u,{recursive:!0}),await En(ye.join(u,`${l}.js`),Qi(l,d.fields)),await En(ye.join(u,`${l}.css`),f),await En(ye.join(u,`_${l}.json`),Yi(l,c,d.fields)),i.info(j("Created"));let x=[`${l}.js`,`${l}.css`,`_${l}.json`],g=M(x);if(i.info(k(`${l}.js`,"decorator stub (port HTL logic)",g)),i.info(k(`${l}.css`,$,g)),i.info(k(`_${l}.json`,"Universal Editor model",g)),v.length&&(i.info(""),i.warn(`LESS/SCSS found (needs a build, not copied): ${v.join(", ")}`)),i.info(""),s&&await r({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:S}=await Promise.resolve().then(()=>(Qe(),Ye));await S(l,{})}i.info(O([`"${l}" migrated. Next: add CSS, then \`eds block preview ${l}\``]))}var Lt,Pn=b(()=>{"use strict";p();F();Ji();er();H();I();Lt=e=>e.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")});function W(e,t){return e?e+t.charAt(0).toUpperCase()+t.slice(1):t}var J,lr=b(()=>{"use strict";p();J={text:(e,t)=>({component:"text",valueType:"string",name:e,label:t}),textarea:(e,t)=>({component:"textarea",valueType:"string",name:e,label:t}),richtext:(e,t)=>({component:"richtext",valueType:"string",name:e,value:"",label:t}),number:(e,t)=>({component:"number",valueType:"number",name:e,label:t}),boolean:(e,t,n=!1)=>({component:"boolean",valueType:"boolean",name:e,value:n,label:t}),dateTime:(e,t)=>({component:"date-time",valueType:"date",name:e,label:t}),select:(e,t,n,o)=>({component:"select",valueType:"string",name:e,label:t,options:n,...o!==void 0?{value:o}:{}}),multiselect:(e,t,n)=>({component:"multiselect",valueType:"string",name:e,label:t,options:n}),radioGroup:(e,t,n,o)=>({component:"radio-group",valueType:"string",name:e,label:t,options:n,...o!==void 0?{value:o}:{}}),checkboxGroup:(e,t,n)=>({component:"checkbox-group",valueType:"string[]",name:e,label:t,options:n}),reference:(e,t)=>({component:"reference",valueType:"string",name:e,label:t}),aemContent:(e,t)=>({component:"aem-content",name:e,label:t}),aemContentFragment:(e,t)=>({component:"aem-content-fragment",name:e,label:t}),aemExperienceFragment:(e,t)=>({component:"aem-experience-fragment",name:e,label:t}),aemTag:(e,t)=>({component:"aem-tag",valueType:"string",name:e,label:t}),tab:(e,t)=>({component:"tab",name:e,label:t}),container:(e,t,n,o=!0)=>({component:"container",name:e,label:t,multi:!0,collapsible:o,fields:n})}});function Dn(e){return Fe.find(t=>t.id===e)}var Ha,Ga,Ja,Wa,dr,mr,An,pr,Tn,Fn,za,qa,Ka,Xa,Va,Fe,Ln=b(()=>{"use strict";p();lr();Ha=[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"},{name:"H5",value:"h5"},{name:"H6",value:"h6"}],Ga=[{name:"Same tab",value:"_self"},{name:"New tab",value:"_blank"}],Ja=[{name:"Default",value:""},{name:"Primary",value:"primary"},{name:"Secondary",value:"secondary"}],Wa=[{name:"Highlight",value:"highlight"},{name:"Dark",value:"dark"},{name:"Centered",value:"centered"},{name:"Full width",value:"full-width"}],dr=(e="")=>[J.text(W(e,"title"),"Title"),J.select(W(e,"titleType"),"Heading level",Ha,"h2")],mr=(e="")=>[J.text(W(e,"eyebrow"),"Eyebrow")],An=(e="")=>[J.reference(W(e,"image"),"Image"),J.text(W(e,"imageAlt"),"Alt text")],pr=(e="")=>[J.richtext(W(e,"text"),"Text")],Tn=(e="")=>[J.text(W(e,"linkText"),"Link text"),J.aemContent(W(e,"link"),"Link"),J.select(W(e,"linkTarget"),"Open in",Ga,"_self")],Fn=(e="")=>[...Tn(e),J.select(W(e,"ctaStyle"),"Style",Ja,"")],za=(e="")=>[J.container(W(e,"ctas")||"ctas","Buttons",Fn())],qa=(e="")=>[J.multiselect(W(e,"classes"),"Styles",Wa)],Ka=(e="")=>[J.aemContent(W(e,"url"),"URL (video / embed)")],Xa=(e="")=>[...An(e),...mr(e),...dr(e),...pr(e),...Fn(e)],Va=(e="")=>[...An(e),J.text(W(e,"title"),"Title"),J.richtext(W(e,"description"),"Description"),...Tn(e)],Fe=[{id:"heading",label:"Heading (title + level)",build:dr},{id:"eyebrow",label:"Eyebrow (kicker line)",build:mr},{id:"image",label:"Image (reference + alt)",build:An},{id:"richtext",label:"Rich text body",build:pr},{id:"link",label:"Link (text + url + target)",build:Tn},{id:"cta",label:"CTA (link + style)",build:Fn},{id:"cta-group",label:"CTA group (repeatable buttons)",build:za},{id:"classes",label:"Section styles (CSS modifiers)",build:qa},{id:"embed",label:"Embed / video (URL)",build:Ka},{id:"teaser",label:"Teaser (image + eyebrow + title + text + CTA)",build:Xa},{id:"card",label:"Card (image + title + description + link)",build:Va}]});var Mn={};U(Mn,{modelAdd:()=>Za});import{existsSync as Rn}from"fs";import{readFile as Ya,writeFile as Qa}from"fs/promises";import On from"path";async function Za(e,t,n={}){let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Model - add partials"));let{select:r,checkbox:s}=await import("@inquirer/prompts"),a=!n.yes,d=e;if(!d&&a){let{readdir:S}=await import("fs/promises"),A=On.join(o,"blocks"),Y=Rn(A)?(await S(A,{withFileTypes:!0})).filter(C=>C.isDirectory()&&Rn(On.join(A,C.name,`_${C.name}.json`))).map(C=>C.name):[];if(Y.length===0){i.error("No block with a _<name>.json model found. Create one with `eds block create`."),process.exitCode=1;return}d=await r({message:"Which block's model?",choices:Y.map(C=>({name:C,value:C}))})}if(!d){i.error("Provide a block name."),process.exitCode=1;return}let c=On.join(o,"blocks",d,`_${d}.json`);if(!Rn(c)){i.error(`No model at blocks/${d}/_${d}.json. Create the block first.`),process.exitCode=1;return}let l=t;l.length===0&&a&&(l=await s({message:"Which partials to add?",choices:Fe.map(S=>({name:S.label,value:S.id}))}));let u=l.map(S=>Dn(S.trim())).filter(S=>!!S),m=l.filter(S=>!Dn(S.trim()));if(m.length&&i.warn(`Unknown partial(s): ${m.join(", ")}. Available: ${Fe.map(S=>S.id).join(", ")}`),u.length===0){i.info("Nothing to add.");return}let f;try{f=JSON.parse(await Ya(c,"utf-8"))}catch{i.error(`Could not parse ${c}.`),process.exitCode=1;return}let $=Array.isArray(f.models)?f.models:[],v=$.find(S=>S.id===d)??$[0];if(!v){i.error("Model has no `models[]` entry to add fields to."),process.exitCode=1;return}v.fields=Array.isArray(v.fields)?v.fields:[];let x=new Set(v.fields.map(S=>S.name)),g=[],h=[];for(let S of u)for(let A of S.build()){if(x.has(A.name)){h.push(A.name);continue}x.add(A.name),v.fields.push(A),g.push(A.name)}await Qa(c,`${JSON.stringify(f,null,2)}
406
- `),i.info(j("Model updated",`blocks/${d}/_${d}.json`)),i.info(k("partials",u.map(S=>S.id).join(", "))),i.info(k("fields added",g.length?g.join(", "):"(none)")),h.length&&i.info(R("warn","skipped (exists)",h.join(", "))),i.info(""),i.info(O([`${g.length} field(s) added to "${d}"`]))}var _n=b(()=>{"use strict";p();F();Ln();H();I()});function fr(e){return Rt.find(t=>t.id.toLowerCase()===e.toLowerCase())}function gr(e,t){if(e.includes(ur))return{js:e,changed:!1,reason:"already has JSON-LD"};let n=e.match(/export default (?:async )?function decorate\s*\(\s*([A-Za-z_$][\w$]*)?[^)]*\)\s*\{/);if(!n||n.index===void 0)return{js:e,changed:!1,reason:"no `export default function decorate(...)` found"};let o=n[1]||"block",r=n.index+n[0].length,s=`
407
- // --- ${ur}: ${t.id}) ---
401
+ `}function wr(e,t=0){let n=[];for(let o of e){let r=" ".repeat(t);if(o.component==="tab")n.push(`${r}${_.blue("\u25B8")} ${o.label??o.name}`);else{let a=o.options?.length?` (${o.options.length} options)`:"",s=o.multi?" \xB7multi":"",d=o.label?`- ${o.label}`:"";n.push(`${r}${_.accent(o.component)}${s} ${o.name}${a} ${d}`),o.fields?.length&&n.push(...wr(o.fields,t+1))}}return n}function yr(e){let t=0;for(let n of e)n.component!=="tab"&&(t+=1,n.fields&&(t+=yr(n.fields)));return t}async function Ec(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await i.logoOnceAnimated("Migrate component");let{input:o,confirm:r}=await Promise.resolve().then(()=>(B(),U)),a=!t.yes,s=e;if(!s&&a&&(s=await o({message:"Path to the classic component folder",validate:S=>Tn(S.trim())||"Folder not found"})),!s){i.error("Provide the path to the classic component folder."),process.exitCode=1;return}if(s=Ee.resolve(s.trim()),!An(s)){i.error(`No Touch UI dialog (_cq_dialog/.content.xml) found in ${s}.`),process.exitCode=1;return}let d=await sr(s);if(!d||d.fields.length===0){i.warn("Dialog found but no mappable fields were detected."),d?.unmapped.length&&i.info(`Unmapped resourceTypes: ${d.unmapped.join(", ")}`),process.exitCode=1;return}let l=await ar(s)??Ee.basename(s),c=t.name&&Ut(t.name)||Ut(a?await o({message:"Block name",default:Ut(l)}):l);i.info(j("Mapped fields",`${yr(d.fields)} from dialog`));for(let S of wr(d.fields))i.info(` ${S}`);if(d.unmapped.length&&(i.info(""),i.warn(`Skipped (unrecognised): ${d.unmapped.join(", ")}`)),i.info(""),a&&!await r({message:`Generate block "${c}"?`,default:!0})){i.info("Cancelled.");return}let u=Ee.join(n,"blocks",c);if(Tn(u)){i.error(`Block "${c}" already exists at blocks/${c}. Use --name to pick another.`),process.exitCode=1;return}let p=t.clientlib?Ee.resolve(t.clientlib.trim()):await Zi(s),f=dr(c),g="empty - add styles from clientlib / rendered CSS",y=[];if(p&&Tn(p)){let S=await er(p);S.css.trim()&&(f=jc(c,S.css,S.files),g=`from clientlib (${S.files.length} file(s)) - review & scope`),y=S.preprocessed}await Sc(u,{recursive:!0}),await Rn(Ee.join(u,`${c}.js`),lr(c,d.fields)),await Rn(Ee.join(u,`${c}.css`),f),await Rn(Ee.join(u,`_${c}.json`),cr(c,l,d.fields)),i.info(j("Created"));let h=[`${c}.js`,`${c}.css`,`_${c}.json`],b=O(h);if(i.info($(`${c}.js`,"decorator stub (port HTL logic)",b)),i.info($(`${c}.css`,g,b)),i.info($(`_${c}.json`,"Universal Editor model",b)),y.length&&(i.info(""),i.warn(`LESS/SCSS found (needs a build, not copied): ${y.join(", ")}`)),i.info(""),a&&await r({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:x}=await Promise.resolve().then(()=>(at(),rt));await x(c,{})}i.info(L([`"${c}" migrated. Next: add CSS, then \`eds block preview ${c}\``]))}var Ut,Fn=w(()=>{"use strict";m();R();tr();pr();z();I();Ut=e=>e.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")});function V(e,t){return e?e+t.charAt(0).toUpperCase()+t.slice(1):t}var X,vr=w(()=>{"use strict";m();X={text:(e,t)=>({component:"text",valueType:"string",name:e,label:t}),textarea:(e,t)=>({component:"textarea",valueType:"string",name:e,label:t}),richtext:(e,t)=>({component:"richtext",valueType:"string",name:e,value:"",label:t}),number:(e,t)=>({component:"number",valueType:"number",name:e,label:t}),boolean:(e,t,n=!1)=>({component:"boolean",valueType:"boolean",name:e,value:n,label:t}),dateTime:(e,t)=>({component:"date-time",valueType:"date",name:e,label:t}),select:(e,t,n,o)=>({component:"select",valueType:"string",name:e,label:t,options:n,...o!==void 0?{value:o}:{}}),multiselect:(e,t,n)=>({component:"multiselect",valueType:"string",name:e,label:t,options:n}),radioGroup:(e,t,n,o)=>({component:"radio-group",valueType:"string",name:e,label:t,options:n,...o!==void 0?{value:o}:{}}),checkboxGroup:(e,t,n)=>({component:"checkbox-group",valueType:"string[]",name:e,label:t,options:n}),reference:(e,t)=>({component:"reference",valueType:"string",name:e,label:t}),aemContent:(e,t)=>({component:"aem-content",name:e,label:t}),aemContentFragment:(e,t)=>({component:"aem-content-fragment",name:e,label:t}),aemExperienceFragment:(e,t)=>({component:"aem-experience-fragment",name:e,label:t}),aemTag:(e,t)=>({component:"aem-tag",valueType:"string",name:e,label:t}),tab:(e,t)=>({component:"tab",name:e,label:t}),container:(e,t,n,o=!0)=>({component:"container",name:e,label:t,multi:!0,collapsible:o,fields:n})}});function Nn(e){return Ie.find(t=>t.id===e)}var Pc,Cc,Ac,Tc,kr,xr,Ln,$r,On,Mn,Rc,Dc,Fc,Lc,Oc,Ie,_n=w(()=>{"use strict";m();vr();Pc=[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"},{name:"H5",value:"h5"},{name:"H6",value:"h6"}],Cc=[{name:"Same tab",value:"_self"},{name:"New tab",value:"_blank"}],Ac=[{name:"Default",value:""},{name:"Primary",value:"primary"},{name:"Secondary",value:"secondary"}],Tc=[{name:"Highlight",value:"highlight"},{name:"Dark",value:"dark"},{name:"Centered",value:"centered"},{name:"Full width",value:"full-width"}],kr=(e="")=>[X.text(V(e,"title"),"Title"),X.select(V(e,"titleType"),"Heading level",Pc,"h2")],xr=(e="")=>[X.text(V(e,"eyebrow"),"Eyebrow")],Ln=(e="")=>[X.reference(V(e,"image"),"Image"),X.text(V(e,"imageAlt"),"Alt text")],$r=(e="")=>[X.richtext(V(e,"text"),"Text")],On=(e="")=>[X.text(V(e,"linkText"),"Link text"),X.aemContent(V(e,"link"),"Link"),X.select(V(e,"linkTarget"),"Open in",Cc,"_self")],Mn=(e="")=>[...On(e),X.select(V(e,"ctaStyle"),"Style",Ac,"")],Rc=(e="")=>[X.container(V(e,"ctas")||"ctas","Buttons",Mn())],Dc=(e="")=>[X.multiselect(V(e,"classes"),"Styles",Tc)],Fc=(e="")=>[X.aemContent(V(e,"url"),"URL (video / embed)")],Lc=(e="")=>[...Ln(e),...xr(e),...kr(e),...$r(e),...Mn(e)],Oc=(e="")=>[...Ln(e),X.text(V(e,"title"),"Title"),X.richtext(V(e,"description"),"Description"),...On(e)],Ie=[{id:"heading",label:"Heading (title + level)",build:kr},{id:"eyebrow",label:"Eyebrow (kicker line)",build:xr},{id:"image",label:"Image (reference + alt)",build:Ln},{id:"richtext",label:"Rich text body",build:$r},{id:"link",label:"Link (text + url + target)",build:On},{id:"cta",label:"CTA (link + style)",build:Mn},{id:"cta-group",label:"CTA group (repeatable buttons)",build:Rc},{id:"classes",label:"Section styles (CSS modifiers)",build:Dc},{id:"embed",label:"Embed / video (URL)",build:Fc},{id:"teaser",label:"Teaser (image + eyebrow + title + text + CTA)",build:Lc},{id:"card",label:"Card (image + title + description + link)",build:Oc}]});var Bn={};N(Bn,{modelAdd:()=>_c});import{existsSync as In}from"fs";import{readFile as Mc,writeFile as Nc}from"fs/promises";import Un from"path";async function _c(e,t,n={}){let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Model - add partials"));let{select:r,checkbox:a}=await Promise.resolve().then(()=>(B(),U)),s=!n.yes,d=e;if(!d&&s){let{readdir:x}=await import("fs/promises"),T=Un.join(o,"blocks"),oe=In(T)?(await x(T,{withFileTypes:!0})).filter(H=>H.isDirectory()&&In(Un.join(T,H.name,`_${H.name}.json`))).map(H=>H.name):[];if(oe.length===0){i.error("No block with a _<name>.json model found. Create one with `eds block create`."),process.exitCode=1;return}d=await r({message:"Which block's model?",choices:oe.map(H=>({name:H,value:H}))})}if(!d){i.error("Provide a block name."),process.exitCode=1;return}let l=Un.join(o,"blocks",d,`_${d}.json`);if(!In(l)){i.error(`No model at blocks/${d}/_${d}.json. Create the block first.`),process.exitCode=1;return}let c=t;c.length===0&&s&&(c=await a({message:"Which partials to add?",choices:Ie.map(x=>({name:x.label,value:x.id}))}));let u=c.map(x=>Nn(x.trim())).filter(x=>!!x),p=c.filter(x=>!Nn(x.trim()));if(p.length&&i.warn(`Unknown partial(s): ${p.join(", ")}. Available: ${Ie.map(x=>x.id).join(", ")}`),u.length===0){i.info("Nothing to add.");return}let f;try{f=JSON.parse(await Mc(l,"utf-8"))}catch{i.error(`Could not parse ${l}.`),process.exitCode=1;return}let g=Array.isArray(f.models)?f.models:[],y=g.find(x=>x.id===d)??g[0];if(!y){i.error("Model has no `models[]` entry to add fields to."),process.exitCode=1;return}y.fields=Array.isArray(y.fields)?y.fields:[];let h=new Set(y.fields.map(x=>x.name)),b=[],S=[];for(let x of u)for(let T of x.build()){if(h.has(T.name)){S.push(T.name);continue}h.add(T.name),y.fields.push(T),b.push(T.name)}await Nc(l,`${JSON.stringify(f,null,2)}
402
+ `),i.info(j("Model updated",`blocks/${d}/_${d}.json`)),i.info($("partials",u.map(x=>x.id).join(", "))),i.info($("fields added",b.length?b.join(", "):"(none)")),S.length&&i.info(D("warn","skipped (exists)",S.join(", "))),i.info(""),i.info(L([`${b.length} field(s) added to "${d}"`]))}var Hn=w(()=>{"use strict";m();R();_n();z();I()});function jr(e){return Bt.find(t=>t.id.toLowerCase()===e.toLowerCase())}function Er(e,t){if(e.includes(Sr))return{js:e,changed:!1,reason:"already has JSON-LD"};let n=e.match(/export default (?:async )?function decorate\s*\(\s*([A-Za-z_$][\w$]*)?[^)]*\)\s*\{/);if(!n||n.index===void 0)return{js:e,changed:!1,reason:"no `export default function decorate(...)` found"};let o=n[1]||"block",r=n.index+n[0].length,a=`
403
+ // --- ${Sr}: ${t.id}) ---
408
404
  {
409
405
  const root = ${o};
410
406
  const ld = ${t.object};
@@ -413,7 +409,7 @@ ${t.trim()}
413
409
  ldScript.textContent = JSON.stringify(ld);
414
410
  document.head.append(ldScript);
415
411
  }
416
- `;return{js:`${e.slice(0,r)}${s}${e.slice(r)}`,changed:!0}}var ur,Rt,hr=b(()=>{"use strict";p();ur="json-ld (eds schema",Rt=[{id:"Article",label:"Article / BlogPosting",object:`{
412
+ `;return{js:`${e.slice(0,r)}${a}${e.slice(r)}`,changed:!0}}var Sr,Bt,Pr=w(()=>{"use strict";m();Sr="json-ld (eds schema",Bt=[{id:"Article",label:"Article / BlogPosting",object:`{
417
413
  '@context': 'https://schema.org',
418
414
  '@type': 'Article',
419
415
  headline: root.querySelector('h1, h2, h3')?.textContent?.trim() || document.title,
@@ -492,16 +488,16 @@ ${t.trim()}
492
488
  position: i + 1,
493
489
  text: li.textContent?.trim(),
494
490
  })),
495
- }`}]});var Nn={};U(Nn,{schemaBlock:()=>rc});import{existsSync as ec}from"fs";import{readFile as tc,writeFile as nc}from"fs/promises";import oc from"path";import ic from"chalk";async function rc(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Schema - JSON-LD"));let o=oc.join(n,"blocks",e,`${e}.js`);if(!ec(o)){i.error(`Block "${e}" not found (no blocks/${e}/${e}.js).`),process.exitCode=1;return}let r=t.type;if(!r&&!t.yes){let{select:d}=await import("@inquirer/prompts");r=await d({message:"Which schema.org type?",choices:Rt.map(c=>({name:`${c.id} - ${c.label}`,value:c.id}))})}let s=r?fr(r):void 0;if(!s){i.error(`Unknown schema type "${r}". Options: ${Rt.map(d=>d.id).join(", ")}`),process.exitCode=1;return}let a=gr(await tc(o,"utf-8"),s);if(!a.changed){i.warn(`Not added: ${a.reason}.`);return}await nc(o,a.js),i.info(j("JSON-LD added")),i.info(k(`blocks/${e}/${e}.js`,`${s.id} (${s.label})`)),i.info(""),i.info(ic.dim(" Review the generated object - some fields are heuristic or TODO. Validate at search.google.com/test/rich-results."))}var Un=b(()=>{"use strict";p();F();H();hr();I()});function ac(e,t){for(let n of e.match(/<meta\b[^>]*>/gi)??[])if(n.match(/\bname=["']([^"']+)["']/i)?.[1]===t)return n.match(/\bcontent=["']([^"']*)["']/i)?.[1]??"";return null}function br(e){return ac(e,sc)!==null}function wr(e){return Array.isArray(e)?e.map(t=>t&&typeof t=="object"?t.id:void 0).filter(t=>typeof t=="string"):[]}function yr(e){let t=!!e.configPresent["component-definition.json"]&&!!e.configPresent["component-models.json"],n=new Set(e.modelIds),o=e.blocks.map(r=>{let s=r.hasModelFile||n.has(r.name);return{name:r.name,editable:s,reason:s?void 0:"no UE model (_<name>.json or component-models entry)"}});return{isUeProject:t,blocks:o}}var In,sc,vr=b(()=>{"use strict";p();In=["component-definition.json","component-models.json","component-filters.json"],sc="urn:adobe:aue:system:aemconnection"});var tt={};U(tt,{ueCheck:()=>uc,ueOpen:()=>fc});import{existsSync as et}from"fs";import{readFile as kr,readdir as cc}from"fs/promises";import Ze from"path";import Ot from"chalk";async function lc(e){if(!et(e))return null;try{return JSON.parse(await kr(e,"utf-8"))}catch{return null}}async function dc(e){let t=Ze.join(e,"blocks");return et(t)?(await cc(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>({name:o.name,hasModelFile:et(Ze.join(t,o.name,`_${o.name}.json`))})):[]}async function mc(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{let{execa:n}=await import("execa");await n(t,[e],{stdio:"ignore"})}catch{}}async function pc(e){try{let{execa:t}=await import("execa");return(await t("git",["remote","get-url","origin"],{cwd:e})).stdout.trim()||null}catch{return null}}async function uc(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Universal Editor - readiness"));let t={};for(let m of In)t[m]=et(Ze.join(e,m));let n=await lc(Ze.join(e,"component-models.json")),o=await dc(e),{isUeProject:r,blocks:s}=yr({configPresent:t,blocks:o,modelIds:wr(n)});i.info(j("Universal Editor config"));let a=[...In],d=M(a);for(let m of a)i.info(R(t[m]?"pass":"fail",m,void 0,d));if(!r){i.info(""),i.warn("This doesn't look like a Universal Editor (crosswalk) project - run `eds scaffold ue` first."),process.exitCode=1;return}let c=Ze.join(e,"head.html");if(et(c)){let m=br(await kr(c,"utf-8"));i.info(R(m?"pass":"info","head.html",m?"aemconnection present":"no aemconnection (fine for cloud author)"))}if(i.info(j("Blocks",`${s.length} found`)),s.length===0)i.info(Ot.dim(" No blocks yet."));else{let m=M(s.map(f=>f.name));for(let f of s)i.info(R(f.editable?"pass":"warn",f.name,f.reason,m))}let l=s.filter(m=>m.editable).length,u=s.length-l;i.info(""),i.info(oe({pass:l,warn:u})),i.info(Ot.dim(" Open a page in the editor with `eds ue open <path>`."))}async function fc(e,t={}){let n=E()??process.cwd(),o=e??t.path??"/",r=t.url;if(!r){let a=await pc(n),d=a?Ae(a):null;if(!d){i.error("Couldn't determine the preview host from git."),i.info(Ot.dim(" Pass it explicitly: `eds ue open <path> --url main--<repo>--<owner>.aem.page`")),process.exitCode=1;return}r=Te(d.owner,d.repo,t.ref??"main")}let s=ci({host:r,path:o,org:t.org});i.info(j("Universal Editor")),i.info(k("page",`${r}${o.startsWith("/")?"":"/"}${o}`)),i.info(k("open",s)),t.open!==!1?await mc(s):i.info(Ot.dim(" (use without --no-open to launch the browser)"))}var nt=b(()=>{"use strict";p();F();H();vr();St();I()});var Hn={};U(Hn,{createBlock:()=>wc,ueModelFor:()=>Sr});import{existsSync as gc}from"fs";import{mkdir as hc,writeFile as Bn}from"fs/promises";import ot from"path";import xr from"chalk";function bc(e){return e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function Sr(e){let t=bc(e);return`${JSON.stringify({definitions:[{title:t,id:e,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:t,model:e}}}}}],models:[{id:e,fields:[{component:"text",name:"title",label:"Title",valueType:"string"},{component:"select",name:"titleType",label:"Title Type",valueType:"string",value:"h2",options:[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"}]},{component:"richtext",name:"text",value:"",label:"Text",valueType:"string"}]}],filters:[]},null,2)}
496
- `}async function wc(e,t={}){if(!pe.test(e)){i.error(`Invalid block name "${e}". Use kebab-case (e.g., "hero-banner", "card-list").`),process.exitCode=1;return}let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}let o=ot.join(n,"blocks",e);if(gc(o)){i.error(`Block "${e}" already exists at ${o}`),process.exitCode=1;return}await hc(o,{recursive:!0});let r=`export default function decorate(block) {
491
+ }`}]});var Gn={};N(Gn,{schemaBlock:()=>zc});import{existsSync as Ic}from"fs";import{readFile as Uc,writeFile as Bc}from"fs/promises";import Hc from"path";import Gc from"chalk";async function zc(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Schema - JSON-LD"));let o=Hc.join(n,"blocks",e,`${e}.js`);if(!Ic(o)){i.error(`Block "${e}" not found (no blocks/${e}/${e}.js).`),process.exitCode=1;return}let r=t.type;if(!r&&!t.yes){let{select:d}=await Promise.resolve().then(()=>(B(),U));r=await d({message:"Which schema.org type?",choices:Bt.map(l=>({name:`${l.id} - ${l.label}`,value:l.id}))})}let a=r?jr(r):void 0;if(!a){i.error(`Unknown schema type "${r}". Options: ${Bt.map(d=>d.id).join(", ")}`),process.exitCode=1;return}let s=Er(await Uc(o,"utf-8"),a);if(!s.changed){i.warn(`Not added: ${s.reason}.`);return}await Bc(o,s.js),i.info(j("JSON-LD added")),i.info($(`blocks/${e}/${e}.js`,`${a.id} (${a.label})`)),i.info(""),i.info(Gc.dim(" Review the generated object - some fields are heuristic or TODO. Validate at search.google.com/test/rich-results."))}var zn=w(()=>{"use strict";m();R();z();Pr();I()});function Wc(e,t){for(let n of e.match(/<meta\b[^>]*>/gi)??[])if(n.match(/\bname=["']([^"']+)["']/i)?.[1]===t)return n.match(/\bcontent=["']([^"']*)["']/i)?.[1]??"";return null}function Cr(e){return Wc(e,Jc)!==null}function Ar(e){return Array.isArray(e)?e.map(t=>t&&typeof t=="object"?t.id:void 0).filter(t=>typeof t=="string"):[]}function Tr(e){let t=!!e.configPresent["component-definition.json"]&&!!e.configPresent["component-models.json"],n=new Set(e.modelIds),o=e.blocks.map(r=>{let a=r.hasModelFile||n.has(r.name);return{name:r.name,editable:a,reason:a?void 0:"no UE model (_<name>.json or component-models entry)"}});return{isUeProject:t,blocks:o}}var Jn,Jc,Rr=w(()=>{"use strict";m();Jn=["component-definition.json","component-models.json","component-filters.json"],Jc="urn:adobe:aue:system:aemconnection"});var lt={};N(lt,{ueCheck:()=>Qc,ueOpen:()=>Zc});import{existsSync as ct}from"fs";import{readFile as Dr,readdir as qc}from"fs/promises";import st from"path";import Ht from"chalk";async function Kc(e){if(!ct(e))return null;try{return JSON.parse(await Dr(e,"utf-8"))}catch{return null}}async function Xc(e){let t=st.join(e,"blocks");return ct(t)?(await qc(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>({name:o.name,hasModelFile:ct(st.join(t,o.name,`_${o.name}.json`))})):[]}async function Vc(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{let{execa:n}=await import("execa");await n(t,[e],{stdio:"ignore"})}catch{}}async function Yc(e){try{let{execa:t}=await import("execa");return(await t("git",["remote","get-url","origin"],{cwd:e})).stdout.trim()||null}catch{return null}}async function Qc(){let e=E();if(!e){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Universal Editor - readiness"));let t={};for(let p of Jn)t[p]=ct(st.join(e,p));let n=await Kc(st.join(e,"component-models.json")),o=await Xc(e),{isUeProject:r,blocks:a}=Tr({configPresent:t,blocks:o,modelIds:Ar(n)});i.info(j("Universal Editor config"));let s=[...Jn],d=O(s);for(let p of s)i.info(D(t[p]?"pass":"fail",p,void 0,d));if(!r){i.info(""),i.warn("This doesn't look like a Universal Editor (crosswalk) project - run `eds scaffold ue` first."),process.exitCode=1;return}let l=st.join(e,"head.html");if(ct(l)){let p=Cr(await Dr(l,"utf-8"));i.info(D(p?"pass":"info","head.html",p?"aemconnection present":"no aemconnection (fine for cloud author)"))}if(i.info(j("Blocks",`${a.length} found`)),a.length===0)i.info(Ht.dim(" No blocks yet."));else{let p=O(a.map(f=>f.name));for(let f of a)i.info(D(f.editable?"pass":"warn",f.name,f.reason,p))}let c=a.filter(p=>p.editable).length,u=a.length-c;i.info(""),i.info(de({pass:c,warn:u})),i.info(Ht.dim(" Open a page in the editor with `eds ue open <path>`."))}async function Zc(e,t={}){let n=E()??process.cwd(),o=e??t.path??"/",r=t.url;if(!r){let s=await Yc(n),d=s?Ne(s):null;if(!d){i.error("Couldn't determine the preview host from git."),i.info(Ht.dim(" Pass it explicitly: `eds ue open <path> --url main--<repo>--<owner>.aem.page`")),process.exitCode=1;return}r=_e(d.owner,d.repo,t.ref??"main")}let a=yi({host:r,path:o,org:t.org});i.info(j("Universal Editor")),i.info($("page",`${r}${o.startsWith("/")?"":"/"}${o}`)),i.info($("open",a)),t.open!==!1?await Vc(a):i.info(Ht.dim(" (use without --no-open to launch the browser)"))}var dt=w(()=>{"use strict";m();R();z();Rr();Tt();I()});var qn={};N(qn,{createBlock:()=>ol,ueModelFor:()=>Lr});import{existsSync as el}from"fs";import{mkdir as tl,writeFile as Wn}from"fs/promises";import pt from"path";import Fr from"chalk";function nl(e){return e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function Lr(e){let t=nl(e);return`${JSON.stringify({definitions:[{title:t,id:e,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:t,model:e}}}}}],models:[{id:e,fields:[{component:"text",name:"title",label:"Title",valueType:"string"},{component:"select",name:"titleType",label:"Title Type",valueType:"string",value:"h2",options:[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"}]},{component:"richtext",name:"text",value:"",label:"Text",valueType:"string"}]}],filters:[]},null,2)}
492
+ `}async function ol(e,t={}){if(!ye.test(e)){i.error(`Invalid block name "${e}". Use kebab-case (e.g., "hero-banner", "card-list").`),process.exitCode=1;return}let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}let o=pt.join(n,"blocks",e);if(el(o)){i.error(`Block "${e}" already exists at ${o}`),process.exitCode=1;return}await tl(o,{recursive:!0});let r=`export default function decorate(block) {
497
493
  // TODO: implement ${e} block
498
494
  }
499
- `,s=`.${e} {
495
+ `,a=`.${e} {
500
496
  /* TODO: style ${e} block */
501
497
  }
502
- `;await Bn(ot.join(o,`${e}.js`),r),await Bn(ot.join(o,`${e}.css`),s);let a=t.ueModel!==!1;a&&await Bn(ot.join(o,`_${e}.json`),Sr(e)),i.success(`Block "${e}" created at ${xr.cyan(ot.relative(n,o))}${a?xr.dim(" (+ Universal Editor model)"):""}`)}var Gn=b(()=>{"use strict";p();F();H();Pe()});import{existsSync as Mt}from"fs";import{readFile as yc}from"fs/promises";import{homedir as De}from"os";import Le from"path";async function Wn(e){let{execaCommand:t}=await import("execa");try{return(await t(`which ${e}`)).stdout.trim()||void 0}catch{return}}function jr(e){if(!e||typeof e!="object")return;let t=e,n=t.mcpServers;if(n&&typeof n=="object"){for(let o of Object.keys(n))if(o.toLowerCase().includes("figma"))return o}for(let o of Object.values(t)){let r=jr(o);if(r)return r}}async function zn(e){for(let t of e)try{if(!Mt(t))continue;let n=await yc(t,"utf-8");try{let o=jr(JSON.parse(n));if(o)return o}catch{}if(n.toLowerCase().includes("figma"))return"figma"}catch{}}async function $r(e){if(e){let t=Jn.find(n=>n.type===e);if(t){let n=await Wn(t.binary);if(n){let o=await zn(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Mt(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}i.warn(`Preferred agent "${e}" not found in PATH`)}}for(let t of Jn){let n=await Wn(t.binary);if(n){let o=await zn(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Mt(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}}}async function _t(){let e=[];for(let t of Jn){let n=await Wn(t.binary);if(n){let o=await zn(t.mcpConfigPaths);e.push({type:t.type,path:n,configDir:Mt(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o})}}return e}var Jn,qn=b(()=>{"use strict";p();F();Jn=[{type:"claude",binary:"claude",configDir:Le.join(De(),".claude"),mcpConfigPaths:[Le.join(De(),".claude","plugins.json"),Le.join(De(),".claude.json")]},{type:"cursor",binary:"cursor",configDir:Le.join(De(),".cursor"),mcpConfigPaths:[Le.join(De(),".cursor","mcp.json")]},{type:"codex",binary:"codex",configDir:Le.join(De(),".codex"),mcpConfigPaths:[]}]});import{mkdir as vc,readFile as kc,writeFile as xc}from"fs/promises";import{tmpdir as Sc}from"os";import it from"path";import jc from"readline";import K from"chalk";async function Er(e,t){let n=t?it.join(t,"tmp"):Sc(),o=it.join(n,"eds-cli");await vc(o,{recursive:!0});let r=`from-design-${Date.now()}.md`,s=it.join(o,r);return await xc(s,e,"utf-8"),s}async function Cr(e,t,n){let{execa:o}=await import("execa"),r=await kc(t,"utf-8");try{switch(e.type){case"claude":{i.info(`Running Claude Code ${K.dim("- live log:")}`);let s=[...e.figmaMcpServerName?[e.figmaMcpServerName]:[],"figma-sse","figma-desktop","figma","Figma","plugin_figma_figma"],a=[...new Set(s.map(c=>`mcp__${c}`)),"Edit","Write","Read"].join(","),d=o("claude",["-p",r,"--output-format","stream-json","--verbose","--allowedTools",a],{cwd:n,buffer:!1,stdio:["ignore","pipe","inherit"]});await Ec(d,n);break}case"cursor":{i.info("Running Cursor agent..."),await o("cursor",["--prompt",r],{cwd:n,stdio:"inherit"});break}case"codex":{i.info("Running Codex..."),await o("codex",[r],{cwd:n,stdio:"inherit"});break}}return!0}catch(s){let a=s instanceof Error?s.message:String(s);return i.error(`Agent ${e.type} failed: ${a}`),!1}}function $c(e){return e.includes("figma")?e.split("__").pop()??e:e.toLowerCase()}async function Ec(e,t){let n=(await import("ora")).default,o=Date.now(),r=()=>`${Math.round((Date.now()-o)/1e3)}s`,s=n({text:`thinking ${K.dim(r())}`,color:"yellow"}).start(),a="thinking",d=setInterval(()=>{s.text=`${a} ${K.dim(r())}`},300),c=new Map,l=m=>{s.stop(),i.info(` ${m}`),s.start()},u;try{if(e.stdout){let m=jc.createInterface({input:e.stdout});for await(let f of m){let $=f.trim();if(!$)continue;let v;try{v=JSON.parse($)}catch{continue}let x=Array.isArray(v.message?.content)?v.message.content:[];if(v.type==="assistant"){for(let g of x)if(g.type==="text"&&"text"in g){let h=g.text.trim().split(`
503
- `)[0].slice(0,100);h&&l(K.dim(h))}else if(g.type==="tool_use"&&"name"in g){let h="id"in g&&g.id?g.id:`${Math.random()}`;c.set(h,{label:Cc(g.name,g.input,t),start:Date.now()}),a=$c(g.name)}}else if(v.type==="user"){for(let g of x)if(g.type==="tool_result"&&"tool_use_id"in g&&g.tool_use_id){let h=c.get(g.tool_use_id);if(h){let S=`${((Date.now()-h.start)/1e3).toFixed(1)}s`,A="is_error"in g&&g.is_error?` ${K.red("failed")}`:"";l(`${h.label} ${K.dim(S)}${A}`),c.delete(g.tool_use_id)}}}else if(v.type==="result"){let g=typeof v.duration_ms=="number"?`${(v.duration_ms/1e3).toFixed(1)}s`:"",h=typeof v.total_cost_usd=="number"?`$${v.total_cost_usd.toFixed(3)}`:"";u=[g,h].filter(Boolean).join(" \xB7 ")||"done"}}}for(let m of c.values())l(`${m.label} ${K.dim("\u2026")}`);clearInterval(d),u?s.succeed(`${L.accent("agent finished")} ${K.dim(u)}`):s.stop()}catch(m){throw clearInterval(d),s.stop(),m}await e}function Cc(e,t,n){let o=r=>{let s=t?.[r];return typeof s!="string"?"":s.startsWith(n)?it.relative(n,s):it.basename(s)};if(e.includes("figma")){let r=e.split("__").pop()??e;return`${G.figma} ${K.bold(r)} ${K.dim("Figma MCP")}`}switch(e){case"Write":case"Edit":case"NotebookEdit":return`${L.accent("\u270E")} ${K.cyan(o("file_path"))}`;case"Read":return K.dim(`\xB7 read ${o("file_path")}`);case"Bash":{let r=typeof t?.command=="string"?t.command.split(`
504
- `)[0].slice(0,70):"";return K.dim(`$ ${r}`)}default:return`${L.blue("\u2192")} ${e}`}}var Pr=b(()=>{"use strict";p();F();I()});import{existsSync as Pc}from"fs";import{readFile as Ac}from"fs/promises";import{homedir as Tc}from"os";import Kn from"path";async function Ar(e){try{let t=await Ac(e,"utf-8");return JSON.parse(t)}catch{return}}async function ae(e){let t=await Ar(Xn),n=e?await Ar(Kn.join(e,Fc)):void 0,o={...typeof t=="object"&&t!==null?t:{},...typeof n=="object"&&n!==null?n:{}},r=tn.safeParse(o);return r.success?r.data:(i.debug("Config validation issues:",r.error.flatten()),tn.parse({}))}function Fr(){return Tr}function Vn(){return Xn}function Yn(){return Pc(Xn)}var Tr,Xn,Fc,ve=b(()=>{"use strict";p();F();Pe();Tr=Kn.join(Tc(),".eds"),Xn=Kn.join(Tr,"config.json"),Fc=".edsrc.json"});function Dr(e){return e<=480?`${e} mobile`:e<=1024?`${e} tablet`:`${e} desktop`}function Dc(e,t="figma"){return e?e.split(",").map(n=>Number.parseInt(n.trim(),10)).filter(n=>Number.isFinite(n)&&n>0).map(n=>({width:n,label:Dr(n),source:t})):[]}function Lr(e,t){let n=Dc(e,"figma");return n.length?n:Lc(t)}function Lc(e){if(!Array.isArray(e))return[];let t=new Set,n=[];for(let o of e){let r=Number(o?.width);if(!Number.isFinite(r)||r<=0||t.has(r))continue;t.add(r);let s=o.source;n.push({width:r,label:Dr(r),source:s==="figma"?"figma":"default"})}return n}var Rr=b(()=>{"use strict";p()});function Nt(e){if(/^\d+[-:]\d+$/.test(e.trim()))throw new Error(`Input "${e}" looks like a node-id but not a full URL. Provide a Figma URL or use --file-key.`);let t;try{t=new URL(e.trim())}catch{throw new Error(`Invalid Figma URL: "${e}"`)}if(!t.hostname.endsWith("figma.com"))throw new Error(`Not a Figma URL: "${e}"`);let n=t.pathname.split("/").filter(Boolean);if(n.length<2)throw new Error(`Cannot extract fileKey from URL: "${e}"`);let o=n[0],r,s;n[2]==="branch"&&n[3]?(r=n[3],s=n[4]?decodeURIComponent(n[4]):void 0):(r=n[1],s=n[2]?decodeURIComponent(n[2]):void 0);let a=t.searchParams.get("node-id"),d=a?Rc(a):void 0;return{fileKey:r,nodeId:d,fileName:s}}function Rc(e){return decodeURIComponent(e).replace(/-/g,":")}var Or=b(()=>{"use strict";p()});import{existsSync as Oc}from"fs";import{readFile as Mc}from"fs/promises";import _c from"path";function Nc(e,t,n){if(!e||e==="document"||e==="ue")return"";let o=t?` (model / persisted query: \`${t}\`)`:"",r="`${window.location.origin}/graphql/execute.json/<project>/<query>;path=<cfPath>`";return e==="cf"?`
498
+ `;await Wn(pt.join(o,`${e}.js`),r),await Wn(pt.join(o,`${e}.css`),a);let s=t.ueModel!==!1;s&&await Wn(pt.join(o,`_${e}.json`),Lr(e)),i.success(`Block "${e}" created at ${Fr.cyan(pt.relative(n,o))}${s?Fr.dim(" (+ Universal Editor model)"):""}`)}var Kn=w(()=>{"use strict";m();R();z();Me()});import{existsSync as Gt}from"fs";import{readFile as il}from"fs/promises";import{homedir as Ue}from"os";import Be from"path";async function Vn(e){let{execaCommand:t}=await import("execa");try{return(await t(`which ${e}`)).stdout.trim()||void 0}catch{return}}function Or(e){if(!e||typeof e!="object")return;let t=e,n=t.mcpServers;if(n&&typeof n=="object"){for(let o of Object.keys(n))if(o.toLowerCase().includes("figma"))return o}for(let o of Object.values(t)){let r=Or(o);if(r)return r}}async function Yn(e){for(let t of e)try{if(!Gt(t))continue;let n=await il(t,"utf-8");try{let o=Or(JSON.parse(n));if(o)return o}catch{}if(n.toLowerCase().includes("figma"))return"figma"}catch{}}async function Mr(e){if(e){let t=Xn.find(n=>n.type===e);if(t){let n=await Vn(t.binary);if(n){let o=await Yn(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Gt(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}i.warn(`Preferred agent "${e}" not found in PATH`)}}for(let t of Xn){let n=await Vn(t.binary);if(n){let o=await Yn(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Gt(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}}}async function zt(){let e=[];for(let t of Xn){let n=await Vn(t.binary);if(n){let o=await Yn(t.mcpConfigPaths);e.push({type:t.type,path:n,configDir:Gt(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o})}}return e}var Xn,Qn=w(()=>{"use strict";m();R();Xn=[{type:"claude",binary:"claude",configDir:Be.join(Ue(),".claude"),mcpConfigPaths:[Be.join(Ue(),".claude","plugins.json"),Be.join(Ue(),".claude.json")]},{type:"cursor",binary:"cursor",configDir:Be.join(Ue(),".cursor"),mcpConfigPaths:[Be.join(Ue(),".cursor","mcp.json")]},{type:"codex",binary:"codex",configDir:Be.join(Ue(),".codex"),mcpConfigPaths:[]}]});import{mkdir as rl,readFile as al,writeFile as sl}from"fs/promises";import{tmpdir as cl}from"os";import mt from"path";import ll from"readline";import ee from"chalk";async function Zn(e,t){let n=t?mt.join(t,"tmp"):cl(),o=mt.join(n,"eds-cli");await rl(o,{recursive:!0});let r=`from-design-${Date.now()}.md`,a=mt.join(o,r);return await sl(a,e,"utf-8"),a}async function eo(e,t,n,o){let{execa:r}=await import("execa"),a=await al(t,"utf-8");try{switch(e.type){case"claude":{i.info(`Running Claude Code ${ee.dim("- live log:")}`);let s=[...e.figmaMcpServerName?[e.figmaMcpServerName]:[],"figma-sse","figma-desktop","figma","Figma","plugin_figma_figma"],d=[...new Set(s.map(u=>`mcp__${u}`)),"Edit","Write","Read"].join(","),c=r("claude",["-p",a,"--model",o??"haiku","--output-format","stream-json","--verbose","--allowedTools",d],{cwd:n,buffer:!1,stdio:["ignore","pipe","inherit"]});await pl(c,n);break}case"cursor":{i.info("Running Cursor agent..."),await r("cursor",["--prompt",a],{cwd:n,stdio:"inherit"});break}case"codex":{i.info("Running Codex..."),await r("codex",[a],{cwd:n,stdio:"inherit"});break}}return!0}catch(s){let d=s instanceof Error?s.message:String(s);return i.error(`Agent ${e.type} failed: ${d}`),!1}}function dl(e){return e.includes("figma")?e.split("__").pop()??e:e.toLowerCase()}async function pl(e,t){let n=(await import("ora")).default,o=Date.now(),r=()=>`${Math.round((Date.now()-o)/1e3)}s`,a=n({text:`thinking ${ee.dim(r())}`,color:"yellow"}).start(),s="thinking",d=setInterval(()=>{a.text=`${s} ${ee.dim(r())}`},300),l=new Map,c=p=>{a.stop(),i.info(` ${p}`),a.start()},u;try{if(e.stdout){let p=ll.createInterface({input:e.stdout});for await(let f of p){let g=f.trim();if(!g)continue;let y;try{y=JSON.parse(g)}catch{continue}let h=Array.isArray(y.message?.content)?y.message.content:[];if(y.type==="assistant"){for(let b of h)if(b.type==="text"&&"text"in b){let S=b.text.trim().split(`
499
+ `)[0].slice(0,100);S&&c(ee.dim(S))}else if(b.type==="tool_use"&&"name"in b){let S="id"in b&&b.id?b.id:`${Math.random()}`;l.set(S,{label:ml(b.name,b.input,t),start:Date.now()}),s=dl(b.name)}}else if(y.type==="user"){for(let b of h)if(b.type==="tool_result"&&"tool_use_id"in b&&b.tool_use_id){let S=l.get(b.tool_use_id);if(S){let x=`${((Date.now()-S.start)/1e3).toFixed(1)}s`,T="is_error"in b&&b.is_error?` ${ee.red("failed")}`:"";c(`${S.label} ${ee.dim(x)}${T}`),l.delete(b.tool_use_id)}}}else if(y.type==="result"){let b=typeof y.duration_ms=="number"?`${(y.duration_ms/1e3).toFixed(1)}s`:"",S=typeof y.total_cost_usd=="number"?`$${y.total_cost_usd.toFixed(3)}`:"";u=[b,S].filter(Boolean).join(" \xB7 ")||"done"}}}for(let p of l.values())c(`${p.label} ${ee.dim("\u2026")}`);clearInterval(d),u?a.succeed(`${_.accent("agent finished")} ${ee.dim(u)}`):a.stop()}catch(p){throw clearInterval(d),a.stop(),p}await e}function ml(e,t,n){let o=r=>{let a=t?.[r];return typeof a!="string"?"":a.startsWith(n)?mt.relative(n,a):mt.basename(a)};if(e.includes("figma")){let r=e.split("__").pop()??e;return`${J.figma} ${ee.bold(r)} ${ee.dim("Figma MCP")}`}switch(e){case"Write":case"Edit":case"NotebookEdit":return`${_.accent("\u270E")} ${ee.cyan(o("file_path"))}`;case"Read":return ee.dim(`\xB7 read ${o("file_path")}`);case"Bash":{let r=typeof t?.command=="string"?t.command.split(`
500
+ `)[0].slice(0,70):"";return ee.dim(`$ ${r}`)}default:return`${_.blue("\u2192")} ${e}`}}var Nr=w(()=>{"use strict";m();R();I()});import{existsSync as ul}from"fs";import{readFile as fl}from"fs/promises";import{homedir as gl}from"os";import to from"path";async function _r(e){try{let t=await fl(e,"utf-8");return JSON.parse(t)}catch{return}}async function fe(e){let t=await _r(no),n=e?await _r(to.join(e,hl)):void 0,o={...typeof t=="object"&&t!==null?t:{},...typeof n=="object"&&n!==null?n:{}},r=sn.safeParse(o);return r.success?r.data:(i.debug("Config validation issues:",r.error.flatten()),sn.parse({}))}function Ur(){return Ir}function oo(){return no}function io(){return ul(no)}var Ir,no,hl,Pe=w(()=>{"use strict";m();R();Me();Ir=to.join(gl(),".eds"),no=to.join(Ir,"config.json"),hl=".edsrc.json"});function Br(e){return e<=480?`${e} mobile`:e<=1024?`${e} tablet`:`${e} desktop`}function bl(e,t="figma"){return e?e.split(",").map(n=>Number.parseInt(n.trim(),10)).filter(n=>Number.isFinite(n)&&n>0).map(n=>({width:n,label:Br(n),source:t})):[]}function Hr(e,t){let n=bl(e,"figma");return n.length?n:wl(t)}function wl(e){if(!Array.isArray(e))return[];let t=new Set,n=[];for(let o of e){let r=Number(o?.width);if(!Number.isFinite(r)||r<=0||t.has(r))continue;t.add(r);let a=o.source;n.push({width:r,label:Br(r),source:a==="figma"?"figma":"default"})}return n}var Gr=w(()=>{"use strict";m()});async function qr(e){let{fileKey:t,nodeId:n,token:o}=e,r=n?`${zr}/files/${t}/nodes?ids=${encodeURIComponent(n)}`:`${zr}/files/${t}`,a=await fetch(r,{headers:{"X-Figma-Token":o}});if(!a.ok){let s=await a.text().catch(()=>""),d=a.status===403?" (check the token scope: it needs file_content:read, and access to this file)":a.status===404?" (file or node not found \u2014 check the URL)":"";throw new Error(`Figma REST ${a.status} ${a.statusText}${d}${s?` \u2014 ${s.slice(0,200)}`:""}`)}return a.json()}function ro(e){if(!e)return;let t=o=>Math.round(Math.max(0,Math.min(1,o))*255).toString(16).padStart(2,"0"),n=`#${t(e.r)}${t(e.g)}${t(e.b)}`;return e.a!==void 0&&e.a<1?`${n}${t(e.a)}`:n}function Wr(e){let t=e?.find(n=>n.visible!==!1);if(t){if(t.type==="SOLID")return ro(t.color);if(t.type?.startsWith("GRADIENT")){let n=(t.gradientStops??[]).map(o=>ro(o.color)).filter(Boolean);return n.length?`gradient(${n.join(" \u2192 ")})`:"gradient"}return t.type==="IMAGE"?"image(placeholder)":t.type?.toLowerCase()}}function Kr(e,t){if(!e||typeof e!="object")return null;let n={name:e.name,type:e.type};if(e.absoluteBoundingBox){let{width:s,height:d}=e.absoluteBoundingBox;s!=null&&d!=null&&(n.size={w:Math.round(s),h:Math.round(d)})}e.layoutMode&&e.layoutMode!=="NONE"&&(n.layout={direction:e.layoutMode==="HORIZONTAL"?"row":"column",gap:e.itemSpacing,padding:[e.paddingTop,e.paddingRight,e.paddingBottom,e.paddingLeft],align:[e.primaryAxisAlignItems,e.counterAxisAlignItems].filter(Boolean).join("/")});let o=Wr(e.fills);o&&(n.fill=o);let r=Wr(e.strokes);r&&(n.stroke={color:r,weight:e.strokeWeight}),e.cornerRadius&&(n.radius=e.cornerRadius);let a=(e.effects??[]).filter(s=>s.visible!==!1&&(s.type==="DROP_SHADOW"||s.type==="INNER_SHADOW")).map(s=>`${s.type==="INNER_SHADOW"?"inset ":""}${s.offset?.x??0} ${s.offset?.y??0} ${s.radius??0} ${ro(s.color)??""}`.trim());if(a.length&&(n.shadows=a),e.type==="TEXT"&&e.characters!==void 0){n.text=e.characters;let s=e.style??{};n.font={family:s.fontFamily,size:s.fontSize,weight:s.fontWeight,lineHeight:s.lineHeightPx,letterSpacing:s.letterSpacing,align:s.textAlignHorizontal}}if(e.children?.length&&t<yl){let s=e.children.slice(0,Jr).map(d=>Kr(d,t+1)).filter(Boolean);s.length&&(n.children=s),e.children.length>Jr&&(n.childrenTruncated=e.children.length)}return n}function Xr(e,t){let n=e,o;if(t&&n.nodes){let a=Object.keys(n.nodes)[0];o=a?n.nodes[a]?.document:void 0}if(o??=n.document,!o)throw new Error("Figma REST response had no document node to serialize.");let r={source:"figma-rest",file:n.name,root:Kr(o,0)};return JSON.stringify(r,null,2)}var zr,yl,Jr,Vr=w(()=>{"use strict";m();zr="https://api.figma.com/v1";yl=12,Jr=60});import{existsSync as vl}from"fs";import{mkdir as kl,readFile as xl,writeFile as $l}from"fs/promises";import ao from"path";function Sl(e,t,n){let o=a=>a.replace(/[^a-z0-9._-]/gi,"-"),r=`${o(t)}__${o(n??"file")}.json`;return ao.join(e,"tmp","eds-cli","design-cache",r)}async function jl(e){if(!vl(e))return null;try{return await xl(e,"utf-8")}catch{return null}}async function El(e,t){await kl(ao.dirname(e),{recursive:!0}),await $l(e,t,"utf-8")}async function Yr(e){if(e.localFile)return{design:{mode:"file",filePath:e.localFile},summary:`local file ${e.localFile}`};let{figma:t,projectRoot:n}=e;if(!t?.fileKey)return{summary:"provider MCP"};let o=Sl(n,t.fileKey,t.nodeId),r=ao.relative(n,o);if(!e.refresh){let a=await jl(o);if(a)return{design:{mode:"spec",spec:a,cachePath:r},summary:`cache ${r}`}}if(e.token&&!e.preferMcp)try{let a=await qr({fileKey:t.fileKey,nodeId:t.nodeId,token:e.token}),s=Xr(a,t.nodeId);return await El(o,s),{design:{mode:"spec",spec:s,cachePath:r},summary:`REST \u2192 ${r}`}}catch(a){return{design:{mode:"mcp",cachePath:r},summary:"MCP (REST failed \u2014 1 call)",restError:a instanceof Error?a.message:String(a)}}return{design:{mode:"mcp",cachePath:r},summary:"MCP (1 call, cached)"}}var Qr=w(()=>{"use strict";m();Vr()});function Jt(e){if(/^\d+[-:]\d+$/.test(e.trim()))throw new Error(`Input "${e}" looks like a node-id but not a full URL. Provide a Figma URL or use --file-key.`);let t;try{t=new URL(e.trim())}catch{throw new Error(`Invalid Figma URL: "${e}"`)}if(!t.hostname.endsWith("figma.com"))throw new Error(`Not a Figma URL: "${e}"`);let n=t.pathname.split("/").filter(Boolean);if(n.length<2)throw new Error(`Cannot extract fileKey from URL: "${e}"`);let o=n[0],r,a;n[2]==="branch"&&n[3]?(r=n[3],a=n[4]?decodeURIComponent(n[4]):void 0):(r=n[1],a=n[2]?decodeURIComponent(n[2]):void 0);let s=t.searchParams.get("node-id"),d=s?Pl(s):void 0;return{fileKey:r,nodeId:d,fileName:a}}function Pl(e){return decodeURIComponent(e).replace(/-/g,":")}var Zr=w(()=>{"use strict";m()});import{existsSync as Cl}from"fs";import{readFile as Al}from"fs/promises";import Tl from"path";function Rl(e,t,n){if(!e||e==="document"||e==="ue")return"";let o=t?` (model / persisted query: \`${t}\`)`:"",r="`${window.location.origin}/graphql/execute.json/<project>/<query>;path=<cfPath>`";return e==="cf"?`
505
501
  ## Content source: Content Fragment
506
502
  This block renders an AEM **Content Fragment**${o} - not inline-authored copy.
507
503
  - UE model: use an \`aem-content-fragment\` field (e.g. \`name: "fragment"\`) for the CF reference.
@@ -514,32 +510,30 @@ This block mixes **two sources in one model and one \`decorate(block)\`**:
514
510
  - **Inline (UE-authored)** parts \u2192 normal fields (text / richtext / image / select) read straight from the authored DOM cells, with semantic collapsing.
515
511
  - **Content Fragment** part${o} \u2192 an \`aem-content-fragment\` field; \`decorate()\` is **async** and also fetches that CF via a GraphQL persisted query (${r}) and renders its fields.
516
512
  - Field order in the model = cell order in the authored DOM. Read the inline cells by position; detect the CF reference by its \`/content/dam/\` link. Merge both into the final markup, and handle the CF loading/empty/error states.
517
- `}async function Mr(e){let t=await Uc(e.projectRoot),n=Nc(e.contentSource,e.cfHint,e.blockName),o=e.screenshot!==!1,r=o?`## Step 5 \u2014 Pixel-Perfect Self-Verification (do not skip)
518
- After writing the files, **verify against the screenshot from Step 1**:
519
- 1. Re-open the \`get_screenshot\` image and compare it to your implementation region by region.
520
- 2. Check each axis: spacing, font sizes/weights/line-heights, colors, border-radius, shadows, alignment, and overall proportions.
521
- 3. For every mismatch, adjust the CSS and re-check. Repeat until the rendered block is indistinguishable from the screenshot.
522
- 4. Briefly state what you verified and any value you had to infer.`:`## Step 5 \u2014 Structural Self-Verification (do not skip)
523
- No screenshot was fetched (token-lean mode). Verify against the **exact values from \`get_design_context\`**:
524
- 1. Re-check every extracted value (spacing, fonts, colors, radius, shadows, alignment) against your CSS.
525
- 2. Fix any mismatch.
526
- 3. Briefly state what you verified and any value you had to infer.`,s=e.provider??"figma",a=rt[s],d=s==="figma"?`## Step 1 \u2014 Fetch the Design
527
- Call the Figma MCP tools for this selection:
528
- - \`get_design_context\` \u2014 structure, layout, measurements, text content
529
- - \`get_variable_defs\` \u2014 design tokens (variables) to map to CSS custom properties
530
- ${o?"- `get_screenshot` \u2014 the ground-truth visual reference for Step 5. Request it at `maxDimension: 1024` (enough to verify; do not request larger).":"- (screenshot skipped to save tokens \u2014 pass `excludeScreenshot: true` to `get_design_context`)"}
531
-
532
- **Token efficiency:** call each tool **once** for the target node only \u2014 don't re-fetch and don't walk sibling/parent nodes you don't need.${o?"":" You will verify structurally against the `get_design_context` measurements, not a picture."}
533
-
534
- Target:
535
- - fileKey: \`${e.figma?.fileKey}\`
536
- ${e.figma?.nodeId?`- node: \`${e.figma.nodeId}\``:"- (no node selected \u2014 use the full page)"}
537
-
538
- ${e.figma?.nodeId?`Use node ID \`${e.figma.nodeId}\` in file \`${e.figma.fileKey}\`.`:`Use file key \`${e.figma?.fileKey}\` (no specific node selected \u2014 analyze the full page or ask the user to select a frame).`}`:`## Step 1 \u2014 Fetch the Design
539
- Read the design from **${a}** through your ${a} MCP connection (use its design-context / inspect / screenshot tools). Design reference: \`${e.designRef??"(the selected design)"}\`.
540
- Extract the **exact** structure, layout, colours, typography, spacing, radius and effects \u2014 do not approximate.${o?" Capture a screenshot for the Step 5 pixel check.":" No screenshot (token-lean) \u2014 verify structurally against the extracted values."}
541
-
542
- **Token efficiency:** fetch once for the target only.`,c=e.withUeModel?`
513
+ `}async function ea(e){let t=await Dl(e.projectRoot),n=Rl(e.contentSource,e.cfHint,e.blockName),o=e.screenshot===!0,r=e.provider??"figma",a=He[r],s=e.design,d=s?.mode==="file"?/\.(png|jpe?g|webp)$/i.test(s.filePath):!1,c=`## Step 5 \u2014 One Verification Pass (single pass, then stop)
514
+ Do **exactly one** self-check \u2014 do **not** loop:
515
+ 1. Compare your implementation to ${s?.mode==="spec"?"the exact values in the embedded design data from Step 1":s?.mode==="file"?d?"the local design image":"the exact values in the local SVG":s?.mode==="mcp"?"the exact values from the `get_design_context` you cached":o?"the `get_screenshot` image":"the exact values from `get_design_context`"} once, across: spacing, fonts, colors, radius, shadows, alignment and proportions.
516
+ 2. Apply **one** round of corrections, then **stop** \u2014 don't iterate to "pixel perfect". The author reviews the result in the live preview (\`eds block preview\`) and will request another pass with specific feedback if needed.
517
+ 3. Briefly state what you checked and any value you had to infer.`,u=`Target: fileKey \`${e.figma?.fileKey}\`${e.figma?.nodeId?`, node \`${e.figma.nodeId}\``:" (no node selected \u2014 use the full page)"}.`,p;s?.mode==="spec"?p=`## Step 1 \u2014 Use the Provided Design Data (no MCP)
518
+ The design was already fetched for you and is embedded below \u2014 **do not call any Figma MCP tool** (\`get_design_context\`, \`get_variable_defs\`, \`get_screenshot\`). Parse it for the exact structure, layout, spacing, colors, typography, radius and effects.
519
+
520
+ \`\`\`json
521
+ ${s.spec}
522
+ \`\`\`
523
+
524
+ Image fills are placeholders (the data references assets, not pixels) \u2014 render a placeholder at the right aspect-ratio per the Placeholders section; authors supply the real image.`:s?.mode==="file"?p=`## Step 1 \u2014 Read the Local Design Export (no MCP)
525
+ Read \`${s.filePath}\` with your **Read** tool. Do **not** call any Figma MCP tool.
526
+
527
+ ${d?"It's a raster image (PNG/JPG) \u2014 open it and reproduce it visually: infer spacing, colors, typography, radius, shadows and layout as precisely as you can from the pixels.":"It's an **SVG** \u2014 read it as text and parse the **exact** values: geometry and positions (x/y/width/height, `viewBox`), text and typography (font-family / font-size / font-weight on `<text>`/`<tspan>`), fills and gradients, strokes, and effects. Use the numbers verbatim, converting px\u2192rem where appropriate. The SVG is flattened \u2014 regroup into semantic structure yourself (Step 3), don't mirror raw `<g>`/`<path>` nesting."}`:s?.mode==="mcp"?p=`## Step 1 \u2014 Fetch the Design Once, Then Cache It (single MCP call)
528
+ Call **\`get_design_context\` exactly once** for the target node. Do **not** call \`get_variable_defs\` or \`get_screenshot\` \u2014 each extra MCP call burns the Figma plan's scarce tool-call budget; derive colors and tokens from the context you already got.
529
+ **Immediately after**, \`Write\` the raw design data you received to \`${s.cachePath}\` (pretty JSON) so re-runs and refine passes reuse it without another MCP call. Then generate from it.
530
+
531
+ ${u}`:r==="figma"?p=`## Step 1 \u2014 Fetch the Design (single MCP call)
532
+ Call **\`get_design_context\` exactly once** for the target node \u2014 it returns structure, layout, measurements, text and the colors/tokens you need. Do **not** call \`get_variable_defs\`${o?"":" or `get_screenshot`"} \u2014 each extra MCP call burns the Figma plan's scarce budget.${o?" You may call `get_screenshot` once (`maxDimension: 1024`) for the Step 5 check.":""}
533
+
534
+ ${u}`:p=`## Step 1 \u2014 Fetch the Design
535
+ Read the design from **${a}** through your ${a} MCP connection (design-context / inspect tools). Design reference: \`${e.designRef??"(the selected design)"}\`.
536
+ Extract the **exact** structure, layout, colours, typography, spacing, radius and effects \u2014 do not approximate. Fetch once for the target only.`;let f=e.withUeModel?`
543
537
  ## Step 4b \u2014 Universal Editor Authoring (REQUIRED, not optional)
544
538
  Authors must be able to drop and edit this block in the Universal Editor, so generate its UE configuration **in the same pass** as the code.
545
539
 
@@ -614,14 +608,14 @@ Rules:
614
608
  If the project uses a **single aggregated model file** (\`component-definition.json\` + \`component-models.json\` + \`component-filters.json\`) instead of per-block \`_${e.blockName}.json\`, detect that convention and add the block's definition/model/filter to those files instead (and register the block in the \`section\` filter). Prefer the per-block \`_${e.blockName}.json\` when neither exists. Full field reference and a repeatable-cards round-trip example: \`docs/universal-editor-fields.md\`.
615
609
 
616
610
  **Reusable field groups (partials):** when the design shows one of these common shapes, reuse the standard group instead of inventing fields \u2014 same groups \`eds model add\` uses, so the model stays consistent across the project:
617
- ${Fe.map(l=>`- \`${l.id}\` \u2014 ${l.label}`).join(`
611
+ ${Ie.map(h=>`- \`${h.id}\` \u2014 ${h.label}`).join(`
618
612
  `)}
619
- `:"";return`# Pixel-Perfect EDS Block from ${a}
613
+ `:"",g=s?.mode==="file"?"a design export":a,y=s?.mode==="file"?"design":`${a} design`;return`# Pixel-Perfect EDS Block from ${g}
620
614
 
621
615
  ## Task
622
- Generate an AEM Edge Delivery Services block named **\`${e.blockName}\`** that reproduces the ${a} design **1:1 \u2014 pixel perfect**. Exact spacing, colors, typography, and layout. Not "close enough" \u2014 identical.
616
+ Generate an AEM Edge Delivery Services block named **\`${e.blockName}\`** that reproduces the ${y} **1:1 \u2014 pixel perfect**. Exact spacing, colors, typography, and layout. Not "close enough" \u2014 identical.
623
617
 
624
- ${d}
618
+ ${p}
625
619
 
626
620
  ## Step 2 \u2014 Extract Exact Values
627
621
  From the design data you fetched, record the **precise** values \u2014 do not approximate:
@@ -662,20 +656,21 @@ export default function decorate(block) {
662
656
  /* Map Figma design tokens to CSS custom properties; reuse project tokens below where they match */
663
657
  /* Mobile-first; exact values from Step 2 */
664
658
  \`\`\`
665
- ${c}${n}
659
+ ${f}${n}
666
660
  ## Placeholders & assets \u2014 be visible before Universal Editor takes over
667
661
  Content images and copy come from **authoring** (the document / DAM via UE), not the repo. Do **not** ship design-tool CDN URLs (Figma / Google Stitch links are short-lived) and do **not** bundle content photos into the repo.
668
662
  - In \`decorate()\`, read the image/text from the authored DOM. When none is present yet, render a lightweight **placeholder** so the block is visible *before* an author sets the real content: an inline SVG data-URI grey box (or a CSS placeholder) at the correct \`aspect-ratio\`, and sensible placeholder copy.
669
- - Provide the mock for the preview in \`blocks/${e.blockName}/_${e.blockName}.preview.html\` (used by \`eds block preview\`). Keep placeholder copy there, not hardcoded in the block.
663
+ - Provide the mock for the preview in \`blocks/${e.blockName}/_${e.blockName}.preview.html\` (used by \`eds block preview\`). Keep placeholder copy there, not hardcoded in the block. **This file must be a bare block fragment only** \u2014 just the authored \`<div class="${e.blockName} block">\u2026</div>\` markup that \`decorate()\` consumes. Do **not** wrap it in \`<!DOCTYPE>\`, \`<html>\`, \`<head>\`, \`<body>\`, \`<link>\`, \`<style>\` or \`<script>\`; the preview harness supplies the page, the block CSS and the \`decorate()\` call itself. A full HTML document here renders as a blank preview.
670
664
  - Only bundle genuinely **static, decorative** assets (e.g. a small icon) as an optimized inline/\`icons/\` **SVG**, referenced by project-relative path. Never bundle authorable content images.
671
665
  - Always set \`width\`/\`height\` or \`aspect-ratio\` to avoid CLS.
672
666
 
673
- ${r}
667
+ ${c}
674
668
 
675
669
  ## EDS Block Conventions
676
670
  - **Full-width by default**: the block/section spans the **full viewport width** (full-bleed) \u2014 never a fixed or centered fixed-width box. Constrain only the *inner content* to a sensible \`max-width\` (centered) for line-length/readability, with fluid horizontal padding. The design frame's width (e.g. 1280px) is the content cap, not the section width.
677
671
  - **Mobile-first & fluid**: base styles target the smallest screen; layer breakpoints upward. The section must look right at any width, not only the design frame's.
678
672
  - **No frameworks**: vanilla JS and CSS only
673
+ - **Self-contained JS**: the block's \`.js\` must run on its own. Do **not** \`import\` from \`scripts/\` or other blocks (no analytics/tracking/aem helpers) \u2014 a missing module makes the whole block fail to load and renders blank. No analytics/tracking code unless explicitly requested.
679
674
  - **\`decorate(block)\`**: enhance the authored DOM; never inject hardcoded copy that should be authored
680
675
  - **Semantic HTML**: correct elements and heading hierarchy
681
676
  - **Class naming**: prefix all classes with the block name: \`.${e.blockName}-item\`, \`.${e.blockName}-title\`
@@ -690,15 +685,36 @@ ${t}
690
685
  2. Production-ready, Lighthouse-friendly (aim for 100), no \`console.log\`
691
686
  3. Brief inline comments only for non-obvious logic
692
687
  4. **Minimise chat output (save tokens):** write the files directly with your editing tools \u2014 do **not** paste the generated code back into the chat, and skip step-by-step narration. End with a **\u22643-line** summary: files created + any value you had to infer.
688
+ - **No shell access:** you can only read/write files and call the design MCP. Do **not** run \`eslint\`, \`stylelint\`, \`npm\`, \`npx\`, \`tsc\`, a build, or any shell/Bash command \u2014 those tools aren't granted and the attempts just fail and waste time. Write valid, clean, correctly-formatted files directly; linting/formatting is the project's job, not yours.
693
689
  5. Mobile-first CSS with breakpoints at 600px and 900px
694
690
  6. Prefer existing project tokens over new hardcoded values${e.withUeModel?"\n7. UE model field `name`s must match what `decorate()` reads, and every Figma variant must appear as a select option wired to a CSS modifier":""}
695
691
 
696
692
  Finally, record the design's frame width(s) you read in Step 1 into \`blocks/${e.blockName}/.eds-meta.json\` as \`{ "breakpoints": [{ "width": <px>, "source": "figma" }] }\` (one entry per distinct frame width). The CLI merges this so \`eds block preview\` shows the block at the **real design widths**, not a fixed device set.
697
693
 
698
694
  ---
699
- *Prompt version: ${Ut}*
700
- `}async function Uc(e){let t=_c.join(e,"styles","styles.css");if(!Oc(t))return"";try{let o=(await Mc(t,"utf-8")).match(/:root\s*\{([^}]+)\}/);if(!o)return"";let r=o[1].split(`
701
- `).filter(s=>s.trim().startsWith("--")).map(s=>s.trim()).join(`
695
+ *Prompt version: ${ut}*
696
+ `}function ta(e){let t=e.provider??"figma",n=t==="figma"&&e.figma?.fileKey?`If the change needs design values, re-read **only what you need** from Figma (fileKey \`${e.figma.fileKey}\`${e.figma.nodeId?`, node \`${e.figma.nodeId}\``:""}) \u2014 don't re-fetch the whole design.`:e.designRef?`If the change needs design values, re-read only what you need from the ${He[t]} design: \`${e.designRef}\`.`:"";return`# Refine the \`${e.blockName}\` EDS block
697
+
698
+ The block already exists in \`blocks/${e.blockName}/\` and the author reviewed it in the live preview. Apply **this change** and nothing else:
699
+
700
+ > ${e.feedback.split(`
701
+ `).join(`
702
+ > `)}
703
+
704
+ ## How to work
705
+ 1. **Read the current files first** (\`blocks/${e.blockName}/${e.blockName}.js\`, \`${e.blockName}.css\`, and \`_${e.blockName}.json\` if present). Edit them in place \u2014 do **not** rewrite from scratch or regenerate unrelated parts.
706
+ 2. Make the smallest change that satisfies the request. Keep everything else byte-for-byte unless the change requires otherwise.
707
+ 3. Preserve the EDS conventions already in place: full-width section / constrained inner content, mobile-first, vanilla JS/CSS, block-prefixed class names, \`decorate(block)\` reads authored DOM (no hardcoded copy), accessibility, no \`console.log\`. If the block has a UE model, keep field \`name\`s and \`decorate()\` in sync.
708
+ 4. ${n||"Use the values already in the files; infer sensibly if the request is purely stylistic."}
709
+
710
+ ## Constraints
711
+ - **One pass, then stop** \u2014 apply the change, don't loop or re-verify to "pixel perfect"; the author re-checks in the preview and may ask again.
712
+ - **No shell access:** only read/write files${t==="figma"?" and call the Figma MCP":""}. Do **not** run \`eslint\`, \`stylelint\`, \`npm\`, \`npx\`, \`tsc\`, a build, or any Bash command \u2014 they aren't granted and just fail.
713
+ - **Minimise chat output:** edit files directly, don't paste code back. End with a **\u22642-line** summary of what changed.
714
+
715
+ *Prompt version: ${ut}*
716
+ `}async function Dl(e){let t=Tl.join(e,"styles","styles.css");if(!Cl(t))return"";try{let o=(await Al(t,"utf-8")).match(/:root\s*\{([^}]+)\}/);if(!o)return"";let r=o[1].split(`
717
+ `).filter(a=>a.trim().startsWith("--")).map(a=>a.trim()).join(`
702
718
  `);return r?`
703
719
  ## Existing Project Tokens
704
720
  The project already defines these CSS custom properties in \`styles/styles.css\`.
@@ -709,36 +725,107 @@ Reuse them instead of hardcoding values:
709
725
  ${r}
710
726
  }
711
727
  \`\`\`
712
- `:""}catch{return""}}var Ut,rt,_r=b(()=>{"use strict";p();Ln();Ut="0.5.1",rt={figma:"Figma",stitch:"Google Stitch",canva:"Canva",sketch:"Sketch",framer:"Framer"}});function st(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Nr(e){let{blockName:t,sampleContent:n}=e;return`<!DOCTYPE html>
728
+ `:""}catch{return""}}var ut,He,na=w(()=>{"use strict";m();_n();ut="0.7.0",He={figma:"Figma",stitch:"Google Stitch",canva:"Canva",sketch:"Sketch",framer:"Framer"}});function ae(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Fl(e){let t=e,n=t.match(/<body[^>]*>([\s\S]*?)<\/body>/i);return n&&(t=n[1]),t.replace(/<!DOCTYPE[^>]*>/gi,"").replace(/<\/?(?:html|head|body)[^>]*>/gi,"").replace(/<link\b[^>]*>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<!--[\s\S]*?-->/g,"").trim()}function so(e){let{blockName:t}=e,n=Fl(e.sampleContent);return`<!DOCTYPE html>
713
729
  <html lang="en">
714
730
  <head>
715
731
  <meta charset="utf-8" />
716
732
  <meta name="viewport" content="width=device-width, initial-scale=1" />
733
+ <link rel="stylesheet" href="/styles/styles.css" />
717
734
  <link rel="stylesheet" href="/blocks/${t}/${t}.css" />
718
- <style>*{box-sizing:border-box}html,body{margin:0;padding:0}</style>
735
+ <!-- Project styles.css gates visibility on body.appear (added by scripts.js on a
736
+ real page). The preview doesn't run scripts.js, so set it here and force the
737
+ body visible, else the whole frame stays display:none \u2192 blank. -->
738
+ <style>*{box-sizing:border-box}html,body{margin:0;padding:0}body{display:block!important}</style>
719
739
  </head>
720
- <body>
740
+ <body class="appear">
721
741
  ${n}
722
742
  <script type="module">
723
- import decorate from '/blocks/${t}/${t}.js';
724
- const block = document.querySelector('.${t}');
725
- if (block) { try { decorate(block); } catch (e) { console.error('decorate() failed:', e); } }
743
+ // Load the block defensively: a bad import inside the block (e.g. a missing
744
+ // scripts/*.js) must not blank the frame \u2014 fall back to the authored markup.
745
+ (async () => {
746
+ try {
747
+ const mod = await import('/blocks/${t}/${t}.js');
748
+ const block = document.querySelector('.${t}');
749
+ if (block && typeof mod.default === 'function') mod.default(block);
750
+ } catch (e) { console.error('block script failed \u2014 showing authored content only:', e); }
751
+ })();
726
752
  </script>
727
753
  <script>
728
754
  // Live reload: refresh when eds detects a change to the block.
729
755
  try { new EventSource('/__eds_events').onmessage = () => location.reload(); } catch (e) { /* no SSE */ }
730
756
  </script>
731
757
  </body>
732
- </html>`}function Ur(e){let{blockName:t,breakpoints:n,figmaUrl:o,frameRoute:r,placeholder:s}=e,a=n.filter(m=>m.figma),d=(a.length?a:n).reduce((m,f)=>f.width>m.width?f:m,n[0]),c=n.map(m=>`<option value="${m.width}"${m.width===d.width?" selected":""}>${st(m.label)}</option>`).join(`
733
- `),l=o?`<a class="figma-link" href="${st(o)}" target="_blank" rel="noopener">
758
+ </html>`}function Ll(e){let t=e.filter(n=>n.figma);return(t.length?t:e).reduce((n,o)=>o.width>n.width?o:n,e[0])}function oa(e){let t=e.map((o,r)=>{let a=Ll(o.breakpoints),s=o.breakpoints.map(c=>`<option value="${c.width}"${c.width===a.width?" selected":""}>${ae(c.label)}</option>`).join(""),d=o.figmaUrl?`<a class="figma-link" href="${ae(o.figmaUrl)}" target="_blank" rel="noopener">Figma \u2197</a>`:"",l=o.placeholder?'<span class="hint">placeholder content</span>':"";return`<section class="card">
759
+ <div class="cardbar">
760
+ <span class="block">${ae(o.blockName)}</span>
761
+ <select class="bp" data-i="${r}">
762
+ ${s}
763
+ <option value="full">Full</option>
764
+ </select>
765
+ ${l}
766
+ ${d}
767
+ </div>
768
+ <div class="stage">
769
+ <div class="device" data-i="${r}" data-w="${a.width}" style="width:${a.width}px">
770
+ <iframe src="${ae(o.frameRoute)}" title="${ae(o.blockName)} preview" loading="lazy"></iframe>
771
+ </div>
772
+ </div>
773
+ </section>`}).join(`
774
+ `);return`<!DOCTYPE html>
775
+ <html lang="en">
776
+ <head>
777
+ <meta charset="utf-8" />
778
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
779
+ <title>eds preview \u2014 gallery (${e.length})</title>
780
+ <style>
781
+ *{box-sizing:border-box}
782
+ html,body{margin:0;padding:0;background:#1f1f1f;color:#eaeaea;font-family:ui-sans-serif,-apple-system,"Segoe UI",sans-serif}
783
+ .topbar{position:sticky;top:0;z-index:20;display:flex;gap:10px;align-items:center;padding:12px 18px;font-size:13px;background:#141414;border-bottom:1px solid #333}
784
+ .topbar .title{font-weight:700}
785
+ .topbar .count{color:#8a8a8a}
786
+ .card{border-bottom:1px solid #2a2a2a}
787
+ .cardbar{position:sticky;top:45px;z-index:10;display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:10px 18px;font-size:12.5px;background:#181818;border-bottom:1px solid #2a2a2a}
788
+ .cardbar .block{font-weight:700;color:#e6e6e6}
789
+ .hint{color:#8a8a8a}
790
+ select.bp{appearance:none;cursor:pointer;color:#eaeaea;background:#232323;border:1px solid #3a3a3a;border-radius:8px;padding:6px 30px 6px 12px;font:inherit;font-size:12px;font-weight:600;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a8a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 9px center;background-size:13px}
791
+ select.bp:hover{border-color:#6a6a6a}
792
+ .figma-link{margin-left:auto;color:#cfcfcf;text-decoration:none;font-weight:600;font-size:12px;padding:6px 11px;border:1px solid #3a3a3a;border-radius:8px;background:#232323}
793
+ .figma-link:hover{border-color:#6a6a6a;color:#fff}
794
+ .stage{padding:24px 18px;display:flex;justify-content:center;overflow-x:auto}
795
+ .device{position:relative;background:#fff;border:1px solid #000;transition:width .2s ease}
796
+ .device::before{content:attr(data-w) "px";position:absolute;top:-19px;left:0;font-size:11px;color:#8a8a8a;font-family:ui-monospace,Menlo,monospace}
797
+ iframe{display:block;width:100%;height:560px;border:0}
798
+ .empty{padding:60px 20px;text-align:center;color:#8a8a8a}
799
+ .empty code{color:#bdbdbd}
800
+ </style>
801
+ </head>
802
+ <body>
803
+ <div class="topbar"><span class="title">eds gallery</span><span class="count">${e.length} block${e.length===1?"":"s"}</span></div>
804
+ ${e.length?t:'<p class="empty">No previewable blocks yet. Generate one with <code>eds block from-design</code>.</p>'}
805
+ <script>
806
+ for (const sel of document.querySelectorAll('select.bp')) {
807
+ const device = document.querySelector('.device[data-i="'+sel.dataset.i+'"]');
808
+ const apply = (v) => {
809
+ if (v === 'full') { device.style.width = '100%'; device.dataset.w = Math.round(device.getBoundingClientRect().width); }
810
+ else { device.style.width = v + 'px'; device.dataset.w = v; }
811
+ };
812
+ sel.addEventListener('change', () => apply(sel.value === 'full' ? 'full' : Number(sel.value)));
813
+ apply(Number(sel.value));
814
+ }
815
+ // Full-page reload when eds detects a block change (new blocks appear, too).
816
+ try { new EventSource('/__eds_events').onmessage = () => location.reload(); } catch (e) { /* no SSE */ }
817
+ </script>
818
+ </body>
819
+ </html>`}function ia(e){let{blockName:t,breakpoints:n,figmaUrl:o,frameRoute:r,placeholder:a}=e,s=n.filter(p=>p.figma),d=(s.length?s:n).reduce((p,f)=>f.width>p.width?f:p,n[0]),l=n.map(p=>`<option value="${p.width}"${p.width===d.width?" selected":""}>${ae(p.label)}</option>`).join(`
820
+ `),c=o?`<a class="figma-link" href="${ae(o)}" target="_blank" rel="noopener">
734
821
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>
735
822
  Open in Figma
736
- </a>`:"",u=s?`<span class="hint">placeholder content \u2014 add <code>blocks/${t}/_${t}.preview.html</code></span>`:"";return`<!DOCTYPE html>
823
+ </a>`:"",u=a?`<span class="hint">placeholder content \u2014 add <code>blocks/${t}/_${t}.preview.html</code></span>`:"";return`<!DOCTYPE html>
737
824
  <html lang="en">
738
825
  <head>
739
826
  <meta charset="utf-8" />
740
827
  <meta name="viewport" content="width=device-width, initial-scale=1" />
741
- <title>eds preview \u2014 ${st(t)}</title>
828
+ <title>eds preview \u2014 ${ae(t)}</title>
742
829
  <style>
743
830
  *{box-sizing:border-box}
744
831
  html,body{margin:0;padding:0;background:#1f1f1f;color:#eaeaea;font-family:ui-sans-serif,-apple-system,"Segoe UI",sans-serif}
@@ -760,18 +847,18 @@ ${n}
760
847
  </head>
761
848
  <body>
762
849
  <div class="bar">
763
- <span class="label">Block</span><span class="block">${st(t)}</span>
850
+ <span class="label">Block</span><span class="block">${ae(t)}</span>
764
851
  <label class="label" for="bp" style="margin-left:8px">Breakpoint</label>
765
852
  <select id="bp">
766
- ${c}
853
+ ${l}
767
854
  <option value="full">Full ca\u0142a szeroko\u015B\u0107</option>
768
855
  </select>
769
856
  ${u}
770
- ${l}
857
+ ${c}
771
858
  </div>
772
859
  <div class="stage">
773
860
  <div class="device" id="device" data-w="${d.width}" style="width:${d.width}px">
774
- <iframe id="frame" src="${r}" title="${st(t)} preview"></iframe>
861
+ <iframe id="frame" src="${r}" title="${ae(t)} preview"></iframe>
775
862
  </div>
776
863
  </div>
777
864
  <script>
@@ -785,27 +872,29 @@ ${n}
785
872
  setWidth(Number(bp.value));
786
873
  </script>
787
874
  </body>
788
- </html>`}var Ir=b(()=>{"use strict";p()});import{createReadStream as Ic,existsSync as Bc,statSync as Hc}from"fs";import Gc from"http";import Qn from"path";function Br(e,t,n,o="127.0.0.1"){let r=Qn.resolve(e),s=new Set,a=Gc.createServer((d,c)=>{let l=decodeURIComponent((d.url??"/").split("?")[0]);if(l===Wc){c.writeHead(200,{"content-type":"application/json"}),c.end(JSON.stringify({eds:!0}));return}if(l===zc){c.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"}),c.write(`: connected
875
+ </html>`}var ra=w(()=>{"use strict";m()});import{createReadStream as Ol,existsSync as Ml,statSync as Nl}from"fs";import _l from"http";import co from"path";function lo(e,t,n,o="127.0.0.1",r){let a=co.resolve(e),s=new Set,d=_l.createServer(async(l,c)=>{let u=decodeURIComponent((l.url??"/").split("?")[0]);if(u===Ul){c.writeHead(200,{"content-type":"application/json"}),c.end(JSON.stringify({eds:!0}));return}if(u===Bl){c.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"}),c.write(`: connected
789
876
 
790
- `),s.add(c),d.on("close",()=>s.delete(c));return}let u=t[l];if(u){c.writeHead(200,{"content-type":u.type}),c.end(u.body);return}let m=Qn.join(r,l);if(!m.startsWith(r)){c.writeHead(403),c.end("Forbidden");return}if(!Bc(m)||!Hc(m).isFile()){c.writeHead(404,{"content-type":"text/plain"}),c.end(`Not found: ${l}`);return}c.writeHead(200,{"content-type":Jc[Qn.extname(m).toLowerCase()]??"application/octet-stream"}),Ic(m).pipe(c)});return new Promise((d,c)=>{let l=0,u=m=>{a.once("error",f=>{f.code==="EADDRINUSE"&&l<10?(l++,u(m+1)):c(f)}),a.listen(m,o,()=>{d({url:`http://${o}:${m}/`,port:m,reload:()=>{for(let f of s)f.write(`data: reload
877
+ `),s.add(c),l.on("close",()=>s.delete(c));return}let p=t[u];if(p){c.writeHead(200,{"content-type":p.type}),c.end(p.body);return}if(r)try{let g=await r(u);if(g){c.writeHead(200,{"content-type":g.type}),c.end(g.body);return}}catch(g){c.writeHead(500,{"content-type":"text/plain"}),c.end(`Preview error: ${g instanceof Error?g.message:String(g)}`);return}let f=co.join(a,u);if(!f.startsWith(a)){c.writeHead(403),c.end("Forbidden");return}if(!Ml(f)||!Nl(f).isFile()){c.writeHead(404,{"content-type":"text/plain"}),c.end(`Not found: ${u}`);return}c.writeHead(200,{"content-type":Il[co.extname(f).toLowerCase()]??"application/octet-stream"}),Ol(f).pipe(c)});return new Promise((l,c)=>{let u=0,p=f=>{d.once("error",g=>{g.code==="EADDRINUSE"&&u<10?(u++,p(f+1)):c(g)}),d.listen(f,o,()=>{l({url:`http://${o}:${f}/`,port:f,reload:()=>{for(let g of s)g.write(`data: reload
791
878
 
792
- `)},close:()=>new Promise(f=>{for(let $ of s)$.end();a.close(()=>f())})})})};u(n)})}var Jc,Wc,zc,Hr=b(()=>{"use strict";p();Jc={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif",".avif":"image/avif",".woff":"font/woff",".woff2":"font/woff2",".ico":"image/x-icon"},Wc="/__eds_ping",zc="/__eds_events"});var It={};U(It,{previewBlock:()=>Zc});import{existsSync as at,watch as qc}from"fs";import{readFile as Gr}from"fs/promises";import ct from"path";import Zn from"chalk";function eo(e){return e<=480?`${e} mobile`:e<=1024?`${e} tablet`:`${e} desktop`}function Xc(e,t){if(e){let o=e.split(",").map(r=>Number.parseInt(r.trim(),10)).filter(r=>Number.isFinite(r)&&r>0);if(o.length)return o.map(r=>({width:r,label:eo(r),figma:!1}))}let n=t?.breakpoints;return Array.isArray(n)&&n.length?n.map(o=>({width:Number(o.width),label:typeof o.label=="string"?o.label:eo(Number(o.width)),figma:o.source==="figma"})).filter(o=>Number.isFinite(o.width)&&o.width>0):Kc.map(o=>({width:o,label:eo(o),figma:!1}))}function Vc(e){if(!e?.figmaFileKey||typeof e.figmaFileKey!="string")return;let t=typeof e.figmaNodeId=="string"?e.figmaNodeId.replace(":","-"):void 0,n=`https://www.figma.com/design/${e.figmaFileKey}/preview`;return t?`${n}?node-id=${t}`:n}function Yc(e){return`<div class="${e} block">
879
+ `)},close:()=>new Promise(g=>{for(let y of s)y.end();d.close(()=>g())})})})};p(n)})}var Il,Ul,Bl,aa=w(()=>{"use strict";m();Il={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif",".avif":"image/avif",".woff":"font/woff",".woff2":"font/woff2",".ico":"image/x-icon"},Ul="/__eds_ping",Bl="/__eds_events"});var ft={};N(ft,{galleryPreview:()=>Wl,previewBlock:()=>Jl,startPreview:()=>fa});import{existsSync as ne,watch as la}from"fs";import{readFile as Wt,readdir as Hl}from"fs/promises";import Q from"path";import ge from"chalk";function po(e){return e<=480?`${e} mobile`:e<=1024?`${e} tablet`:`${e} desktop`}function da(e,t){if(e){let o=e.split(",").map(r=>Number.parseInt(r.trim(),10)).filter(r=>Number.isFinite(r)&&r>0);if(o.length)return o.map(r=>({width:r,label:po(r),figma:!1}))}let n=t?.breakpoints;return Array.isArray(n)&&n.length?n.map(o=>({width:Number(o.width),label:typeof o.label=="string"?o.label:po(Number(o.width)),figma:o.source==="figma"})).filter(o=>Number.isFinite(o.width)&&o.width>0):zl.map(o=>({width:o,label:po(o),figma:!1}))}function pa(e){if(!e?.figmaFileKey||typeof e.figmaFileKey!="string")return;let t=typeof e.figmaNodeId=="string"?e.figmaNodeId.replace(":","-"):void 0,n=`https://www.figma.com/design/${e.figmaFileKey}/preview`;return t?`${n}?node-id=${t}`:n}function ma(e){return`<div class="${e} block">
793
880
  <div><div>
794
881
  <h2>${e} heading</h2>
795
882
  <p>Sample body copy for the preview. Replace with real authored content.</p>
796
883
  <p><a href="#">Primary action</a></p>
797
884
  <p><a href="#">Secondary action</a></p>
798
885
  </div></div>
799
- </div>`}async function Qc(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{let{execa:n}=await import("execa");await n(t,[e],{stdio:"ignore",shell:process.platform==="win32"})}catch{}}async function Zc(e,t={}){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let o=ct.join(n,"blocks",e);if(!at(o)){i.error(`Block "${e}" not found at blocks/${e}/.`),process.exitCode=1;return}if(!at(ct.join(o,`${e}.css`))&&!at(ct.join(o,`${e}.js`))){i.error(`Block "${e}" has no ${e}.css / ${e}.js to preview.`),process.exitCode=1;return}let r=null,s=ct.join(o,".eds-meta.json");if(at(s))try{r=JSON.parse(await Gr(s,"utf-8"))}catch{}let a=ct.join(o,`_${e}.preview.html`),d,c=!1;at(a)?d=await Gr(a,"utf-8"):(d=Yc(e),c=!0);let l=Xc(t.widths,r),u=Vc(r),m="/__eds_preview_frame",f=Nr({blockName:e,breakpoints:l,sampleContent:d,frameRoute:m}),$=Ur({blockName:e,breakpoints:l,sampleContent:d,figmaUrl:u,frameRoute:m,placeholder:c}),v=Number.parseInt(t.port??"8777",10),x=await Br(n,{"/":{body:$,type:"text/html; charset=utf-8"},[m]:{body:f,type:"text/html; charset=utf-8"}},Number.isFinite(v)?v:8777);i.logoOnce(P(`Preview \u2014 ${e}`)),i.info(j("Live preview",x.url)),i.info(R("pass","breakpoints",`${l.map(A=>`${A.width}${A.figma?"\u2713":""}`).join(", ")}, Full`)),c&&i.info(R("warn","content",`placeholder \u2014 add blocks/${e}/_${e}.preview.html for real content`));let g,h=qc(o,{recursive:!0},()=>{clearTimeout(g),g=setTimeout(()=>x.reload(),150)});i.info(""),i.info(` ${Zn.bold("\u279C")} ${Zn.cyan(x.url)}`),i.info(R("pass","live reload","edits to the block refresh the browser")),i.info(Zn.dim(` Press Ctrl+C to stop.
800
- `)),t.open!==!1&&await Qc(x.url);let S=async()=>{h.close(),await x.close(),process.exit(0)};process.on("SIGINT",S),process.on("SIGTERM",S)}var Kc,Bt=b(()=>{"use strict";p();F();Ir();Hr();H();I();Kc=[375,768,1280]});var no={};U(no,{blockFromDesign:()=>il});import{existsSync as ke}from"fs";import{readFile as Re,writeFile as el}from"fs/promises";import ce from"path";import _ from"chalk";import to from"ora";async function tl(e=8777){try{let t=new AbortController,n=setTimeout(()=>t.abort(),400),o=await fetch(`http://127.0.0.1:${e}/__eds_ping`,{signal:t.signal});return clearTimeout(n),o.ok?(await o.json())?.eds===!0:!1}catch{return!1}}async function nl(e){let{input:t,select:n,confirm:o}=await import("@inquirer/prompts"),r=await n({message:"1/7 Design source",choices:[{name:"Figma",value:"figma"},{name:"Google Stitch",value:"stitch"},{name:"Canva",value:"canva"},{name:"Sketch",value:"sketch"},{name:"Framer",value:"framer"}],default:"figma"}),s=await t({message:"2/7 Component name",validate:S=>pe.test(S.trim())||"Use kebab-case, e.g. hero-banner"}),a=e??await t({message:`3/7 ${rt[r]} link`,validate:S=>{if(!S.trim())return"Paste the design link";if(r!=="figma")return!0;try{return Nt(S.trim()),!0}catch(A){return A.message}}}),d=await n({message:"4/7 Where does the content come from?",choices:[{name:"Document authoring (default EDS)",value:"document"},{name:"Universal Editor",value:"ue"},{name:"Content Fragment",value:"cf"},{name:"Mixed - Universal Editor + Content Fragment",value:"mixed"}],default:"document"}),c;(d==="cf"||d==="mixed")&&(c=(await t({message:" CF model / GraphQL persisted-query name (optional)"})).trim()||void 0);let l=await o({message:"5/7 Generate the Universal Editor model?",default:!0}),u=await o({message:"6/7 Fetch a screenshot for a pixel-perfect check? (off = fewer tokens)",default:!0}),m=await _t(),f=await n({message:"7/7 Run with",choices:[...m.map(S=>({name:`${S.type}${r==="figma"&&!S.hasFigmaMcp?" (Figma MCP not detected)":""}`,value:`agent:${S.type}`})),{name:"Preview the prompt only (--dry-run)",value:"dry-run"},{name:"Save the prompt, run it later (--agent none)",value:"none"}],default:m[0]?`agent:${m[0].type}`:"dry-run"}),$=rt[r].toLowerCase();i.info(j("Summary"));let v=M(["component",$,"content","ue model","screenshot","run"]);i.info(k("component",s,v));let x=r==="figma"?(()=>{let S=Nt(a.trim());return S.nodeId?`node ${S.nodeId}`:S.fileKey})():a.trim();if(i.info(k($,x,v)),i.info(k("content",d+(c?` (${c})`:""),v)),i.info(k("ue model",l?"yes":"no",v)),i.info(k("screenshot",u?"yes":"no (token-lean)",v)),i.info(k("run",f.replace("agent:",""),v)),i.info(""),!await o({message:"Generate this block?",default:!0}))return null;let h={figmaUrl:a.trim(),name:s,provider:r,source:d,cfHint:c,ueModel:l,screenshot:u};return f==="dry-run"?h.dryRun=!0:f==="none"?h.agent="none":(h.agent=f.replace("agent:",""),h.yes=!0),h}function ol(e){return e&&e.replace(/[-_\s]+/g,"-").replace(/[^a-z0-9-]/gi,"").toLowerCase().replace(/^-+|-+$/g,"")||"design-block"}async function il(e,t){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}await i.logoOnceAnimated("Design \u2192 EDS block");let o=e,r=t;if(!o){let C=await nl(o);if(!C){i.info("Cancelled.");return}o=C.figmaUrl,r={...r,...C}}let s=r.provider??"figma",a=rt[s],d=null,c=o;if(s==="figma"){let C=to("Parsing Figma URL...").start();try{d=Nt(o),C.succeed(`Parsed Figma URL ${_.dim(d.nodeId?`node ${d.nodeId}`:`file ${d.fileKey}`)}`)}catch(X){C.fail(X.message),process.exitCode=1;return}}else i.info(` ${G.pass} ${a} design ${_.dim(c)}`);let l=r.name||(d?ol(d.fileName):"");if(!pe.test(l)){i.error(`Invalid block name "${l}". Use --name with a kebab-case name (e.g., --name hero-banner).`),process.exitCode=1;return}let u=to("Reading design tokens & building prompt...").start(),m=await Mr({provider:s,figma:d,designRef:c,blockName:l,projectRoot:n,withUeModel:r.ueModel!==!1,contentSource:r.source??"document",cfHint:r.cfHint,screenshot:r.screenshot!==!1}),f=await Er(m,n),$=ke(ce.join(n,"styles","styles.css"));if(u.succeed($?`Loaded design tokens ${_.dim("styles/styles.css")}`:`Built prompt ${_.dim("no project tokens found")}`),i.info(_.dim(` prompt \u2192 ${f}`)),r.dryRun){i.info(""),i.info(_.yellow("Dry run mode \u2014 prompt generated but agent not invoked.")),i.info(`Prompt file: ${_.cyan(f)}`),i.info(`Block name: ${_.cyan(l)}`),i.info(`Prompt version: ${Ut}`),i.info(""),i.info("Preview:"),i.info(_.dim("\u2500".repeat(60))),console.log(m);return}let v=await ae(n),x=r.agent||v.agent;if(r.agent==="none"){i.info("Agent skipped (--agent none). Use the prompt file manually:"),i.info(` ${_.cyan(f)}`);return}let g=to("Detecting AI agent...").start(),h=await $r(x);if(!h){g.fail("No AI agent found (claude, cursor, or codex)."),i.info(`Install Claude Code: ${_.cyan("npm install -g @anthropic-ai/claude-code")}`),i.info(`Or use the prompt file manually: ${_.cyan(f)}`),process.exitCode=1;return}if(g.succeed(`Agent ready ${_.cyan(h.type)} ${_.dim(h.path)}`),s==="figma"&&!h.hasFigmaMcp&&(i.warn(`Figma MCP may not be configured for ${h.type}.`),i.info(`Run ${_.cyan("eds figma setup")} to configure it.`)),!r.yes){let{confirm:C}=await import("@inquirer/prompts");if(!await C({message:`Run ${h.type} with the generated prompt?`,default:!0})){i.info(`Prompt saved to: ${_.cyan(f)}`);return}}if(i.info(` ${_.dim("\u2192")} Handing off to ${_.cyan(h.type)} ${_.dim(`via ${a} MCP`)}`),s==="figma"&&i.info(_.dim(" get_design_context \xB7 get_variable_defs \xB7 get_screenshot")),!await Cr(h,f,n)){process.exitCode=1;return}let A=ce.join(n,"blocks",l),Y=await rl(A,l,r.ueModel!==!1);if(ke(A)){let C=ce.join(A,".eds-meta.json"),X;if(ke(C))try{X=JSON.parse(await Re(C,"utf-8")).breakpoints}catch{}let ne=Lr(r.widths,X),je={provider:s,designRef:c,figmaFileKey:d?.fileKey??null,figmaNodeId:d?.nodeId??null,lastSyncedAt:new Date().toISOString(),promptVersion:Ut,agentUsed:h.type,...ne.length?{breakpoints:ne}:{}};await el(C,`${JSON.stringify(je,null,2)}
801
- `),ne.length&&i.info(_.dim(` Preview breakpoints: ${ne.map(ls=>ls.width).join(" \xB7 ")}`))}if(!Y){i.warn(`Block "${l}" generated with issues \u2014 review the output above before publishing.`),process.exitCode=1;return}if(i.success(`Block "${l}" generation complete.`),!r.yes){let{confirm:C}=await import("@inquirer/prompts");if(await C({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:ne}=await Promise.resolve().then(()=>(Qe(),Ye));await ne(l,{})}}if(r.serve!==!1)if(await tl())i.info(_.dim(" A preview server is already running at http://127.0.0.1:8777 \u2014 your change will refresh there."));else{i.info("");let{previewBlock:C}=await Promise.resolve().then(()=>(Bt(),It));await C(l,{})}else i.info(` ${_.dim("\u2192")} Next: ${_.cyan(`eds block preview ${l}`)}`)}async function rl(e,t,n){let o=[],r=ce.join(e,`${t}.js`),s=ce.join(e,`${t}.css`),a=ke(r),d=ke(s);if(o.push({status:a?"pass":"fail",name:`${t}.js`,message:a?"created":"missing \u2014 agent did not write the JS file"}),o.push({status:d?"pass":"fail",name:`${t}.css`,message:d?"created":"missing \u2014 agent did not write the CSS file"}),a){let l=await Re(r,"utf-8");o.push({status:/export\s+default/.test(l)?"pass":"fail",name:"decorate export",message:/export\s+default/.test(l)?"found":"no default export \u2014 block won't load"}),l.includes("console.log")&&o.push({status:"warn",name:"no console.log",message:"found console.log \u2014 remove before production"})}if(d){let l=await Re(s,"utf-8");o.push({status:l.includes(`.${t}`)?"pass":"warn",name:"scoped CSS",message:l.includes(`.${t}`)?`scoped to .${t}`:`no .${t} selector \u2014 styles may leak`})}if(n){let l=ke(ce.join(e,`_${t}.json`)),u=ce.join(e,"..","..","component-models.json"),m=!1;if(!l&&ke(u))try{m=(await Re(u,"utf-8")).includes(`"${t}"`)}catch{}let f=l||m;if(o.push({status:f?"pass":"warn",name:"Universal Editor model",message:f?l?`_${t}.json created`:"added to component-models.json":`missing \u2014 no _${t}.json (run with default UE generation, or --no-ue-model to skip)`}),l&&a)try{let $=await Re(ce.join(e,`_${t}.json`),"utf-8"),v=await Re(r,"utf-8"),x=/"resourceType"\s*:\s*"[^"]*\/item"/.test($)||/"filter"\s*:/.test($)||/"multi"\s*:\s*true/.test($),g=/\.children/.test(v)||/\bfor\s*\(/.test(v)||/\.forEach\s*\(/.test(v);x&&o.push({status:g?"pass":"warn",name:"multifield wired",message:g?"decorate() iterates items":"repeatable model but decorate() never iterates block.children \u2014 only one item will render"})}catch{}}i.info(j("Verification"));let c=M(o.map(l=>l.name));for(let l of o)i.info(R(l.status,l.name,l.message,c));return i.info(""),!o.some(l=>l.status==="fail")}var oo=b(()=>{"use strict";p();qn();Pr();ve();Rr();Or();_r();F();H();Pe();I()});var Jr={};U(Jr,{listBlocks:()=>cl});import{existsSync as lt}from"fs";import{readFile as sl,readdir as al}from"fs/promises";import Oe from"path";import Me from"chalk";async function cl(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=Oe.join(t,"blocks");if(!lt(n)){i.info("No blocks/ directory found.");return}let o=await al(n,{withFileTypes:!0}),r=[];for(let a of o){if(!a.isDirectory())continue;let d=a.name,c=Oe.join(n,d),l={name:d,hasJs:lt(Oe.join(c,`${d}.js`)),hasCss:lt(Oe.join(c,`${d}.css`)),hasUeModel:lt(Oe.join(c,`_${d}.json`))},u=Oe.join(c,".eds-meta.json");if(lt(u))try{let m=JSON.parse(await sl(u,"utf-8"));l.figmaSource={fileKey:m.figmaFileKey,nodeId:m.figmaNodeId,lastSyncedAt:m.lastSyncedAt}}catch{}r.push(l)}if(e.json){console.log(JSON.stringify(r,null,2));return}if(r.length===0){i.info("No blocks found.");return}i.info(j("Blocks",`${r.length} in project`));let s=M(r.map(a=>a.name));for(let a of r){let d=[a.hasJs?L.ok("js"):Me.dim.strikethrough("js"),a.hasCss?L.ok("css"):Me.dim.strikethrough("css")];a.hasUeModel&&d.push(L.blue("ue-model")),a.figmaSource&&d.push(`${G.figma} ${L.dotPurple("figma")}`);let c=Ue(Me.bold(a.name),s);if(i.info(` ${c} ${Me.dim("[")}${d.join(" ")}${Me.dim("]")}`),a.figmaSource){let l=new Date(a.figmaSource.lastSyncedAt).toLocaleDateString();i.info(` ${" ".repeat(s)} ${G.arrow} ${Me.dim(`figma:${a.figmaSource.fileKey} \xB7 synced ${l}`)}`)}}i.info("")}var Wr=b(()=>{"use strict";p();F();H();I()});function zr(e){return Ht.find(t=>t.id===e)}function qr(e,t){return`
886
+ </div>`}async function sa(e,t,n){let o=Q.join(e,"blocks",t);if(!ne(Q.join(o,`${t}.css`))&&!ne(Q.join(o,`${t}.js`)))return null;let r=null,a=Q.join(o,".eds-meta.json");if(ne(a))try{r=JSON.parse(await Wt(a,"utf-8"))}catch{}let s=Q.join(o,`_${t}.preview.html`),d,l=!1;return ne(s)?d=await Wt(s,"utf-8"):(d=ma(t),l=!0),{name:t,sampleContent:d,breakpoints:da(n,r),figmaUrl:pa(r),placeholder:l}}async function ca(e){let t=Q.join(e,"blocks");if(!ne(t))return[];let n=await Hl(t,{withFileTypes:!0}),o=[];for(let r of n){if(!r.isDirectory()||Gl.has(r.name))continue;let a=Q.join(t,r.name);(ne(Q.join(a,`${r.name}.css`))||ne(Q.join(a,`${r.name}.js`)))&&o.push(r.name)}return o.sort()}async function ua(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{let{execa:n}=await import("execa");await n(t,[e],{stdio:"ignore",shell:process.platform==="win32"})}catch{}}async function fa(e,t={}){let n=E();if(!n)return i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1,null;let o=Q.join(n,"blocks",e);if(!ne(o))return i.error(`Block "${e}" not found at blocks/${e}/.`),process.exitCode=1,null;if(!ne(Q.join(o,`${e}.css`))&&!ne(Q.join(o,`${e}.js`)))return i.error(`Block "${e}" has no ${e}.css / ${e}.js to preview.`),process.exitCode=1,null;(e==="header"||e==="footer")&&(i.warn(`"${e}" is page chrome, not a content block \u2014 it won't render standalone here.`),i.info(ge.dim(` It fetches the ${e==="header"?"nav":"footer"} fragment and needs the full page runtime.`)),i.info(ge.dim(" Preview a content block instead (e.g. a block generated from a design).")));let r=null,a=Q.join(o,".eds-meta.json");if(ne(a))try{r=JSON.parse(await Wt(a,"utf-8"))}catch{}let s=Q.join(o,`_${e}.preview.html`),d,l=!1;ne(s)?d=await Wt(s,"utf-8"):(d=ma(e),l=!0);let c=da(t.widths,r),u=pa(r),p="/__eds_preview_frame",f=so({blockName:e,breakpoints:c,sampleContent:d,frameRoute:p}),g=ia({blockName:e,breakpoints:c,sampleContent:d,figmaUrl:u,frameRoute:p,placeholder:l}),y=Number.parseInt(t.port??"8777",10),h=await lo(n,{"/":{body:g,type:"text/html; charset=utf-8"},[p]:{body:f,type:"text/html; charset=utf-8"}},Number.isFinite(y)?y:8777);i.logoOnce(P(`Preview \u2014 ${e}`)),i.info(j("Live preview",h.url)),i.info(D("pass","breakpoints",`${c.map(x=>`${x.width}${x.figma?"\u2713":""}`).join(", ")}, Full`)),l&&i.info(D("warn","content",`placeholder \u2014 add blocks/${e}/_${e}.preview.html for real content`));let b,S=la(o,{recursive:!0},()=>{clearTimeout(b),b=setTimeout(()=>h.reload(),150)});return i.info(""),i.info(` ${ge.bold("\u279C")} ${ge.cyan(h.url)}`),i.info(D("pass","live reload","edits to the block refresh the browser")),t.open!==!1&&await ua(h.url),{url:h.url,close:async()=>{S.close(),await h.close()}}}async function Jl(e,t={}){let n=await fa(e,t);n&&(i.info(ge.dim(` Press Ctrl+C to stop.
887
+ `)),await new Promise(o=>{let r=async()=>{await n.close(),o(),process.exit(0)};process.on("SIGINT",r),process.on("SIGTERM",r)}))}async function Wl(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n="/__eds_frame/",o=async c=>{if(c==="/"){let u=await ca(t),p=[];for(let f of u){let g=await sa(t,f,e.widths);g&&p.push({blockName:f,breakpoints:g.breakpoints,frameRoute:n+f,figmaUrl:g.figmaUrl,placeholder:g.placeholder})}return{body:oa(p),type:"text/html; charset=utf-8"}}if(c.startsWith(n)){let u=c.slice(n.length);if(!/^[a-z0-9-]+$/i.test(u))return;let p=await sa(t,u,e.widths);return p?{body:so({blockName:u,breakpoints:p.breakpoints,sampleContent:p.sampleContent,frameRoute:n+u}),type:"text/html; charset=utf-8"}:void 0}},r=Number.parseInt(e.port??"8777",10),a=await lo(t,{},Number.isFinite(r)?r:8777,"127.0.0.1",o),s=await ca(t);i.logoOnce(P("Preview \u2014 gallery")),i.info(j("Live gallery",a.url)),i.info(D(s.length?"pass":"warn","blocks",s.length?s.join(", "):"none yet \u2014 generate one with eds block from-design"));let d,l=la(Q.join(t,"blocks"),{recursive:!0},()=>{clearTimeout(d),d=setTimeout(()=>a.reload(),150)});i.info(""),i.info(` ${ge.bold("\u279C")} ${ge.cyan(a.url)}`),i.info(D("pass","live reload","new & edited blocks refresh the browser")),i.info(ge.dim(` Press Ctrl+C to stop.
888
+ `)),e.open!==!1&&await ua(a.url),await new Promise(c=>{let u=async()=>{l.close(),await a.close(),c(),process.exit(0)};process.on("SIGINT",u),process.on("SIGTERM",u)})}var Gl,zl,gt=w(()=>{"use strict";m();R();ra();aa();z();I();Gl=new Set(["header","footer"]),zl=[375,768,1280]});var mo={};N(mo,{blockFromDesign:()=>Ql});import{existsSync as se}from"fs";import{readFile as Ge,writeFile as ql}from"fs/promises";import W from"path";import C from"chalk";import qt from"ora";async function Kl(e=8777){try{let t=new AbortController,n=setTimeout(()=>t.abort(),400),o=await fetch(`http://127.0.0.1:${e}/__eds_ping`,{signal:t.signal});return clearTimeout(n),o.ok?(await o.json())?.eds===!0:!1}catch{return!1}}async function Xl(e){let{input:t,select:n,confirm:o}=await Promise.resolve().then(()=>(B(),U)),r=await n({message:"1/7 Design source",choices:[{name:"Figma",value:"figma"},{name:"Google Stitch",value:"stitch"},{name:"Canva",value:"canva"},{name:"Sketch",value:"sketch"},{name:"Framer",value:"framer"}],default:"figma"}),a=await t({message:"2/7 Component name",validate:x=>ye.test(x.trim())||"Use kebab-case, e.g. hero-banner"}),s=e??await t({message:`3/7 ${He[r]} link`,validate:x=>{if(!x.trim())return"Paste the design link";if(r!=="figma")return!0;try{return Jt(x.trim()),!0}catch(T){return T.message}}}),d=await n({message:"4/7 Where does the content come from?",choices:[{name:"Document authoring (default EDS)",value:"document"},{name:"Universal Editor",value:"ue"},{name:"Content Fragment",value:"cf"},{name:"Mixed - Universal Editor + Content Fragment",value:"mixed"}],default:"document"}),l;(d==="cf"||d==="mixed")&&(l=(await t({message:" CF model / GraphQL persisted-query name (optional)"})).trim()||void 0);let c=await o({message:"5/7 Generate the Universal Editor model?",default:!0}),u=await o({message:"6/7 Add a screenshot MCP call for a pixel check? (off = one fewer MCP call)",default:!1}),p=await zt(),f=await n({message:"7/7 Run with",choices:[...p.map(x=>({name:`${x.type}${r==="figma"&&!x.hasFigmaMcp?" (Figma MCP not detected)":""}`,value:`agent:${x.type}`})),{name:"Preview the prompt only (--dry-run)",value:"dry-run"},{name:"Save the prompt, run it later (--agent none)",value:"none"}],default:p[0]?`agent:${p[0].type}`:"dry-run"}),g=He[r].toLowerCase();i.info(j("Summary"));let y=O(["component",g,"content","ue model","screenshot","run"]);i.info($("component",a,y));let h=r==="figma"?(()=>{let x=Jt(s.trim());return x.nodeId?`node ${x.nodeId}`:x.fileKey})():s.trim();if(i.info($(g,h,y)),i.info($("content",d+(l?` (${l})`:""),y)),i.info($("ue model",c?"yes":"no",y)),i.info($("screenshot",u?"yes":"no (token-lean)",y)),i.info($("run",f.replace("agent:",""),y)),i.info(""),!await o({message:"Generate this block?",default:!0}))return null;let S={figmaUrl:s.trim(),name:a,provider:r,source:d,cfHint:l,ueModel:c,screenshot:u};return f==="dry-run"?S.dryRun=!0:f==="none"?S.agent="none":(S.agent=f.replace("agent:",""),S.yes=!0),S}function ga(e){return e&&e.replace(/[-_\s]+/g,"-").replace(/[^a-z0-9-]/gi,"").toLowerCase().replace(/^-+|-+$/g,"")||"design-block"}function Yl(e){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(e))return null;let t=W.isAbsolute(e)?e:W.resolve(process.cwd(),e);return!se(t)||!Vl.has(W.extname(t).toLowerCase())?null:t}async function Ql(e,t){let n=E();if(!n){i.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}await i.logoOnceAnimated("Design \u2192 EDS block");let o=e,r=t;if(!o){let K=await Xl(o);if(!K){i.info("Cancelled.");return}o=K.figmaUrl,r={...r,...K}}let a=r.provider??"figma",s=He[a],d=Yl(o),l=d?d.startsWith(n+W.sep)?W.relative(n,d):d:void 0,c=null,u=l??o;if(d)i.info(` ${J.pass} Local design file ${C.dim(l)} ${C.dim("(no Figma MCP)")}`);else if(a==="figma"){let K=qt("Parsing Figma URL...").start();try{c=Jt(o),K.succeed(`Parsed Figma URL ${C.dim(c.nodeId?`node ${c.nodeId}`:`file ${c.fileKey}`)}`)}catch(Re){K.fail(Re.message),process.exitCode=1;return}}else i.info(` ${J.pass} ${s} design ${C.dim(u)}`);let p=r.name||(d?ga(W.basename(d,W.extname(d))):c?ga(c.fileName):"");if(!ye.test(p)){i.error(`Invalid block name "${p}". Use --name with a kebab-case name (e.g., --name hero-banner).`),process.exitCode=1;return}!r.name&&c?.nodeId&&(i.warn(`Block name "${p}" came from the Figma file name, not the selected frame.`),i.info(C.dim(` Pass ${C.cyan("--name <kebab-case>")} for a cleaner block name.`)));let f=await fe(n),g=f.figma?.token??process.env.FIGMA_TOKEN??process.env.FIGMA_PAT,y=qt("Resolving design source...").start(),h=await Yr({figma:c,localFile:l,token:g,projectRoot:n,preferMcp:r.mcp,refresh:r.refresh});y.succeed(`Design source ${C.dim(h.summary)}`),h.restError&&i.warn(`Figma REST fetch failed, using MCP fallback: ${h.restError}`);let b=qt("Reading design tokens & building prompt...").start(),S=await ea({provider:a,figma:c,designRef:u,blockName:p,projectRoot:n,withUeModel:r.ueModel!==!1,contentSource:r.source??"document",cfHint:r.cfHint,screenshot:r.screenshot===!0,design:h.design}),x=await Zn(S,n),T=se(W.join(n,"styles","styles.css"));if(b.succeed(T?`Loaded design tokens ${C.dim("styles/styles.css")}`:`Built prompt ${C.dim("no project tokens found")}`),i.info(C.dim(` prompt \u2192 ${x}`)),r.dryRun){i.info(""),i.info(C.yellow("Dry run mode \u2014 prompt generated but agent not invoked.")),i.info(`Prompt file: ${C.cyan(x)}`),i.info(`Block name: ${C.cyan(p)}`),i.info(`Prompt version: ${ut}`),i.info(""),i.info("Preview:"),i.info(C.dim("\u2500".repeat(60))),console.log(S);return}let oe=r.agent||f.agent;if(r.agent==="none"){i.info("Agent skipped (--agent none). Use the prompt file manually:"),i.info(` ${C.cyan(x)}`);return}let H=qt("Detecting AI agent...").start(),q=await Mr(oe);if(!q){H.fail("No AI agent found (claude, cursor, or codex)."),i.info(`Install Claude Code: ${C.cyan("npm install -g @anthropic-ai/claude-code")}`),i.info(`Or use the prompt file manually: ${C.cyan(x)}`),process.exitCode=1;return}if(H.succeed(`Agent ready ${C.cyan(q.type)} ${C.dim(q.path)}`),(h.design?.mode==="mcp"||!h.design&&a==="figma")&&a==="figma"&&!q.hasFigmaMcp&&(i.warn(`Figma MCP may not be configured for ${q.type}.`),i.info(`Run ${C.cyan("eds figma setup")} to configure it, or set a Figma token for REST.`)),!r.yes){let{confirm:K}=await Promise.resolve().then(()=>(B(),U));if(!await K({message:`Run ${q.type} with the generated prompt?`,default:!0})){i.info(`Prompt saved to: ${C.cyan(x)}`);return}}let Te=h.design?.mode==="spec"?"embedded design (no MCP)":h.design?.mode==="file"?`reading ${l}`:h.design?.mode==="mcp"?`via ${s} MCP (1 call, cached)`:`via ${s} MCP`;if(i.info(` ${C.dim("\u2192")} Handing off to ${C.cyan(q.type)} ${C.dim(Te)}`),h.design?.mode==="mcp"&&i.info(C.dim(" get_design_context \xD71 \u2192 cache")),!await eo(q,x,n,f.model)){process.exitCode=1;return}let Ke=W.join(n,"blocks",p);if(!(se(W.join(Ke,`${p}.js`))||se(W.join(Ke,`${p}.css`)))){i.warn(`No block files were written to blocks/${p}/ \u2014 nothing to preview.`),i.info(C.dim(" The agent couldn't read the design, so it generated nothing. Common cause: the")),i.info(C.dim(` ${s} MCP tool-call limit (e.g. Figma Starter plan). See the log above.`)),i.info(C.dim(" Wait for the limit to reset or upgrade the plan, then re-run the same command.")),process.exitCode=1;return}let Oa=await ed(Ke,p,r.ueModel!==!1);if(se(Ke)){let K=W.join(Ke,".eds-meta.json"),Re;if(se(K))try{Re=JSON.parse(await Ge(K,"utf-8")).breakpoints}catch{}let De=Hr(r.widths,Re),Ma={provider:a,designRef:u,figmaFileKey:c?.fileKey??null,figmaNodeId:c?.nodeId??null,lastSyncedAt:new Date().toISOString(),promptVersion:ut,agentUsed:q.type,...De.length?{breakpoints:De}:{}};await ql(K,`${JSON.stringify(Ma,null,2)}
889
+ `),De.length&&i.info(C.dim(` Preview breakpoints: ${De.map(Na=>Na.width).join(" \xB7 ")}`))}if(!Oa){i.warn(`Block "${p}" generated with issues \u2014 review the output above before publishing.`),process.exitCode=1;return}if(i.success(`Block "${p}" generation complete.`),!r.yes){let{confirm:K}=await Promise.resolve().then(()=>(B(),U));if(await K({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:De}=await Promise.resolve().then(()=>(at(),rt));await De(p,{})}}if(!r.yes)await Zl({blockName:p,projectRoot:n,agent:q,model:f.model,provider:a,figma:c,designRef:u});else if(r.serve){let{previewBlock:K}=await Promise.resolve().then(()=>(gt(),ft));await K(p,{})}else i.info(` ${C.dim("\u2192")} Next: ${C.cyan(`eds block preview ${p}`)}`)}async function Zl(e){let{select:t,input:n}=await Promise.resolve().then(()=>(B(),U)),{startPreview:o}=await Promise.resolve().then(()=>(gt(),ft)),r=null;for(i.info("");;){let a=await t({message:"Block ready \u2014 what next?",choices:[{name:"Refine \u2014 describe a change",value:"refine"},{name:r?`Preview open at ${r.url} (reloads on change)`:"Open live preview",value:"preview",disabled:r?"running":!1},{name:"Finish",value:"done"}],default:"refine"});if(a==="done")break;if(a==="preview"){await Kl()?i.info(C.dim(" A preview server is already running at http://127.0.0.1:8777.")):r=await o(e.blockName,{});continue}let s=(await n({message:"Describe the change:"})).trim();if(!s)continue;let d=ta({blockName:e.blockName,feedback:s,provider:e.provider,figma:e.figma,designRef:e.designRef}),l=await Zn(d,e.projectRoot);i.info(` ${C.dim("\u2192")} Applying your change with ${C.cyan(e.agent.type)}\u2026`),await eo(e.agent,l,e.projectRoot,e.model)}r&&(i.info(C.dim(` Preview still live at ${r.url} \u2014 press Ctrl+C to stop.
890
+ `)),await new Promise(a=>{let s=async()=>{r&&await r.close(),a(),process.exit(0)};process.on("SIGINT",s),process.on("SIGTERM",s)}))}async function ed(e,t,n){let o=[],r=W.join(e,`${t}.js`),a=W.join(e,`${t}.css`),s=se(r),d=se(a);if(o.push({status:s?"pass":"fail",name:`${t}.js`,message:s?"created":"missing \u2014 agent did not write the JS file"}),o.push({status:d?"pass":"fail",name:`${t}.css`,message:d?"created":"missing \u2014 agent did not write the CSS file"}),s){let c=await Ge(r,"utf-8");o.push({status:/export\s+default/.test(c)?"pass":"fail",name:"decorate export",message:/export\s+default/.test(c)?"found":"no default export \u2014 block won't load"}),c.includes("console.log")&&o.push({status:"warn",name:"no console.log",message:"found console.log \u2014 remove before production"})}if(d){let c=await Ge(a,"utf-8");o.push({status:c.includes(`.${t}`)?"pass":"warn",name:"scoped CSS",message:c.includes(`.${t}`)?`scoped to .${t}`:`no .${t} selector \u2014 styles may leak`})}if(n){let c=se(W.join(e,`_${t}.json`)),u=W.join(e,"..","..","component-models.json"),p=!1;if(!c&&se(u))try{p=(await Ge(u,"utf-8")).includes(`"${t}"`)}catch{}let f=c||p;if(o.push({status:f?"pass":"warn",name:"Universal Editor model",message:f?c?`_${t}.json created`:"added to component-models.json":`missing \u2014 no _${t}.json (run with default UE generation, or --no-ue-model to skip)`}),c&&s)try{let g=await Ge(W.join(e,`_${t}.json`),"utf-8"),y=await Ge(r,"utf-8"),h=/"resourceType"\s*:\s*"[^"]*\/item"/.test(g)||/"filter"\s*:/.test(g)||/"multi"\s*:\s*true/.test(g),b=/\.children/.test(y)||/\bfor\s*\(/.test(y)||/\.forEach\s*\(/.test(y);h&&o.push({status:b?"pass":"warn",name:"multifield wired",message:b?"decorate() iterates items":"repeatable model but decorate() never iterates block.children \u2014 only one item will render"})}catch{}}i.info(j("Verification"));let l=O(o.map(c=>c.name));for(let c of o)i.info(D(c.status,c.name,c.message,l));return i.info(""),!o.some(c=>c.status==="fail")}var Vl,uo=w(()=>{"use strict";m();Qn();Nr();Pe();Gr();Qr();Zr();na();R();z();Me();I();Vl=new Set([".svg",".png",".jpg",".jpeg",".webp"])});var ha={};N(ha,{listBlocks:()=>od});import{existsSync as ht}from"fs";import{readFile as td,readdir as nd}from"fs/promises";import ze from"path";import Je from"chalk";async function od(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=ze.join(t,"blocks");if(!ht(n)){i.info("No blocks/ directory found.");return}let o=await nd(n,{withFileTypes:!0}),r=[];for(let s of o){if(!s.isDirectory())continue;let d=s.name,l=ze.join(n,d),c={name:d,hasJs:ht(ze.join(l,`${d}.js`)),hasCss:ht(ze.join(l,`${d}.css`)),hasUeModel:ht(ze.join(l,`_${d}.json`))},u=ze.join(l,".eds-meta.json");if(ht(u))try{let p=JSON.parse(await td(u,"utf-8"));c.figmaSource={fileKey:p.figmaFileKey,nodeId:p.figmaNodeId,lastSyncedAt:p.lastSyncedAt}}catch{}r.push(c)}if(e.json){console.log(JSON.stringify(r,null,2));return}if(r.length===0){i.info("No blocks found.");return}i.info(j("Blocks",`${r.length} in project`));let a=O(r.map(s=>s.name));for(let s of r){let d=[s.hasJs?_.ok("js"):Je.dim.strikethrough("js"),s.hasCss?_.ok("css"):Je.dim.strikethrough("css")];s.hasUeModel&&d.push(_.blue("ue-model")),s.figmaSource&&d.push(`${J.figma} ${_.dotPurple("figma")}`);let l=Xe(Je.bold(s.name),a);if(i.info(` ${l} ${Je.dim("[")}${d.join(" ")}${Je.dim("]")}`),s.figmaSource){let c=new Date(s.figmaSource.lastSyncedAt).toLocaleDateString();i.info(` ${" ".repeat(a)} ${J.arrow} ${Je.dim(`figma:${s.figmaSource.fileKey} \xB7 synced ${c}`)}`)}}i.info("")}var ba=w(()=>{"use strict";m();R();z();I()});function wa(e){return Kt.find(t=>t.id===e)}function ya(e,t){return`
802
891
  // \u2500\u2500 ${e} (eds integrate) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
803
892
  {
804
893
  ${t.split(`
805
894
  `).map(n=>n&&` ${n}`).join(`
806
895
  `)}
807
896
  }
808
- `}var Ht,Kr=b(()=>{"use strict";p();Ht=[{id:"gtm",name:"Google Tag Manager",fields:[{name:"id",message:"GTM container ID",placeholder:"GTM-XXXXXXX"}],code:()=>`// Google Tag Manager - loaded from ./analytics.js (delayed phase, after LCP).
897
+ `}var Kt,va=w(()=>{"use strict";m();Kt=[{id:"gtm",name:"Google Tag Manager",fields:[{name:"id",message:"GTM container ID",placeholder:"GTM-XXXXXXX"}],code:()=>`// Google Tag Manager - loaded from ./analytics.js (delayed phase, after LCP).
809
898
  import { loadGTM } from './analytics.js';
810
899
  import pageMetaPush from './page-meta.js';
811
900
 
@@ -832,7 +921,7 @@ window.dataLayer = window.dataLayer || [];
832
921
  export function trackEvent(event) {
833
922
  if (isDev()) {
834
923
  // eslint-disable-next-line no-console
835
- console.log('[gtm]', JSON.stringify(event, null, 2));
924
+ console.log('[gtm]', event);
836
925
  }
837
926
  window.dataLayer.push(event);
838
927
  }
@@ -896,19 +985,19 @@ document.head.appendChild(cb);`},{id:"custom",name:"Custom third-party script",f
896
985
  const s = document.createElement('script');
897
986
  s.async = true;
898
987
  s.src = ${JSON.stringify(e.url||"")};
899
- document.head.appendChild(s);`}]});var ro={};U(ro,{integrate:()=>pl});import{existsSync as ll}from"fs";import{mkdir as Xr,readFile as dl,writeFile as Vr}from"fs/promises";import Gt from"path";import io from"chalk";async function pl(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Integrate - third-party service"));let{select:n,input:o}=await import("@inquirer/prompts"),r=e||await n({message:"Which service do you want to add?",choices:Ht.map(m=>({name:m.name,value:m.id}))}),s=zr(r);if(!s){i.error(`Unknown integration "${r}". Options: ${Ht.map(m=>m.id).join(", ")}`),process.exitCode=1;return}let a={};for(let m of s.fields){let f=await o({message:` ${m.message}`,default:m.placeholder});a[m.name]=f.trim()}let d=[];if(s.module)for(let m of s.module(a)){let f=Gt.join(t,m.file);await Xr(Gt.dirname(f),{recursive:!0}),await Vr(f,m.content),d.push(m.file)}let c=s.module?`
900
- // ${s.name} (eds integrate)
901
- ${s.code(a)}
902
- `:qr(s.name,s.code(a)),l=Gt.join(t,"scripts","delayed.js");await Xr(Gt.dirname(l),{recursive:!0});let u=ll(l)?await dl(l,"utf-8"):ml;await Vr(l,`${u.replace(/\s*$/,"")}
903
- ${c}`),i.info(j("Added"));for(let m of d)i.info(k(s.name,`wrote ${m}`));i.info(k(s.name,"wired into scripts/delayed.js")),i.info(""),i.info(io.dim(" Loads after LCP (delayed phase) - zero impact on your Core Web Vitals.")),(s.id==="gtm"||s.id==="ga4")&&i.info(io.dim(" Tip: gate analytics behind user consent (add the Cookiebot integration).")),s.id==="chat"&&i.info(io.dim(" The widget loads only when the visitor clicks the button (facade pattern).")),i.info(""),i.info(O(["Integration added"]))}var ml,so=b(()=>{"use strict";p();Kr();F();H();I();ml=`// delayed.js - third-party / non-critical scripts.
988
+ document.head.appendChild(s);`}]});var go={};N(go,{integrate:()=>sd});import{existsSync as id}from"fs";import{mkdir as ka,readFile as rd,writeFile as xa}from"fs/promises";import Xt from"path";import fo from"chalk";async function sd(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Integrate - third-party service"));let{select:n,input:o}=await Promise.resolve().then(()=>(B(),U)),r=e||await n({message:"Which service do you want to add?",choices:Kt.map(p=>({name:p.name,value:p.id}))}),a=wa(r);if(!a){i.error(`Unknown integration "${r}". Options: ${Kt.map(p=>p.id).join(", ")}`),process.exitCode=1;return}let s={};for(let p of a.fields){let f=await o({message:` ${p.message}`,default:p.placeholder});s[p.name]=f.trim()}let d=[];if(a.module)for(let p of a.module(s)){let f=Xt.join(t,p.file);await ka(Xt.dirname(f),{recursive:!0}),await xa(f,p.content),d.push(p.file)}let l=a.module?`
989
+ // ${a.name} (eds integrate)
990
+ ${a.code(s)}
991
+ `:ya(a.name,a.code(s)),c=Xt.join(t,"scripts","delayed.js");await ka(Xt.dirname(c),{recursive:!0});let u=id(c)?await rd(c,"utf-8"):ad;await xa(c,`${u.replace(/\s*$/,"")}
992
+ ${l}`),i.info(j("Added"));for(let p of d)i.info($(a.name,`wrote ${p}`));i.info($(a.name,"wired into scripts/delayed.js")),i.info(""),i.info(fo.dim(" Loads after LCP (delayed phase) - zero impact on your Core Web Vitals.")),(a.id==="gtm"||a.id==="ga4")&&i.info(fo.dim(" Tip: gate analytics behind user consent (add the Cookiebot integration).")),a.id==="chat"&&i.info(fo.dim(" The widget loads only when the visitor clicks the button (facade pattern).")),i.info(""),i.info(L(["Integration added"]))}var ad,ho=w(()=>{"use strict";m();va();R();z();I();ad=`// delayed.js - third-party / non-critical scripts.
904
993
  // Loaded in the EDS delayed phase (after LCP), so nothing here blocks the page.
905
- `});var ao={};U(ao,{figmaSetup:()=>hl});import{existsSync as ul}from"fs";import{mkdir as fl,writeFile as gl}from"fs/promises";import Q from"chalk";async function hl(){let{select:e,confirm:t}=await import("@inquirer/prompts");i.logoOnce(P()),i.info(j("Figma MCP Setup Wizard")),i.info("Detecting installed AI agents...");let n=await _t(),o;if(n.length===0?(i.warn("No AI agents found (claude, cursor, codex)."),i.info(`Install Claude Code: ${Q.cyan("npm install -g @anthropic-ai/claude-code")}`),o="none"):(i.success(`Found: ${n.map(s=>Q.cyan(s.type)).join(", ")}`),o=await e({message:"Which agent do you want to use with eds-cli?",choices:[...n.map(s=>({name:`${s.type}${s.hasFigmaMcp?Q.green(" (Figma MCP detected)"):""}`,value:s.type})),{name:"None (manual mode)",value:"none"}]})),o!=="none"){let s=n.find(a=>a.type===o);if(s&&!s.hasFigmaMcp){switch(i.warn(`Figma MCP is not configured for ${o}.
994
+ `});var bo={};N(bo,{figmaSetup:()=>pd});import{existsSync as cd}from"fs";import{mkdir as ld,writeFile as dd}from"fs/promises";import ie from"chalk";async function pd(){let{select:e,confirm:t}=await Promise.resolve().then(()=>(B(),U));i.logoOnce(P()),i.info(j("Figma MCP Setup Wizard")),i.info("Detecting installed AI agents...");let n=await zt(),o;if(n.length===0?(i.warn("No AI agents found (claude, cursor, codex)."),i.info(`Install Claude Code: ${ie.cyan("npm install -g @anthropic-ai/claude-code")}`),o="none"):(i.success(`Found: ${n.map(a=>ie.cyan(a.type)).join(", ")}`),o=await e({message:"Which agent do you want to use with eds-cli?",choices:[...n.map(a=>({name:`${a.type}${a.hasFigmaMcp?ie.green(" (Figma MCP detected)"):""}`,value:a.type})),{name:"None (manual mode)",value:"none"}]})),o!=="none"){let a=n.find(s=>s.type===o);if(a&&!a.hasFigmaMcp){switch(i.warn(`Figma MCP is not configured for ${o}.
906
995
  `),i.info(`Install it with one of these methods:
907
- `),o){case"claude":i.info(` ${Q.cyan("claude mcp add --transport sse figma-sse https://mcp.figma.com/sse")}`),i.info(" or for Figma Desktop app:"),i.info(` ${Q.cyan("claude mcp add --transport http figma-desktop http://127.0.0.1:3845/mcp")}`);break;case"cursor":i.info(` Add to ${Q.cyan("~/.cursor/mcp.json")}:`),i.info(Q.dim(JSON.stringify({mcpServers:{figma:{url:"https://mcp.figma.com/sse"}}},null,2)));break;case"codex":i.info(" See Figma MCP docs: https://help.figma.com/hc/en-us/articles/32132100833559");break}i.info("")}else s?.hasFigmaMcp&&i.success(`Figma MCP is already configured for ${o}!`)}if(i.info(Q.dim(`
908
- Note: Figma MCP requires a Figma seat (Dev or Full on paid plans for desktop server).`)),await t({message:"Save preferences to ~/.eds/config.json?",default:!0})){let s=Fr();ul(s)||await fl(s,{recursive:!0});let a={};o!=="none"&&(a.agent=o),await gl(Vn(),`${JSON.stringify(a,null,2)}
909
- `,{mode:384}),i.success(`Config saved to ${Q.cyan(Vn())}`)}i.info(Q.bold(`
910
- Setup complete!`)),o!=="none"&&i.info(`Try: ${Q.cyan('eds block from-design "<figma-url>" --dry-run')}`)}var co=b(()=>{"use strict";p();qn();ve();F();I()});var lo={};U(lo,{doctor:()=>wl});import{existsSync as dt}from"fs";import{readFile as mt,readdir as bl}from"fs/promises";import xe from"path";import{parse as Yr}from"yaml";async function wl(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=Vo(t);e.json||(i.logoOnce(P("Doctor")),i.info(j("Doctor",t)));let o=[];if(o.push({name:"fstab.yaml exists",status:n.hasFstab?"pass":"warn",message:n.hasFstab?"Found":"Missing - fine for Universal Editor / DA; required for document-mounted setups"}),n.hasFstab)try{let m=await mt(xe.join(t,"fstab.yaml"),"utf-8");Yr(m),o.push({name:"fstab.yaml valid YAML",status:"pass",message:"Valid"})}catch{o.push({name:"fstab.yaml valid YAML",status:"fail",message:"Invalid YAML syntax"})}if(o.push({name:"head.html exists",status:n.hasHeadHtml?"pass":"warn",message:n.hasHeadHtml?"Found":"Missing - recommended for metadata/scripts"}),o.push({name:"blocks/ directory",status:n.hasBlocks?"pass":"warn",message:n.hasBlocks?"Found":"Missing - no blocks yet"}),n.hasBlocks){let m=xe.join(t,"blocks"),f=await bl(m,{withFileTypes:!0}),$="",v=xe.join(t,"component-models.json");if(dt(v))try{$=await mt(v,"utf-8")}catch{}for(let x of f){if(!x.isDirectory())continue;let g=x.name,h=xe.join(m,g,`${g}.js`),S=dt(h);o.push({name:`blocks/${g} has JS`,status:S?"pass":"warn",message:S?"Found":`Missing ${g}.js`}),S&&(await mt(h,"utf-8")).includes("console.log")&&o.push({name:`blocks/${g} no console.log`,status:"warn",message:"Found console.log - remove before production"});let A=dt(xe.join(m,g,`_${g}.json`)),Y=$.includes(`"${g}"`);o.push({name:`blocks/${g} UE model`,status:A||Y?"pass":"warn",message:A||Y?A?`_${g}.json`:"in component-models.json":"no Universal Editor model - authors can't edit this block in UE"});let C=xe.join(m,g,".eds-meta.json");if(dt(C))try{let X=JSON.parse(await mt(C,"utf-8")),ne=new Date(X.lastSyncedAt),je=Math.floor((Date.now()-ne.getTime())/(1e3*60*60*24));o.push({name:`blocks/${g} Figma sync`,status:je>30?"warn":"pass",message:je>30?`Last synced ${je} days ago - design may have changed`:`Synced ${je} days ago`})}catch{o.push({name:`blocks/${g} .eds-meta.json`,status:"warn",message:"Invalid metadata file"})}}}let r=xe.join(t,"helix-query.yaml");if(dt(r))try{let m=await mt(r,"utf-8");Yr(m),o.push({name:"helix-query.yaml valid",status:"pass",message:"Valid YAML"})}catch{o.push({name:"helix-query.yaml valid",status:"fail",message:"Invalid YAML syntax"})}o.push({name:"~/.eds/config.json",status:Yn()?"pass":"warn",message:Yn()?"Found":'Missing - run "eds figma setup" to configure'});let s=o.filter(m=>m.status==="fail"),a=o.filter(m=>m.status==="warn");if(e.json){let m={pass:o.filter(f=>f.status==="pass").length,warn:a.length,fail:s.length};console.log(JSON.stringify({projectRoot:t,results:o,summary:m},null,2)),s.length>0&&(process.exitCode=1);return}let d=M(o.map(m=>m.name));for(let m of o)i.info(R(m.status,m.name,m.message,d));let c=o.filter(m=>m.status==="fail"),l=o.filter(m=>m.status==="warn"),u=o.filter(m=>m.status==="pass");i.info(""),i.info(O([oe({pass:u.length,warn:l.length,fail:c.length})])),c.length>0&&(process.exitCode=1)}var mo=b(()=>{"use strict";p();ve();F();H();I()});var uo={};U(uo,{auditLoading:()=>vl});import{existsSync as le}from"fs";import{readFile as _e,readdir as yl,stat as Qr}from"fs/promises";import de from"path";import po from"chalk";async function vl(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}e.json||(i.logoOnce(P("Loading Audit")),i.info(j("Loading Order Audit",t)));let n=[];if(await kl(t,n),await xl(t,n),await Sl(t,n),await jl(t,n),await $l(t,n),await El(t,n),e.json){let o={pass:n.filter(r=>r.status==="pass").length,warn:n.filter(r=>r.status==="warn").length,fail:n.filter(r=>r.status==="fail").length,info:n.filter(r=>r.status==="info").length};console.log(JSON.stringify({projectRoot:t,results:n,summary:o},null,2)),o.fail>0&&(process.exitCode=1);return}Pl(n)}async function kl(e,t){let n=de.join(e,"head.html");if(!le(n)){t.push({rule:"head.html exists",status:"warn",message:"Missing head.html"});return}let o=await _e(n,"utf-8"),r=o.split(`
911
- `);for(let c=0;c<r.length;c++){let l=r[c];/<script\b/i.test(l)&&!/type\s*=\s*["']module["']/i.test(l)&&!/<\/script>/.test(l)&&t.push({rule:"No render-blocking scripts in head.html",status:"fail",message:'Script without type="module" blocks rendering',file:"head.html",line:c+1})}let a=(o.match(/<link[^>]+rel=["']stylesheet["'][^>]*>/gi)||[]).filter(c=>!c.includes("styles/styles.css")&&!c.includes("styles.css"));a.length>0&&t.push({rule:"No extra stylesheets in head.html",status:"warn",message:`${a.length} extra stylesheet(s) \u2014 each competes with LCP budget`,file:"head.html"}),/<link[^>]+rel=["'](preload|preconnect)["']/i.test(o)&&t.push({rule:"No preload/preconnect in head.html",status:"warn",message:"preload/preconnect can hurt EDS LCP \u2014 resources compete with the 100KB budget",file:"head.html"}),/<script\b[^>]*>[\s\S]*?[^\s<][\s\S]*?<\/script>/i.test(o)&&t.push({rule:"No inline scripts in head.html",status:"warn",message:"Inline scripts block rendering \u2014 move to delayed.js",file:"head.html"});let d=/(?:src|href)=["'](https?:\/\/(?!(?:localhost|127\.0\.0\.1))[^"']+)["']/gi;for(let c of o.matchAll(d)){let l=c[1];l.includes("fonts.googleapis.com")||t.push({rule:"No third-party resources in head.html",status:"warn",message:`Third-party resource: ${l} \u2014 move to delayed.js`,file:"head.html"})}/<link[^>]+as=["']font["']/i.test(o)&&t.push({rule:"No font preloads in head.html",status:"warn",message:"Font preloads consume LCP bandwidth budget \u2014 let loadFonts() handle them",file:"head.html"}),t.some(c=>c.file==="head.html")||t.push({rule:"head.html is clean",status:"pass",message:"No render-blocking issues found",file:"head.html"})}async function xl(e,t){let n=de.join(e,"scripts","scripts.js");if(!le(n)){t.push({rule:"scripts/scripts.js exists",status:"warn",message:"Missing scripts.js \u2014 cannot audit loading phases"});return}let o=await _e(n,"utf-8"),r=o.split(`
912
- `),s=/function\s+loadEager|loadEager\s*=/i.test(o),a=/function\s+loadLazy|loadLazy\s*=/i.test(o),d=/function\s+loadDelayed|loadDelayed\s*=/i.test(o);t.push({rule:"loadEager phase exists",status:s?"pass":"fail",message:s?"Found":"Missing loadEager \u2014 LCP optimization depends on it",file:"scripts/scripts.js"}),t.push({rule:"loadLazy phase exists",status:a?"pass":"fail",message:a?"Found":"Missing loadLazy \u2014 below-fold content won't load properly",file:"scripts/scripts.js"}),t.push({rule:"loadDelayed phase exists",status:d?"pass":"warn",message:d?"Found":"Missing loadDelayed \u2014 third-party scripts may block LCP",file:"scripts/scripts.js"});let c=o.match(/setTimeout\s*\([^,]+,\s*(\d+)\s*\)/);if(d&&c){let l=Number.parseInt(c[1],10);l<3e3?t.push({rule:"Delayed phase waits >= 3s",status:"warn",message:`delayed.js loads after ${l}ms \u2014 should be >= 3000ms for LCP safety`,file:"scripts/scripts.js"}):t.push({rule:"Delayed phase waits >= 3s",status:"pass",message:`${l}ms delay before loading delayed.js`,file:"scripts/scripts.js"})}if(s){let l=o.match(/loadEager[\s\S]*?(?=function\s|const\s+load|$)/)?.[0]||"";/loadSections\s*\(/.test(l)&&t.push({rule:"loadEager loads only first section",status:"fail",message:"loadEager calls loadSections() \u2014 should only load first section for fast LCP",file:"scripts/scripts.js"})}for(let l=0;l<r.length;l++){let u=r[l];/import\s.*from\s+['"]https?:\/\//i.test(u)&&t.push({rule:"No third-party imports at top level",status:"warn",message:`Third-party import at line ${l+1} \u2014 move to delayed.js if not critical`,file:"scripts/scripts.js",line:l+1})}if(s){let l=Cl(o,"loadEager");l&&/loadHeader|loadFooter/.test(l)&&t.push({rule:"Header/footer not in loadEager",status:"warn",message:"Header/footer in loadEager delays LCP \u2014 move to loadLazy",file:"scripts/scripts.js"})}}async function Sl(e,t){let n=de.join(e,"styles","styles.css");if(!le(n))return;let r=(await Qr(n)).size/1024;t.push({rule:"styles.css size within LCP budget",status:r>40?"warn":"pass",message:`${r.toFixed(1)} KB${r>40?" \u2014 large CSS competes with 100KB LCP budget":""}`,file:"styles/styles.css"});let s=await _e(n,"utf-8");/@import\s/.test(s)&&t.push({rule:"No @import in styles.css",status:"warn",message:"@import creates a request chain \u2014 inline the CSS or use lazy-styles.css",file:"styles/styles.css"})}async function jl(e,t){let n=de.join(e,"scripts","delayed.js");if(!le(n)){t.push({rule:"scripts/delayed.js exists",status:"info",message:"No delayed.js \u2014 third-party scripts should go here"});return}(await _e(n,"utf-8")).replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").trim()||t.push({rule:"delayed.js has content",status:"info",message:"delayed.js is empty \u2014 add analytics/martech here",file:"scripts/delayed.js"})}async function $l(e,t){let n=de.join(e,"blocks");if(!le(n))return;let o=await yl(n,{withFileTypes:!0});for(let r of o){if(!r.isDirectory())continue;let s=r.name,a=de.join(n,s,`${s}.js`);if(!le(a))continue;let d=await _e(a,"utf-8"),c=d.split(`
913
- `),l=["jquery","lodash","moment","rxjs","d3","three","gsap","anime","chart.js","swiper"];for(let f=0;f<c.length;f++){let $=c[f].toLowerCase();for(let v of l)$.includes("from")&&$.includes(v)&&/import\s/.test($)&&t.push({rule:"No heavy imports in blocks",status:"warn",message:`Imports "${v}" \u2014 heavy library delays section loading`,file:`blocks/${s}/${s}.js`,line:f+1})}/document\.write/i.test(d)&&t.push({rule:"No document.write in blocks",status:"fail",message:"document.write blocks parsing and can break the page",file:`blocks/${s}/${s}.js`});let m=(await Qr(a)).size/1024;m>20&&t.push({rule:"Block JS size reasonable",status:"warn",message:`${m.toFixed(1)} KB \u2014 consider splitting or lazy-loading parts`,file:`blocks/${s}/${s}.js`})}for(let r of o){if(!r.isDirectory())continue;let s=r.name,a=de.join(n,s,`${s}.css`);if(!le(a))continue;let d=await _e(a,"utf-8"),c=/^([a-z][a-z0-9-]*)\s*\{/gm;for(let l of d.matchAll(c)){let u=l[1];["body","html","main"].includes(u)||t.push({rule:"Block CSS is scoped",status:"warn",message:`Bare element selector "${u}" \u2014 may leak styles and cause CLS. Use .${s} prefix`,file:`blocks/${s}/${s}.css`})}}}async function El(e,t){let n=de.join(e,"scripts","aem.js");if(!le(n)){t.push({rule:"scripts/aem.js exists",status:"warn",message:"Missing aem.js (or lib-franklin.js) \u2014 the EDS framework library"});return}t.push({rule:"aem.js present",status:"pass",message:"Found \u2014 remember: never modify this file",file:"scripts/aem.js"})}function Cl(e,t){let o=new RegExp(`(?:async\\s+)?function\\s+${t}\\s*\\([^)]*\\)\\s*\\{`).exec(e);if(!o)return null;let r=1,s=o.index+o[0].length,a=s;for(;s<e.length&&r>0;)e[s]==="{"?r++:e[s]==="}"&&r--,s++;return e.slice(a,s-1)}function Pl(e){let t=new Map;for(let o of e){let r=o.file||"general",s=t.get(r)??[];s.push(o),t.set(r,s)}for(let[o,r]of t){i.info(` ${G.bullet} ${po.underline(o)}`);for(let s of r){let a=s.line?po.dim(`:${s.line}`):"";i.info(` ${ft(s.status)} ${s.rule}${a}`),s.status!=="pass"&&i.info(po.dim(` ${s.message}`))}i.info("")}let n={pass:e.filter(o=>o.status==="pass").length,warn:e.filter(o=>o.status==="warn").length,fail:e.filter(o=>o.status==="fail").length,info:e.filter(o=>o.status==="info").length};i.info(O([oe(n)])),n.fail>0&&(process.exitCode=1)}var fo=b(()=>{"use strict";p();F();H();I()});var ho={};U(ho,{auditSecurity:()=>_l});import{existsSync as Jt}from"fs";import{readFile as Al,readdir as Tl}from"fs/promises";import Se from"path";import go from"chalk";async function*es(e){let t=await Tl(e,{withFileTypes:!0});for(let n of t){let o=Se.join(e,n.name);if(n.isDirectory()){if(Ll.has(n.name))continue;yield*es(o)}else n.isFile()&&(yield o)}}function Ol(e,t,n){let o=[],r=e.split(`
914
- `);for(let s=0;s<r.length;s++){let a=r[s],d=!1;for(let c of Fl)c.ext.includes(n)&&(c.id==="innerhtml-static"&&d||c.re.test(a)&&(c.extra&&!c.extra(a)||(c.id==="innerhtml-dynamic"&&(d=!0),o.push({severity:c.severity,rule:c.id,message:c.message,file:t,line:s+1,snippet:a.trim().slice(0,100)}))))}return o}async function Ml(e){if(!Jt(Se.join(e,"package.json")))return{status:"skipped",note:"no package.json"};if(!(Jt(Se.join(e,"package-lock.json"))||Jt(Se.join(e,"npm-shrinkwrap.json")))&&!Jt(Se.join(e,"node_modules")))return{status:"skipped",note:"no package-lock.json / node_modules \u2014 run npm install"};try{let{execa:n}=await import("execa"),{stdout:o}=await n("npm",["audit","--json"],{cwd:e,reject:!1}),s=JSON.parse(o)?.metadata?.vulnerabilities??{},a={critical:s.critical??0,high:s.high??0,moderate:s.moderate??0,low:s.low??0};return{status:a.critical+a.high+a.moderate+a.low>0?"vulnerable":"ok",counts:a}}catch(n){return{status:"skipped",note:`npm audit failed: ${n.message}`}}}async function _l(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=[];for await(let c of es(t)){let l=Se.extname(c).slice(1).toLowerCase();if(!Rl.has(l))continue;let u=Se.relative(t,c);if(u.endsWith("aem.js")||u.endsWith("lib-franklin.js"))continue;let m=await Al(c,"utf-8");n.push(...Ol(m,u,l))}let o=await Ml(t),r=c=>n.filter(l=>l.severity===c),s={critical:r("critical").length,high:r("high").length,moderate:r("moderate").length,low:r("low").length},a=s.critical>0||s.high>0||(o.counts?.critical??0)>0||(o.counts?.high??0)>0;if(e.json){console.log(JSON.stringify({projectRoot:t,dependencies:o,findings:n,summary:{code:s}},null,2)),a&&(process.exitCode=1);return}if(i.logoOnce(P("Security Audit")),i.info(j("Dependencies","npm audit")),o.status==="skipped")i.info(R("info","npm audit",o.note??"skipped"));else if(o.status==="ok")i.info(R("pass","npm audit","no known vulnerabilities"));else{let c=o.counts??{critical:0,high:0,moderate:0,low:0};i.info(R(c.critical+c.high>0?"fail":"warn","npm audit",`${c.critical} critical, ${c.high} high, ${c.moderate} moderate, ${c.low} low \u2014 run \`npm audit fix\``))}if(i.info(j("Exploit scan","XSS \xB7 secrets \xB7 injection \xB7 tabnabbing")),n.length===0)i.info(R("pass","code","no risky patterns found"));else{let c=[...n].sort((l,u)=>Zr.indexOf(l.severity)-Zr.indexOf(u.severity));for(let l of c){let u=Dl[l.severity],m=go.dim(`${l.file}:${l.line}`);i.info(` ${ft(u.status)} ${go.bold(u.label)} ${l.message} ${m}`),i.info(go.dim(` ${l.snippet}`))}}let d=oe({fail:s.critical+s.high+(o.counts?.critical??0)+(o.counts?.high??0),warn:s.moderate+(o.counts?.moderate??0),info:s.low+(o.counts?.low??0)});i.info(""),i.info(O([d||`${G.pass} no vulnerabilities or risky patterns found`])),a&&(process.exitCode=1)}var Fl,Zr,Dl,Ll,Rl,bo=b(()=>{"use strict";p();F();H();I();Fl=[{id:"eval",severity:"critical",re:/\beval\s*\(/,message:"eval() executes arbitrary code \u2014 prime XSS / RCE vector",ext:["js","mjs","html"]},{id:"aws-key",severity:"critical",re:/\bAKIA[0-9A-Z]{16}\b/,message:"Hardcoded AWS access key id",ext:["js","mjs","html","json"]},{id:"private-key",severity:"critical",re:/-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/,message:"Embedded private key material",ext:["js","mjs","html","json","pem","txt"]},{id:"new-function",severity:"high",re:/\bnew\s+Function\s*\(/,message:"new Function() runs strings as code",ext:["js","mjs","html"]},{id:"document-write",severity:"high",re:/document\.write(?:ln)?\s*\(/,message:"document.write() enables XSS and blocks parsing",ext:["js","mjs","html"]},{id:"innerhtml-dynamic",severity:"high",re:/\.(?:inner|outer)HTML\s*=\s*[^;\n]*(?:\$\{|\+|concat)/,message:"Dynamic innerHTML assignment \u2014 sanitize or use textContent / DOM APIs",ext:["js","mjs"]},{id:"insert-adjacent-html",severity:"high",re:/insertAdjacentHTML\s*\(/,message:"insertAdjacentHTML with untrusted data is an XSS vector",ext:["js","mjs"]},{id:"js-url",severity:"high",re:/(?:href|src)\s*=\s*["']?\s*javascript:/i,message:"javascript: URL \u2014 XSS vector",ext:["js","mjs","html"]},{id:"secret",severity:"high",re:/(?:api[_-]?key|secret|access[_-]?token|auth[_-]?token|client[_-]?secret|passwd|password)\s*[:=]\s*["'][^"']{8,}["']/i,message:"Possible hardcoded secret / credential",ext:["js","mjs","html","json"],extra:e=>!/(example|placeholder|your[-_]|changeme|xxxx|<[^>]+>|\$\{)/i.test(e)},{id:"bearer-token",severity:"high",re:/Bearer\s+[A-Za-z0-9\-._~+/]{20,}/,message:"Hardcoded bearer token",ext:["js","mjs","html","json"]},{id:"innerhtml-static",severity:"moderate",re:/\.(?:inner|outer)HTML\s*=/,message:"innerHTML assignment \u2014 confirm the content is trusted / sanitized",ext:["js","mjs"]},{id:"insecure-url",severity:"moderate",re:/(?:href|src)\s*=\s*["']http:\/\/(?!localhost|127\.0\.0\.1)/i,message:"Insecure http:// resource \u2014 mixed content, use https://",ext:["html","js","mjs"]},{id:"target-blank",severity:"moderate",re:/target\s*=\s*["']_blank["']/,message:'target="_blank" without rel="noopener" \u2014 reverse tabnabbing',ext:["html","js","mjs"],extra:e=>!/rel\s*=\s*["'][^"']*noopener/i.test(e)},{id:"postmessage-wildcard",severity:"moderate",re:/postMessage\s*\([^,]+,\s*["']\*["']\s*\)/,message:"postMessage to '*' origin \u2014 restrict the target origin",ext:["js","mjs"]},{id:"inline-handler",severity:"low",re:/\son[a-z]+\s*=\s*["']/i,message:"Inline event handler \u2014 move to addEventListener (CSP-unfriendly)",ext:["html"]},{id:"console-log",severity:"low",re:/console\.(?:log|debug)\s*\(/,message:"console.log / debug left in code \u2014 potential info leak",ext:["js","mjs"]}],Zr=["critical","high","moderate","low"],Dl={critical:{status:"fail",label:"CRIT"},high:{status:"fail",label:"HIGH"},moderate:{status:"warn",label:"MOD "},low:{status:"info",label:"LOW "}},Ll=new Set(["node_modules",".git","dist","build",".vscode","coverage"]),Rl=new Set(["js","mjs","html","json","pem","txt"])});async function ts(e,t,n){let o=t.ref||"main",r=n.startsWith("/")?n:`/${n}`,s=`${Nl}/${e}/${t.org}/${t.site}/${o}${r}`;i.debug(`POST ${s}`);let a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"}}),d=await a.json().catch(()=>({})),c=d;return a.ok?{ok:!0,status:a.status,path:r,previewUrl:c.preview?.url,liveUrl:c.live?.url}:{ok:!1,status:a.status,path:r,message:d.message||`HTTP ${a.status}`}}async function wo(e,t){return ts("preview",e,t)}async function yo(e,t){return ts("live",e,t)}async function ns(e,t){return Promise.all(t.map(n=>wo(e,n)))}async function os(e,t){return Promise.all(t.map(n=>yo(e,n)))}var Nl,vo=b(()=>{"use strict";p();F();Nl="https://admin.hlx.page"});var ko={};U(ko,{preview:()=>Il,resolveAdminConfig:()=>Wt});import is from"chalk";import Ul from"ora";async function Il(e,t){let n=E(),o=await ae(n),r=Wt(o,t);if(!r)return;let s=Ul(`Previewing ${e.length} path(s)...`).start(),a=e.length===1?[await wo(r,e[0])]:await ns(r,e);s.stop();let d=!1;for(let c of a)c.ok?i.success(`${c.path} \u2192 ${is.cyan(c.previewUrl||"preview updated")}`):(i.error(`${c.path} \u2014 ${c.message}`),d=!0);d&&(process.exitCode=1)}function Wt(e,t){let n=t.org||e.admin?.org,o=t.site||e.admin?.site,r=t.ref||e.admin?.ref||"main";if(!n||!o){i.error("Missing --org and --site. Set them via flags or in .edsrc.json:"),i.info(is.dim(' { "admin": { "org": "my-org", "site": "my-site" } }')),process.exitCode=1;return}return{org:n,site:o,ref:r}}var zt=b(()=>{"use strict";p();vo();ve();F();H()});var xo={};U(xo,{publish:()=>Gl});import Bl from"chalk";import Hl from"ora";async function Gl(e,t){let n=E(),o=await ae(n),r=Wt(o,t);if(!r)return;let s=Hl(`Publishing ${e.length} path(s)...`).start(),a=e.length===1?[await yo(r,e[0])]:await os(r,e);s.stop();let d=!1;for(let c of a)c.ok?i.success(`${c.path} \u2192 ${Bl.cyan(c.liveUrl||"published")}`):(i.error(`${c.path} \u2014 ${c.message}`),d=!0);d&&(process.exitCode=1)}var So=b(()=>{"use strict";p();vo();ve();F();H();zt()});var qt={};U(qt,{adminWizard:()=>Jl});async function Jl(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Admin API \u2014 preview / publish"));let{select:n,input:o,confirm:r}=await import("@inquirer/prompts"),a=(await ae(t)).admin??{},d=e??await n({message:"What do you want to do?",choices:[{name:"Preview pages (staging)",value:"preview"},{name:"Publish pages (go live)",value:"publish"}]}),c=(await o({message:"GitHub org / owner",default:a.org})).trim(),l=(await o({message:"Repository / site",default:a.site})).trim(),u=(await o({message:"Git ref",default:a.ref||"main"})).trim(),f=(await o({message:"Paths (space- or comma-separated)",default:"/"})).split(/[\s,]+/).filter(Boolean);if(!c||!l||f.length===0){i.error("org, site and at least one path are required."),process.exitCode=1;return}i.info(j("Summary"));let $=M(["operation","org","site","ref","paths"]);if(i.info(k("operation",d,$)),i.info(k("org",c,$)),i.info(k("site",l,$)),i.info(k("ref",u,$)),i.info(k("paths",f.join(", "),$)),i.info(""),d==="publish"&&!await r({message:`Publish ${f.length} path(s) to LIVE?`,default:!1})){i.info("Cancelled.");return}let v={org:c,site:l,ref:u};if(d==="preview"){let{preview:x}=await Promise.resolve().then(()=>(zt(),ko));await x(f,v)}else{let{publish:x}=await Promise.resolve().then(()=>(So(),xo));await x(f,v)}}var Kt=b(()=>{"use strict";p();ve();F();H();I()});var rs={};U(rs,{mainMenu:()=>Kl});import{existsSync as Wl}from"fs";import{readdir as zl}from"fs/promises";import ql from"path";async function jo(e){let t=ql.join(e,"blocks");return Wl(t)?(await zl(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name):[]}async function Kl(){let{select:e,input:t}=await import("@inquirer/prompts");switch(await i.logoOnceAnimated("What do you want to do?"),await e({message:"Choose an action",choices:[{name:"Set up this project (authoring model, CI, naming)",value:"init"},{name:"Generate a page template (initial content)",value:"template"},{name:"Create a disposable sandbox repo on GitHub",value:"sandbox"},{name:"Generate a block from a design (Figma/Stitch/Canva/Sketch/Framer)",value:"from-design"},{name:"Migrate a classic AEM component to EDS",value:"migrate"},{name:"Scaffold Universal Editor components",value:"scaffold"},{name:"Create an empty block",value:"create"},{name:"Add a third-party integration (GTM, chat, consent\u2026)",value:"integrate"},{name:"Add fields to a block model (partials)",value:"model"},{name:"Instrument a block for analytics (dataLayer)",value:"track"},{name:"Add JSON-LD structured data to a block",value:"schema"},{name:"Check Universal Editor readiness / open the editor",value:"ue"},{name:"Preview a block in the browser",value:"preview-block"},{name:"Preview / publish pages (Admin API)",value:"admin"},{name:"Audit the project",value:"audit"},{name:"Configure Figma MCP",value:"figma-setup"}]})){case"init":{let{initProject:o}=await Promise.resolve().then(()=>(At(),Pt));await o({});return}case"template":{let o=await t({message:"Template name",validate:s=>!!s.trim()||"Required"}),{templateNew:r}=await Promise.resolve().then(()=>(xn(),kn));await r(o.trim(),{});return}case"sandbox":{let o=await t({message:"Sandbox repo name",validate:s=>/^[a-z0-9][a-z0-9._-]*$/i.test(s.trim())||"Use a valid repo name"}),{sandboxNew:r}=await Promise.resolve().then(()=>(be(),he));await r(o.trim(),{});return}case"from-design":{let{blockFromDesign:o}=await Promise.resolve().then(()=>(oo(),no));await o(void 0,{});return}case"migrate":{let{migrateComponent:o}=await Promise.resolve().then(()=>(Pn(),Cn));await o(void 0,{});return}case"scaffold":{let{scaffoldInteractive:o}=await Promise.resolve().then(()=>(Z(),ee));await o();return}case"create":{let o=await t({message:"Block name",validate:s=>pe.test(s.trim())||"Use kebab-case, e.g. hero-banner"}),{createBlock:r}=await Promise.resolve().then(()=>(Gn(),Hn));await r(o.trim(),{});return}case"integrate":{let{integrate:o}=await Promise.resolve().then(()=>(so(),ro));await o(void 0);return}case"preview-block":{let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found).");return}let r=await jo(o);if(r.length===0){i.warn("No blocks found in blocks/.");return}let s=await e({message:"Which block?",choices:r.map(d=>({name:d,value:d}))}),{previewBlock:a}=await Promise.resolve().then(()=>(Bt(),It));await a(s,{});return}case"model":{let{modelAdd:o}=await Promise.resolve().then(()=>(_n(),Mn));await o(void 0,[],{});return}case"track":{let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found).");return}let r=await jo(o);if(r.length===0){i.warn("No blocks found in blocks/.");return}let s=await e({message:"Which block to instrument?",choices:r.map(d=>({name:d,value:d}))}),{trackBlock:a}=await Promise.resolve().then(()=>(Qe(),Ye));await a(s,{});return}case"schema":{let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found).");return}let r=await jo(o);if(r.length===0){i.warn("No blocks found in blocks/.");return}let s=await e({message:"Which block?",choices:r.map(d=>({name:d,value:d}))}),{schemaBlock:a}=await Promise.resolve().then(()=>(Un(),Nn));await a(s,{});return}case"ue":{if(await e({message:"Universal Editor:",choices:[{name:"Check readiness (which blocks are editable)",value:"check"},{name:"Open a page in the editor",value:"open"}]})==="check"){let{ueCheck:r}=await Promise.resolve().then(()=>(nt(),tt));await r()}else{let r=await t({message:"Page path",default:"/"}),{ueOpen:s}=await Promise.resolve().then(()=>(nt(),tt));await s(r.trim()||"/",{})}return}case"admin":{let{adminWizard:o}=await Promise.resolve().then(()=>(Kt(),qt));await o();return}case"audit":{let o=await e({message:"Which audit?",choices:[{name:"Doctor \u2014 overall project health",value:"doctor"},{name:"Loading \u2014 three-phase / LCP budget",value:"loading"},{name:"Security \u2014 vulnerabilities & exploit patterns",value:"security"}]});if(o==="doctor"){let{doctor:r}=await Promise.resolve().then(()=>(mo(),lo));await r({})}else if(o==="loading"){let{auditLoading:r}=await Promise.resolve().then(()=>(fo(),uo));await r({})}else{let{auditSecurity:r}=await Promise.resolve().then(()=>(bo(),ho));await r({})}return}case"figma-setup":{let{figmaSetup:o}=await Promise.resolve().then(()=>(co(),ao));await o();return}}}var ss=b(()=>{"use strict";p();F();H();Pe()});p();import Xl from"chalk";import{Command as Vl}from"commander";var $o={name:"aem-eds-kit",version:"0.4.25",description:"CLI for AEM Edge Delivery Services with Figma MCP integration",type:"module",engines:{node:">=20"},bin:{eds:"dist/bin/eds.js"},files:["dist","CHANGELOG.md"],scripts:{dev:"tsx src/bin/eds.ts",build:"tsup",test:"vitest run","test:watch":"vitest",lint:"biome check src/ tests/","lint:fix":"biome check --write src/ tests/",typecheck:"tsc --noEmit",prepare:"git config core.hooksPath .githooks || true",prepublishOnly:"npm run build"},keywords:["aem","edge-delivery-services","helix","figma","mcp","cli","adobe"],author:"Piotr Godycki <piotrgodycki@yahoo.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/piotrgodycki/aem-eds-kit.git"},homepage:"https://piotrgodycki.github.io/aem-eds-kit/",bugs:{url:"https://github.com/piotrgodycki/aem-eds-kit/issues"},dependencies:{"@inquirer/prompts":"^7.0.0",chalk:"^5.4.0",commander:"^13.0.0",execa:"^9.5.0","fast-xml-parser":"^5.11.2",ora:"^8.1.0",yaml:"^2.6.0",zod:"^3.24.0"},devDependencies:{"@biomejs/biome":"^1.9.0","@types/node":"^22.0.0",tsup:"^8.3.0",tsx:"^4.19.0",typescript:"^5.7.0",vitest:"^2.1.0"},optionalDependencies:{"@modelcontextprotocol/sdk":"^1.29.0"}};F();I();var N=new Vl;N.name("eds").description("CLI for AEM Edge Delivery Services with Figma integration").version($o.version).option("--verbose","Enable verbose output").option("--quiet","Suppress non-error output").option("--json","Output in JSON format").option("--no-color","Disable color output").showHelpAfterError("(add --help for usage)").hook("preAction",e=>{let t=e.opts();t.verbose&&i.setLevel("debug"),t.quiet&&i.setQuiet(!0),t.color===!1&&(Xl.level=0)});N.addHelpText("beforeAll",()=>P());var pt=N.command("sandbox").description("Disposable EDS sandbox repos on GitHub");pt.command("new <name>").description("Create a disposable EDS repo from a boilerplate (GitHub auth, no gh required)").option("--org <org>","Create under a GitHub org (else your account)").option("--boilerplate <repo>","Template repo (default adobe/aem-boilerplate)").option("--ue","Use the crosswalk / Universal Editor boilerplate").option("--private","Create a private repo").option("--yes","Skip the guided prompts (use flags/defaults)").action(async(e,t)=>{let{sandboxNew:n}=await Promise.resolve().then(()=>(be(),he));await n(e,t)});pt.command("login").description("Authorize GitHub (OAuth device flow or a token) - no gh needed").action(async()=>{let{sandboxLogin:e}=await Promise.resolve().then(()=>(be(),he));await e()});pt.command("logout").description("Remove the stored GitHub token").action(async()=>{let{sandboxLogout:e}=await Promise.resolve().then(()=>(be(),he));await e()});pt.command("list").description("List your EDS sandboxes (repos tagged eds-sandbox)").action(async()=>{let{sandboxList:e}=await Promise.resolve().then(()=>(be(),he));await e()});pt.command("rm <name>").description("Delete a sandbox repo (destructive)").option("--org <org>","Owner org (else your account)").option("--yes","Skip the confirmation").action(async(e,t)=>{let{sandboxRm:n}=await Promise.resolve().then(()=>(be(),he));await n(e,t)});var Yl=N.command("template").description("Generate page templates / initial content");Yl.command("new <name>").description("Generate EDS page initial content (sections + blocks + metadata), DA push optional").option("--path <path>","Content path (default: /templates/<name>)").option("--title <title>","Page title").option("--description <text>","Page description").option("--blocks <list>","Comma-separated block ids to seed",e=>e.split(",").map(t=>t.trim())).option("--area <area>","Site area / template label (stored in metadata)").option("--authoring <model>","Force authoring model: da | gdrive | sharepoint | ue").option("--push","Push the page to DA (da.live)").option("--org <org>","DA org (else from .edsrc.json)").option("--site <site>","DA site (else from .edsrc.json)").option("--yes","Skip prompts").action(async(e,t)=>{let{templateNew:n}=await Promise.resolve().then(()=>(xn(),kn));await n(e,t)});N.command("init").description("Set up a freshly cloned EDS boilerplate for your authoring model (interactive)").option("--name <name>","Project name (kebab-case)").option("--authoring <model>","Authoring model: ue | da | gdrive | sharepoint").option("--mountpoint <url>","Content source URL (document models)").option("--org <org>","DA org (authoring=da)").option("--site <site>","DA site (authoring=da)").option("--no-ci","Skip the GitHub Actions CI workflow").option("--no-env","Skip the local-dev .env (aem up config)").option("--no-xwalk","Skip xwalk.json (UE multi-field)").option("--yes","Skip prompts; apply with flags/defaults").action(async e=>{let{initProject:t}=await Promise.resolve().then(()=>(At(),Pt));await t(e)});var Ql=N.command("migrate").description("Migrate from classic AEM to EDS");Ql.command("component [dir]").description("Migrate a classic AEM component's dialog into an EDS block + UE model").option("--name <name>","Block name (otherwise inferred from the component)").option("--clientlib <dir>","Path to the component's clientlib (otherwise auto-detected)").option("--yes","Skip confirmation prompts").action(async(e,t)=>{let{migrateComponent:n}=await Promise.resolve().then(()=>(Pn(),Cn));await n(e,t)});var Zl=N.command("model").description("Compose Universal Editor models");Zl.command("add <block> [partials...]").description("Add reusable field groups (partials) to a block's UE model").option("--yes","Skip prompts").action(async(e,t,n)=>{let{modelAdd:o}=await Promise.resolve().then(()=>(_n(),Mn));await o(e,t,n)});var ed=N.command("schema").description("Structured data (JSON-LD) for blocks");ed.command("block <name>").description("Inject a JSON-LD (schema.org) builder into a block's decorate()").option("--type <type>","schema.org type (Article, FAQPage, Product, ...)").option("--yes","Skip prompts").action(async(e,t)=>{let{schemaBlock:n}=await Promise.resolve().then(()=>(Un(),Nn));await n(e,t)});var td=N.command("track").description("Instrument blocks for analytics");td.command("block <name>").description("Add dataLayer tracking (click + form submit) to a block's decorate()").option("--no-click","Skip click tracking").option("--no-submit","Skip form-submit tracking").action(async(e,t)=>{let{trackBlock:n}=await Promise.resolve().then(()=>(Qe(),Ye));await n(e,t)});var as=N.command("ue").description("Universal Editor - readiness check + editor deep link");as.command("check").description("Check whether blocks are Universal-Editor-ready (offline)").action(async()=>{let{ueCheck:e}=await Promise.resolve().then(()=>(nt(),tt));await e()});as.command("open [path]").description("Open a page in the hosted Universal Editor (preview host from git)").option("--org <slug>","IMS org slug (skips the org picker)").option("--ref <branch>","Branch/ref for the preview host (default: main)").option("--url <host>","Override the delivery host (e.g. main--repo--owner.aem.page)").option("--no-open","Print the link without opening the browser").action(async(e,t)=>{let{ueOpen:n}=await Promise.resolve().then(()=>(nt(),tt));await n(e,t)});var Xt=N.command("block").description("Manage EDS blocks");Xt.command("create <name>").description("Scaffold a new EDS block (with Universal Editor model by default)").option("--no-ue-model","Skip the Universal Editor model (generated by default)").action(async(e,t)=>{let{createBlock:n}=await Promise.resolve().then(()=>(Gn(),Hn));await n(e,t)});Xt.command("from-design [design-url]").description("Generate an EDS block from a design (Figma/Stitch/Canva/Sketch; interactive wizard when run with no URL)").option("--name <name>","Override the inferred block name").option("--agent <type>","Force agent type (claude|cursor|codex|none)").option("--dry-run","Generate prompt only, do not invoke agent").option("--source <type>","Content source: document|ue|cf|mixed (default: document)").option("--widths <list>","Design frame widths for preview breakpoints (e.g. 390,768,1440)").option("--no-ue-model","Skip the Universal Editor model (generated by default)").option("--no-screenshot","Skip the screenshot fetch (fewer tokens; structural verification)").option("--no-serve","Don't auto-start the live preview after generating").option("--yes","Skip confirmation prompts").action(async(e,t)=>{let{blockFromDesign:n}=await Promise.resolve().then(()=>(oo(),no));await n(e,t)});Xt.command("list").description("List all blocks in the project").action(async e=>{let{listBlocks:t}=await Promise.resolve().then(()=>(Wr(),Jr));await t({...e,json:N.opts().json})});Xt.command("preview <name>").description("Serve a live, breakpoint-switchable preview of a block in the browser").option("--port <port>","Port to serve on (default: 8777, falls back if taken)").option("--widths <list>","Comma-separated breakpoint widths (e.g. 375,768,1280)").option("--no-open","Do not open the browser automatically").action(async(e,t)=>{let{previewBlock:n}=await Promise.resolve().then(()=>(Bt(),It));await n(e,t)});var Ne=N.command("scaffold").description("Scaffold standard UE components and blocks").action(async()=>{let{scaffoldInteractive:e}=await Promise.resolve().then(()=>(Z(),ee));await e()});Ne.command("ue").description("Scaffold default-content UE components + a field-reference block (all 17 fields)").action(async()=>{let{scaffoldUe:e}=await Promise.resolve().then(()=>(Z(),ee));await e()});Ne.command("blocks [names...]").description("Scaffold standard blocks (hero, cards, columns, accordion, embed) with UE models").action(async e=>{let{scaffoldBlocks:t}=await Promise.resolve().then(()=>(Z(),ee));await t(e)});Ne.command("ci").description("Scaffold a GitHub Actions workflow (doctor + audits + project lint/build)").action(async()=>{let{scaffoldCi:e}=await Promise.resolve().then(()=>(Z(),ee));await e()});Ne.command("helpers [names...]").description("Scaffold scripts/utils.js with chosen EDS helpers (interactive picker)").action(async e=>{let{scaffoldHelpers:t}=await Promise.resolve().then(()=>(Z(),ee));await t(e)});Ne.command("env").description("Write a local-dev .env for `aem up` (AEM_OPEN / AEM_PORT / AEM_PAGES_URL)").option("--open <path>","AEM_OPEN - path opened on start (default: /)").option("--port <port>","AEM_PORT - proxy port (default: 3007)").option("--pages-url <url>","AEM_PAGES_URL - content origin (default: from git remote)").option("--yes","Skip prompts; use flags/defaults").action(async e=>{let{scaffoldEnv:t}=await Promise.resolve().then(()=>(Z(),ee));await t(e)});Ne.command("xwalk").description("Write xwalk.json enabling Universal Editor multi-field support").action(async()=>{let{scaffoldXwalk:e}=await Promise.resolve().then(()=>(Z(),ee));await e()});N.command("integrate [type]").description("Add a third-party service (GTM, GA4, chat, consent) to scripts/delayed.js").action(async e=>{let{integrate:t}=await Promise.resolve().then(()=>(so(),ro));await t(e)});var nd=N.command("figma").description("Figma MCP integration");nd.command("setup").description("Configure Figma MCP for your AI agent").action(async()=>{let{figmaSetup:e}=await Promise.resolve().then(()=>(co(),ao));await e()});N.command("doctor").description("Audit your EDS project for common issues").action(async()=>{let{doctor:e}=await Promise.resolve().then(()=>(mo(),lo));await e({json:N.opts().json})});var cs=N.command("audit").description("Run project audits");cs.command("loading").description("Check loading order (eager/lazy/delayed phases, LCP budget)").action(async()=>{let{auditLoading:e}=await Promise.resolve().then(()=>(fo(),uo));await e({json:N.opts().json})});cs.command("security").description("Scan for vulnerabilities (npm audit) and exploit patterns (XSS, secrets, tabnabbing)").action(async()=>{let{auditSecurity:e}=await Promise.resolve().then(()=>(bo(),ho));await e({json:N.opts().json})});N.command("preview [paths...]").description("Preview pages via Admin API (interactive wizard when run with no paths)").option("--org <org>","GitHub org/owner").option("--site <site>","Repository name").option("--ref <ref>","Git ref (default: main)").action(async(e,t)=>{if(!e||e.length===0){let{adminWizard:o}=await Promise.resolve().then(()=>(Kt(),qt));await o("preview");return}let{preview:n}=await Promise.resolve().then(()=>(zt(),ko));await n(e,t)});N.command("publish [paths...]").description("Publish pages to live via Admin API (interactive wizard when run with no paths)").option("--org <org>","GitHub org/owner").option("--site <site>","Repository name").option("--ref <ref>","Git ref (default: main)").action(async(e,t)=>{if(!e||e.length===0){let{adminWizard:o}=await Promise.resolve().then(()=>(Kt(),qt));await o("publish");return}let{publish:n}=await Promise.resolve().then(()=>(So(),xo));await n(e,t)});(async()=>{try{if(process.argv.slice(2).length===0)if(process.stdout.isTTY){let{mainMenu:e}=await Promise.resolve().then(()=>(ss(),rs));await e()}else N.outputHelp();else await N.parseAsync()}catch(e){i.error(e instanceof Error?e.message:String(e)),process.exitCode=1}})();
996
+ `),o){case"claude":i.info(` ${ie.cyan("claude mcp add --transport sse figma-sse https://mcp.figma.com/sse")}`),i.info(" or for Figma Desktop app:"),i.info(` ${ie.cyan("claude mcp add --transport http figma-desktop http://127.0.0.1:3845/mcp")}`);break;case"cursor":i.info(` Add to ${ie.cyan("~/.cursor/mcp.json")}:`),i.info(ie.dim(JSON.stringify({mcpServers:{figma:{url:"https://mcp.figma.com/sse"}}},null,2)));break;case"codex":i.info(" See Figma MCP docs: https://help.figma.com/hc/en-us/articles/32132100833559");break}i.info("")}else a?.hasFigmaMcp&&i.success(`Figma MCP is already configured for ${o}!`)}if(i.info(ie.dim(`
997
+ Note: Figma MCP requires a Figma seat (Dev or Full on paid plans for desktop server).`)),await t({message:"Save preferences to ~/.eds/config.json?",default:!0})){let a=Ur();cd(a)||await ld(a,{recursive:!0});let s={};o!=="none"&&(s.agent=o),await dd(oo(),`${JSON.stringify(s,null,2)}
998
+ `,{mode:384}),i.success(`Config saved to ${ie.cyan(oo())}`)}i.info(ie.bold(`
999
+ Setup complete!`)),o!=="none"&&i.info(`Try: ${ie.cyan('eds block from-design "<figma-url>" --dry-run')}`)}var wo=w(()=>{"use strict";m();Qn();Pe();R();I()});var yo={};N(yo,{doctor:()=>ud});import{existsSync as bt}from"fs";import{readFile as wt,readdir as md}from"fs/promises";import Ce from"path";import{parse as $a}from"yaml";async function ud(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=si(t);e.json||(i.logoOnce(P("Doctor")),i.info(j("Doctor",t)));let o=[];if(o.push({name:"fstab.yaml exists",status:n.hasFstab?"pass":"warn",message:n.hasFstab?"Found":"Missing - fine for Universal Editor / DA; required for document-mounted setups"}),n.hasFstab)try{let p=await wt(Ce.join(t,"fstab.yaml"),"utf-8");$a(p),o.push({name:"fstab.yaml valid YAML",status:"pass",message:"Valid"})}catch{o.push({name:"fstab.yaml valid YAML",status:"fail",message:"Invalid YAML syntax"})}if(o.push({name:"head.html exists",status:n.hasHeadHtml?"pass":"warn",message:n.hasHeadHtml?"Found":"Missing - recommended for metadata/scripts"}),o.push({name:"blocks/ directory",status:n.hasBlocks?"pass":"warn",message:n.hasBlocks?"Found":"Missing - no blocks yet"}),n.hasBlocks){let p=Ce.join(t,"blocks"),f=await md(p,{withFileTypes:!0}),g="",y=Ce.join(t,"component-models.json");if(bt(y))try{g=await wt(y,"utf-8")}catch{}for(let h of f){if(!h.isDirectory())continue;let b=h.name,S=Ce.join(p,b,`${b}.js`),x=bt(S);o.push({name:`blocks/${b} has JS`,status:x?"pass":"warn",message:x?"Found":`Missing ${b}.js`}),x&&(await wt(S,"utf-8")).includes("console.log")&&o.push({name:`blocks/${b} no console.log`,status:"warn",message:"Found console.log - remove before production"});let T=bt(Ce.join(p,b,`_${b}.json`)),oe=g.includes(`"${b}"`);o.push({name:`blocks/${b} UE model`,status:T||oe?"pass":"warn",message:T||oe?T?`_${b}.json`:"in component-models.json":"no Universal Editor model - authors can't edit this block in UE"});let H=Ce.join(p,b,".eds-meta.json");if(bt(H))try{let q=JSON.parse(await wt(H,"utf-8")),Lo=new Date(q.lastSyncedAt),Te=Math.floor((Date.now()-Lo.getTime())/(1e3*60*60*24));o.push({name:`blocks/${b} Figma sync`,status:Te>30?"warn":"pass",message:Te>30?`Last synced ${Te} days ago - design may have changed`:`Synced ${Te} days ago`})}catch{o.push({name:`blocks/${b} .eds-meta.json`,status:"warn",message:"Invalid metadata file"})}}}let r=Ce.join(t,"helix-query.yaml");if(bt(r))try{let p=await wt(r,"utf-8");$a(p),o.push({name:"helix-query.yaml valid",status:"pass",message:"Valid YAML"})}catch{o.push({name:"helix-query.yaml valid",status:"fail",message:"Invalid YAML syntax"})}o.push({name:"~/.eds/config.json",status:io()?"pass":"warn",message:io()?"Found":'Missing - run "eds figma setup" to configure'});let a=o.filter(p=>p.status==="fail"),s=o.filter(p=>p.status==="warn");if(e.json){let p={pass:o.filter(f=>f.status==="pass").length,warn:s.length,fail:a.length};console.log(JSON.stringify({projectRoot:t,results:o,summary:p},null,2)),a.length>0&&(process.exitCode=1);return}let d=O(o.map(p=>p.name));for(let p of o)i.info(D(p.status,p.name,p.message,d));let l=o.filter(p=>p.status==="fail"),c=o.filter(p=>p.status==="warn"),u=o.filter(p=>p.status==="pass");i.info(""),i.info(L([de({pass:u.length,warn:c.length,fail:l.length})])),l.length>0&&(process.exitCode=1)}var vo=w(()=>{"use strict";m();Pe();R();z();I()});var xo={};N(xo,{auditLoading:()=>gd});import{existsSync as he}from"fs";import{readFile as We,readdir as fd,stat as Sa}from"fs/promises";import be from"path";import ko from"chalk";async function gd(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}e.json||(i.logoOnce(P("Loading Audit")),i.info(j("Loading Order Audit",t)));let n=[];if(await hd(t,n),await bd(t,n),await wd(t,n),await yd(t,n),await vd(t,n),await kd(t,n),e.json){let o={pass:n.filter(r=>r.status==="pass").length,warn:n.filter(r=>r.status==="warn").length,fail:n.filter(r=>r.status==="fail").length,info:n.filter(r=>r.status==="info").length};console.log(JSON.stringify({projectRoot:t,results:n,summary:o},null,2)),o.fail>0&&(process.exitCode=1);return}$d(n)}async function hd(e,t){let n=be.join(e,"head.html");if(!he(n)){t.push({rule:"head.html exists",status:"warn",message:"Missing head.html"});return}let o=await We(n,"utf-8"),r=o.split(`
1000
+ `);for(let l=0;l<r.length;l++){let c=r[l];/<script\b/i.test(c)&&!/type\s*=\s*["']module["']/i.test(c)&&!/<\/script>/.test(c)&&t.push({rule:"No render-blocking scripts in head.html",status:"fail",message:'Script without type="module" blocks rendering',file:"head.html",line:l+1})}let s=(o.match(/<link[^>]+rel=["']stylesheet["'][^>]*>/gi)||[]).filter(l=>!l.includes("styles/styles.css")&&!l.includes("styles.css"));s.length>0&&t.push({rule:"No extra stylesheets in head.html",status:"warn",message:`${s.length} extra stylesheet(s) \u2014 each competes with LCP budget`,file:"head.html"}),/<link[^>]+rel=["'](preload|preconnect)["']/i.test(o)&&t.push({rule:"No preload/preconnect in head.html",status:"warn",message:"preload/preconnect can hurt EDS LCP \u2014 resources compete with the 100KB budget",file:"head.html"}),/<script\b[^>]*>[\s\S]*?[^\s<][\s\S]*?<\/script>/i.test(o)&&t.push({rule:"No inline scripts in head.html",status:"warn",message:"Inline scripts block rendering \u2014 move to delayed.js",file:"head.html"});let d=/(?:src|href)=["'](https?:\/\/(?!(?:localhost|127\.0\.0\.1))[^"']+)["']/gi;for(let l of o.matchAll(d)){let c=l[1];c.includes("fonts.googleapis.com")||t.push({rule:"No third-party resources in head.html",status:"warn",message:`Third-party resource: ${c} \u2014 move to delayed.js`,file:"head.html"})}/<link[^>]+as=["']font["']/i.test(o)&&t.push({rule:"No font preloads in head.html",status:"warn",message:"Font preloads consume LCP bandwidth budget \u2014 let loadFonts() handle them",file:"head.html"}),t.some(l=>l.file==="head.html")||t.push({rule:"head.html is clean",status:"pass",message:"No render-blocking issues found",file:"head.html"})}async function bd(e,t){let n=be.join(e,"scripts","scripts.js");if(!he(n)){t.push({rule:"scripts/scripts.js exists",status:"warn",message:"Missing scripts.js \u2014 cannot audit loading phases"});return}let o=await We(n,"utf-8"),r=o.split(`
1001
+ `),a=/function\s+loadEager|loadEager\s*=/i.test(o),s=/function\s+loadLazy|loadLazy\s*=/i.test(o),d=/function\s+loadDelayed|loadDelayed\s*=/i.test(o);t.push({rule:"loadEager phase exists",status:a?"pass":"fail",message:a?"Found":"Missing loadEager \u2014 LCP optimization depends on it",file:"scripts/scripts.js"}),t.push({rule:"loadLazy phase exists",status:s?"pass":"fail",message:s?"Found":"Missing loadLazy \u2014 below-fold content won't load properly",file:"scripts/scripts.js"}),t.push({rule:"loadDelayed phase exists",status:d?"pass":"warn",message:d?"Found":"Missing loadDelayed \u2014 third-party scripts may block LCP",file:"scripts/scripts.js"});let l=o.match(/setTimeout\s*\([^,]+,\s*(\d+)\s*\)/);if(d&&l){let c=Number.parseInt(l[1],10);c<3e3?t.push({rule:"Delayed phase waits >= 3s",status:"warn",message:`delayed.js loads after ${c}ms \u2014 should be >= 3000ms for LCP safety`,file:"scripts/scripts.js"}):t.push({rule:"Delayed phase waits >= 3s",status:"pass",message:`${c}ms delay before loading delayed.js`,file:"scripts/scripts.js"})}if(a){let c=o.match(/loadEager[\s\S]*?(?=function\s|const\s+load|$)/)?.[0]||"";/loadSections\s*\(/.test(c)&&t.push({rule:"loadEager loads only first section",status:"fail",message:"loadEager calls loadSections() \u2014 should only load first section for fast LCP",file:"scripts/scripts.js"})}for(let c=0;c<r.length;c++){let u=r[c];/import\s.*from\s+['"]https?:\/\//i.test(u)&&t.push({rule:"No third-party imports at top level",status:"warn",message:`Third-party import at line ${c+1} \u2014 move to delayed.js if not critical`,file:"scripts/scripts.js",line:c+1})}if(a){let c=xd(o,"loadEager");c&&/loadHeader|loadFooter/.test(c)&&t.push({rule:"Header/footer not in loadEager",status:"warn",message:"Header/footer in loadEager delays LCP \u2014 move to loadLazy",file:"scripts/scripts.js"})}}async function wd(e,t){let n=be.join(e,"styles","styles.css");if(!he(n))return;let r=(await Sa(n)).size/1024;t.push({rule:"styles.css size within LCP budget",status:r>40?"warn":"pass",message:`${r.toFixed(1)} KB${r>40?" \u2014 large CSS competes with 100KB LCP budget":""}`,file:"styles/styles.css"});let a=await We(n,"utf-8");/@import\s/.test(a)&&t.push({rule:"No @import in styles.css",status:"warn",message:"@import creates a request chain \u2014 inline the CSS or use lazy-styles.css",file:"styles/styles.css"})}async function yd(e,t){let n=be.join(e,"scripts","delayed.js");if(!he(n)){t.push({rule:"scripts/delayed.js exists",status:"info",message:"No delayed.js \u2014 third-party scripts should go here"});return}(await We(n,"utf-8")).replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").trim()||t.push({rule:"delayed.js has content",status:"info",message:"delayed.js is empty \u2014 add analytics/martech here",file:"scripts/delayed.js"})}async function vd(e,t){let n=be.join(e,"blocks");if(!he(n))return;let o=await fd(n,{withFileTypes:!0});for(let r of o){if(!r.isDirectory())continue;let a=r.name,s=be.join(n,a,`${a}.js`);if(!he(s))continue;let d=await We(s,"utf-8"),l=d.split(`
1002
+ `),c=["jquery","lodash","moment","rxjs","d3","three","gsap","anime","chart.js","swiper"];for(let f=0;f<l.length;f++){let g=l[f].toLowerCase();for(let y of c)g.includes("from")&&g.includes(y)&&/import\s/.test(g)&&t.push({rule:"No heavy imports in blocks",status:"warn",message:`Imports "${y}" \u2014 heavy library delays section loading`,file:`blocks/${a}/${a}.js`,line:f+1})}/document\.write/i.test(d)&&t.push({rule:"No document.write in blocks",status:"fail",message:"document.write blocks parsing and can break the page",file:`blocks/${a}/${a}.js`});let p=(await Sa(s)).size/1024;p>20&&t.push({rule:"Block JS size reasonable",status:"warn",message:`${p.toFixed(1)} KB \u2014 consider splitting or lazy-loading parts`,file:`blocks/${a}/${a}.js`})}for(let r of o){if(!r.isDirectory())continue;let a=r.name,s=be.join(n,a,`${a}.css`);if(!he(s))continue;let d=await We(s,"utf-8"),l=/^([a-z][a-z0-9-]*)\s*\{/gm;for(let c of d.matchAll(l)){let u=c[1];["body","html","main"].includes(u)||t.push({rule:"Block CSS is scoped",status:"warn",message:`Bare element selector "${u}" \u2014 may leak styles and cause CLS. Use .${a} prefix`,file:`blocks/${a}/${a}.css`})}}}async function kd(e,t){let n=be.join(e,"scripts","aem.js");if(!he(n)){t.push({rule:"scripts/aem.js exists",status:"warn",message:"Missing aem.js (or lib-franklin.js) \u2014 the EDS framework library"});return}t.push({rule:"aem.js present",status:"pass",message:"Found \u2014 remember: never modify this file",file:"scripts/aem.js"})}function xd(e,t){let o=new RegExp(`(?:async\\s+)?function\\s+${t}\\s*\\([^)]*\\)\\s*\\{`).exec(e);if(!o)return null;let r=1,a=o.index+o[0].length,s=a;for(;a<e.length&&r>0;)e[a]==="{"?r++:e[a]==="}"&&r--,a++;return e.slice(s,a-1)}function $d(e){let t=new Map;for(let o of e){let r=o.file||"general",a=t.get(r)??[];a.push(o),t.set(r,a)}for(let[o,r]of t){i.info(` ${J.bullet} ${ko.underline(o)}`);for(let a of r){let s=a.line?ko.dim(`:${a.line}`):"";i.info(` ${vt(a.status)} ${a.rule}${s}`),a.status!=="pass"&&i.info(ko.dim(` ${a.message}`))}i.info("")}let n={pass:e.filter(o=>o.status==="pass").length,warn:e.filter(o=>o.status==="warn").length,fail:e.filter(o=>o.status==="fail").length,info:e.filter(o=>o.status==="info").length};i.info(L([de(n)])),n.fail>0&&(process.exitCode=1)}var $o=w(()=>{"use strict";m();R();z();I()});var jo={};N(jo,{auditSecurity:()=>Dd});import{existsSync as Vt}from"fs";import{readFile as Sd,readdir as jd}from"fs/promises";import Ae from"path";import So from"chalk";async function*Ea(e){let t=await jd(e,{withFileTypes:!0});for(let n of t){let o=Ae.join(e,n.name);if(n.isDirectory()){if(Cd.has(n.name))continue;yield*Ea(o)}else n.isFile()&&(yield o)}}function Td(e,t,n){let o=[],r=e.split(`
1003
+ `);for(let a=0;a<r.length;a++){let s=r[a],d=!1;for(let l of Ed)l.ext.includes(n)&&(l.id==="innerhtml-static"&&d||l.re.test(s)&&(l.extra&&!l.extra(s)||(l.id==="innerhtml-dynamic"&&(d=!0),o.push({severity:l.severity,rule:l.id,message:l.message,file:t,line:a+1,snippet:s.trim().slice(0,100)}))))}return o}async function Rd(e){if(!Vt(Ae.join(e,"package.json")))return{status:"skipped",note:"no package.json"};if(!(Vt(Ae.join(e,"package-lock.json"))||Vt(Ae.join(e,"npm-shrinkwrap.json")))&&!Vt(Ae.join(e,"node_modules")))return{status:"skipped",note:"no package-lock.json / node_modules \u2014 run npm install"};try{let{execa:n}=await import("execa"),{stdout:o}=await n("npm",["audit","--json"],{cwd:e,reject:!1}),a=JSON.parse(o)?.metadata?.vulnerabilities??{},s={critical:a.critical??0,high:a.high??0,moderate:a.moderate??0,low:a.low??0};return{status:s.critical+s.high+s.moderate+s.low>0?"vulnerable":"ok",counts:s}}catch(n){return{status:"skipped",note:`npm audit failed: ${n.message}`}}}async function Dd(e={}){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=[];for await(let l of Ea(t)){let c=Ae.extname(l).slice(1).toLowerCase();if(!Ad.has(c))continue;let u=Ae.relative(t,l);if(u.endsWith("aem.js")||u.endsWith("lib-franklin.js"))continue;let p=await Sd(l,"utf-8");n.push(...Td(p,u,c))}let o=await Rd(t),r=l=>n.filter(c=>c.severity===l),a={critical:r("critical").length,high:r("high").length,moderate:r("moderate").length,low:r("low").length},s=a.critical>0||a.high>0||(o.counts?.critical??0)>0||(o.counts?.high??0)>0;if(e.json){console.log(JSON.stringify({projectRoot:t,dependencies:o,findings:n,summary:{code:a}},null,2)),s&&(process.exitCode=1);return}if(i.logoOnce(P("Security Audit")),i.info(j("Dependencies","npm audit")),o.status==="skipped")i.info(D("info","npm audit",o.note??"skipped"));else if(o.status==="ok")i.info(D("pass","npm audit","no known vulnerabilities"));else{let l=o.counts??{critical:0,high:0,moderate:0,low:0};i.info(D(l.critical+l.high>0?"fail":"warn","npm audit",`${l.critical} critical, ${l.high} high, ${l.moderate} moderate, ${l.low} low \u2014 run \`npm audit fix\``))}if(i.info(j("Exploit scan","XSS \xB7 secrets \xB7 injection \xB7 tabnabbing")),n.length===0)i.info(D("pass","code","no risky patterns found"));else{let l=[...n].sort((c,u)=>ja.indexOf(c.severity)-ja.indexOf(u.severity));for(let c of l){let u=Pd[c.severity],p=So.dim(`${c.file}:${c.line}`);i.info(` ${vt(u.status)} ${So.bold(u.label)} ${c.message} ${p}`),i.info(So.dim(` ${c.snippet}`))}}let d=de({fail:a.critical+a.high+(o.counts?.critical??0)+(o.counts?.high??0),warn:a.moderate+(o.counts?.moderate??0),info:a.low+(o.counts?.low??0)});i.info(""),i.info(L([d||`${J.pass} no vulnerabilities or risky patterns found`])),s&&(process.exitCode=1)}var Ed,ja,Pd,Cd,Ad,Eo=w(()=>{"use strict";m();R();z();I();Ed=[{id:"eval",severity:"critical",re:/\beval\s*\(/,message:"eval() executes arbitrary code \u2014 prime XSS / RCE vector",ext:["js","mjs","html"]},{id:"aws-key",severity:"critical",re:/\bAKIA[0-9A-Z]{16}\b/,message:"Hardcoded AWS access key id",ext:["js","mjs","html","json"]},{id:"private-key",severity:"critical",re:/-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/,message:"Embedded private key material",ext:["js","mjs","html","json","pem","txt"]},{id:"new-function",severity:"high",re:/\bnew\s+Function\s*\(/,message:"new Function() runs strings as code",ext:["js","mjs","html"]},{id:"document-write",severity:"high",re:/document\.write(?:ln)?\s*\(/,message:"document.write() enables XSS and blocks parsing",ext:["js","mjs","html"]},{id:"innerhtml-dynamic",severity:"high",re:/\.(?:inner|outer)HTML\s*=\s*[^;\n]*(?:\$\{|\+|concat)/,message:"Dynamic innerHTML assignment \u2014 sanitize or use textContent / DOM APIs",ext:["js","mjs"]},{id:"insert-adjacent-html",severity:"high",re:/insertAdjacentHTML\s*\(/,message:"insertAdjacentHTML with untrusted data is an XSS vector",ext:["js","mjs"]},{id:"js-url",severity:"high",re:/(?:href|src)\s*=\s*["']?\s*javascript:/i,message:"javascript: URL \u2014 XSS vector",ext:["js","mjs","html"]},{id:"secret",severity:"high",re:/(?:api[_-]?key|secret|access[_-]?token|auth[_-]?token|client[_-]?secret|passwd|password)\s*[:=]\s*["'][^"']{8,}["']/i,message:"Possible hardcoded secret / credential",ext:["js","mjs","html","json"],extra:e=>!/(example|placeholder|your[-_]|changeme|xxxx|<[^>]+>|\$\{)/i.test(e)},{id:"bearer-token",severity:"high",re:/Bearer\s+[A-Za-z0-9\-._~+/]{20,}/,message:"Hardcoded bearer token",ext:["js","mjs","html","json"]},{id:"innerhtml-static",severity:"moderate",re:/\.(?:inner|outer)HTML\s*=/,message:"innerHTML assignment \u2014 confirm the content is trusted / sanitized",ext:["js","mjs"]},{id:"insecure-url",severity:"moderate",re:/(?:href|src)\s*=\s*["']http:\/\/(?!localhost|127\.0\.0\.1)/i,message:"Insecure http:// resource \u2014 mixed content, use https://",ext:["html","js","mjs"]},{id:"target-blank",severity:"moderate",re:/target\s*=\s*["']_blank["']/,message:'target="_blank" without rel="noopener" \u2014 reverse tabnabbing',ext:["html","js","mjs"],extra:e=>!/rel\s*=\s*["'][^"']*noopener/i.test(e)},{id:"postmessage-wildcard",severity:"moderate",re:/postMessage\s*\([^,]+,\s*["']\*["']\s*\)/,message:"postMessage to '*' origin \u2014 restrict the target origin",ext:["js","mjs"]},{id:"inline-handler",severity:"low",re:/\son[a-z]+\s*=\s*["']/i,message:"Inline event handler \u2014 move to addEventListener (CSP-unfriendly)",ext:["html"]},{id:"console-log",severity:"low",re:/console\.(?:log|debug)\s*\(/,message:"console.log / debug left in code \u2014 potential info leak",ext:["js","mjs"]}],ja=["critical","high","moderate","low"],Pd={critical:{status:"fail",label:"CRIT"},high:{status:"fail",label:"HIGH"},moderate:{status:"warn",label:"MOD "},low:{status:"info",label:"LOW "}},Cd=new Set(["node_modules",".git","dist","build",".vscode","coverage"]),Ad=new Set(["js","mjs","html","json","pem","txt"])});async function Pa(e,t,n){let o=t.ref||"main",r=n.startsWith("/")?n:`/${n}`,a=`${Fd}/${e}/${t.org}/${t.site}/${o}${r}`;i.debug(`POST ${a}`);let s=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"}}),d=await s.json().catch(()=>({})),l=d;return s.ok?{ok:!0,status:s.status,path:r,previewUrl:l.preview?.url,liveUrl:l.live?.url}:{ok:!1,status:s.status,path:r,message:d.message||`HTTP ${s.status}`}}async function Po(e,t){return Pa("preview",e,t)}async function Co(e,t){return Pa("live",e,t)}async function Ca(e,t){return Promise.all(t.map(n=>Po(e,n)))}async function Aa(e,t){return Promise.all(t.map(n=>Co(e,n)))}var Fd,Ao=w(()=>{"use strict";m();R();Fd="https://admin.hlx.page"});var To={};N(To,{preview:()=>Od,resolveAdminConfig:()=>Yt});import Ta from"chalk";import Ld from"ora";async function Od(e,t){let n=E(),o=await fe(n),r=Yt(o,t);if(!r)return;let a=Ld(`Previewing ${e.length} path(s)...`).start(),s=e.length===1?[await Po(r,e[0])]:await Ca(r,e);a.stop();let d=!1;for(let l of s)l.ok?i.success(`${l.path} \u2192 ${Ta.cyan(l.previewUrl||"preview updated")}`):(i.error(`${l.path} \u2014 ${l.message}`),d=!0);d&&(process.exitCode=1)}function Yt(e,t){let n=t.org||e.admin?.org,o=t.site||e.admin?.site,r=t.ref||e.admin?.ref||"main";if(!n||!o){i.error("Missing --org and --site. Set them via flags or in .edsrc.json:"),i.info(Ta.dim(' { "admin": { "org": "my-org", "site": "my-site" } }')),process.exitCode=1;return}return{org:n,site:o,ref:r}}var Qt=w(()=>{"use strict";m();Ao();Pe();R();z()});var Ro={};N(Ro,{publish:()=>_d});import Md from"chalk";import Nd from"ora";async function _d(e,t){let n=E(),o=await fe(n),r=Yt(o,t);if(!r)return;let a=Nd(`Publishing ${e.length} path(s)...`).start(),s=e.length===1?[await Co(r,e[0])]:await Aa(r,e);a.stop();let d=!1;for(let l of s)l.ok?i.success(`${l.path} \u2192 ${Md.cyan(l.liveUrl||"published")}`):(i.error(`${l.path} \u2014 ${l.message}`),d=!0);d&&(process.exitCode=1)}var Do=w(()=>{"use strict";m();Ao();Pe();R();z();Qt()});var Zt={};N(Zt,{adminWizard:()=>Id});async function Id(e){let t=E();if(!t){i.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}i.logoOnce(P("Admin API \u2014 preview / publish"));let{select:n,input:o,confirm:r}=await Promise.resolve().then(()=>(B(),U)),s=(await fe(t)).admin??{},d=e??await n({message:"What do you want to do?",choices:[{name:"Preview pages (staging)",value:"preview"},{name:"Publish pages (go live)",value:"publish"}]}),l=(await o({message:"GitHub org / owner",default:s.org})).trim(),c=(await o({message:"Repository / site",default:s.site})).trim(),u=(await o({message:"Git ref",default:s.ref||"main"})).trim(),f=(await o({message:"Paths (space- or comma-separated)",default:"/"})).split(/[\s,]+/).filter(Boolean);if(!l||!c||f.length===0){i.error("org, site and at least one path are required."),process.exitCode=1;return}i.info(j("Summary"));let g=O(["operation","org","site","ref","paths"]);if(i.info($("operation",d,g)),i.info($("org",l,g)),i.info($("site",c,g)),i.info($("ref",u,g)),i.info($("paths",f.join(", "),g)),i.info(""),d==="publish"&&!await r({message:`Publish ${f.length} path(s) to LIVE?`,default:!1})){i.info("Cancelled.");return}let y={org:l,site:c,ref:u};if(d==="preview"){let{preview:h}=await Promise.resolve().then(()=>(Qt(),To));await h(f,y)}else{let{publish:h}=await Promise.resolve().then(()=>(Do(),Ro));await h(f,y)}}var en=w(()=>{"use strict";m();Pe();R();z();I()});var Ra={};N(Ra,{mainMenu:()=>Gd});import{existsSync as Ud}from"fs";import{readdir as Bd}from"fs/promises";import Hd from"path";async function Fo(e){let t=Hd.join(e,"blocks");return Ud(t)?(await Bd(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name):[]}async function Gd(){let{select:e,input:t}=await Promise.resolve().then(()=>(B(),U));switch(await i.logoOnceAnimated(""),await e({message:"Choose an action",choices:[{name:"Set up project",value:"init",description:"Authoring model, CI, naming"},{name:"Page template",value:"template",description:"Generate initial content"},{name:"Sandbox repo",value:"sandbox",description:"Disposable GitHub repo"},{name:"Block from design",value:"from-design",description:"Figma / Stitch / Canva / Sketch / Framer"},{name:"Migrate component",value:"migrate",description:"Classic AEM component \u2192 EDS"},{name:"Scaffold UE",value:"scaffold",description:"Universal Editor components"},{name:"Empty block",value:"create",description:"Create a bare block"},{name:"Integration",value:"integrate",description:"GTM, chat, consent\u2026"},{name:"Model fields",value:"model",description:"Add fields to a block model (partials)"},{name:"Analytics",value:"track",description:"Instrument a block (dataLayer)"},{name:"Structured data",value:"schema",description:"Add JSON-LD to a block"},{name:"Universal Editor",value:"ue",description:"Check readiness / open the editor"},{name:"Preview block",value:"preview-block",description:"Live preview in the browser"},{name:"Pages",value:"admin",description:"Preview / publish (Admin API)"},{name:"Audit",value:"audit",description:"Doctor / loading / security"},{name:"Figma MCP",value:"figma-setup",description:"Configure the connection"}]})){case"init":{let{initProject:o}=await Promise.resolve().then(()=>(Mt(),Ot));await o({});return}case"template":{let o=await t({message:"Template name",validate:a=>!!a.trim()||"Required"}),{templateNew:r}=await Promise.resolve().then(()=>(Pn(),En));await r(o.trim(),{});return}case"sandbox":{let o=await t({message:"Sandbox repo name",validate:a=>/^[a-z0-9][a-z0-9._-]*$/i.test(a.trim())||"Use a valid repo name"}),{sandboxNew:r}=await Promise.resolve().then(()=>(Se(),$e));await r(o.trim(),{});return}case"from-design":{let{blockFromDesign:o}=await Promise.resolve().then(()=>(uo(),mo));await o(void 0,{});return}case"migrate":{let{migrateComponent:o}=await Promise.resolve().then(()=>(Fn(),Dn));await o(void 0,{});return}case"scaffold":{let{scaffoldInteractive:o}=await Promise.resolve().then(()=>(re(),ce));await o();return}case"create":{let o=await t({message:"Block name",validate:a=>ye.test(a.trim())||"Use kebab-case, e.g. hero-banner"}),{createBlock:r}=await Promise.resolve().then(()=>(Kn(),qn));await r(o.trim(),{});return}case"integrate":{let{integrate:o}=await Promise.resolve().then(()=>(ho(),go));await o(void 0);return}case"preview-block":{let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found).");return}let r=await Fo(o);if(r.length===0){i.warn("No blocks found in blocks/.");return}let a=await e({message:"Which block?",choices:r.map(d=>({name:d,value:d}))}),{previewBlock:s}=await Promise.resolve().then(()=>(gt(),ft));await s(a,{});return}case"model":{let{modelAdd:o}=await Promise.resolve().then(()=>(Hn(),Bn));await o(void 0,[],{});return}case"track":{let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found).");return}let r=await Fo(o);if(r.length===0){i.warn("No blocks found in blocks/.");return}let a=await e({message:"Which block to instrument?",choices:r.map(d=>({name:d,value:d}))}),{trackBlock:s}=await Promise.resolve().then(()=>(at(),rt));await s(a,{});return}case"schema":{let o=E();if(!o){i.error("Not inside an EDS project (no EDS project markers found).");return}let r=await Fo(o);if(r.length===0){i.warn("No blocks found in blocks/.");return}let a=await e({message:"Which block?",choices:r.map(d=>({name:d,value:d}))}),{schemaBlock:s}=await Promise.resolve().then(()=>(zn(),Gn));await s(a,{});return}case"ue":{if(await e({message:"Universal Editor:",choices:[{name:"Check readiness (which blocks are editable)",value:"check"},{name:"Open a page in the editor",value:"open"}]})==="check"){let{ueCheck:r}=await Promise.resolve().then(()=>(dt(),lt));await r()}else{let r=await t({message:"Page path",default:"/"}),{ueOpen:a}=await Promise.resolve().then(()=>(dt(),lt));await a(r.trim()||"/",{})}return}case"admin":{let{adminWizard:o}=await Promise.resolve().then(()=>(en(),Zt));await o();return}case"audit":{let o=await e({message:"Which audit?",choices:[{name:"Doctor \u2014 overall project health",value:"doctor"},{name:"Loading \u2014 three-phase / LCP budget",value:"loading"},{name:"Security \u2014 vulnerabilities & exploit patterns",value:"security"}]});if(o==="doctor"){let{doctor:r}=await Promise.resolve().then(()=>(vo(),yo));await r({})}else if(o==="loading"){let{auditLoading:r}=await Promise.resolve().then(()=>($o(),xo));await r({})}else{let{auditSecurity:r}=await Promise.resolve().then(()=>(Eo(),jo));await r({})}return}case"figma-setup":{let{figmaSetup:o}=await Promise.resolve().then(()=>(wo(),bo));await o();return}}}var Da=w(()=>{"use strict";m();R();z();Me()});m();import zd from"chalk";import{Command as Jd}from"commander";var Oo={name:"aem-eds-kit",version:"0.4.26",description:"CLI for AEM Edge Delivery Services with Figma MCP integration",type:"module",engines:{node:">=20"},bin:{eds:"dist/bin/eds.js"},files:["dist","CHANGELOG.md"],scripts:{dev:"tsx src/bin/eds.ts",build:"tsup",test:"vitest run","test:watch":"vitest",lint:"biome check src/ tests/","lint:fix":"biome check --write src/ tests/",typecheck:"tsc --noEmit",prepare:"git config core.hooksPath .githooks || true",prepublishOnly:"npm run build"},keywords:["aem","edge-delivery-services","helix","figma","mcp","cli","adobe"],author:"Piotr Godycki <piotrgodycki@yahoo.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/piotrgodycki/aem-eds-kit.git"},homepage:"https://piotrgodycki.github.io/aem-eds-kit/",bugs:{url:"https://github.com/piotrgodycki/aem-eds-kit/issues"},dependencies:{"@inquirer/prompts":"^7.0.0",chalk:"^5.4.0",commander:"^13.0.0",execa:"^9.5.0","fast-xml-parser":"^5.11.2",ora:"^8.1.0",yaml:"^2.6.0",zod:"^3.24.0"},devDependencies:{"@biomejs/biome":"^1.9.0","@types/node":"^22.0.0",tsup:"^8.3.0",tsx:"^4.19.0",typescript:"^5.7.0",vitest:"^2.1.0"},optionalDependencies:{"@modelcontextprotocol/sdk":"^1.29.0"}};R();I();var M=new Jd;M.name("eds").description("CLI for AEM Edge Delivery Services with Figma integration").version(Oo.version).option("--verbose","Enable verbose output").option("--quiet","Suppress non-error output").option("--json","Output in JSON format").option("--no-color","Disable color output").showHelpAfterError("(add --help for usage)").hook("preAction",e=>{let t=e.opts();t.verbose&&i.setLevel("debug"),t.quiet&&i.setQuiet(!0),t.color===!1&&(zd.level=0)});M.addHelpText("beforeAll",()=>P());var yt=M.command("sandbox").description("Disposable EDS sandbox repos on GitHub");yt.command("new <name>").description("Create a disposable EDS repo from a boilerplate (GitHub auth, no gh required)").option("--org <org>","Create under a GitHub org (else your account)").option("--boilerplate <repo>","Template repo (default adobe/aem-boilerplate)").option("--ue","Use the crosswalk / Universal Editor boilerplate").option("--private","Create a private repo").option("--yes","Skip the guided prompts (use flags/defaults)").action(async(e,t)=>{let{sandboxNew:n}=await Promise.resolve().then(()=>(Se(),$e));await n(e,t)});yt.command("login").description("Authorize GitHub (OAuth device flow or a token) - no gh needed").action(async()=>{let{sandboxLogin:e}=await Promise.resolve().then(()=>(Se(),$e));await e()});yt.command("logout").description("Remove the stored GitHub token").action(async()=>{let{sandboxLogout:e}=await Promise.resolve().then(()=>(Se(),$e));await e()});yt.command("list").description("List your EDS sandboxes (repos tagged eds-sandbox)").action(async()=>{let{sandboxList:e}=await Promise.resolve().then(()=>(Se(),$e));await e()});yt.command("rm <name>").description("Delete a sandbox repo (destructive)").option("--org <org>","Owner org (else your account)").option("--yes","Skip the confirmation").action(async(e,t)=>{let{sandboxRm:n}=await Promise.resolve().then(()=>(Se(),$e));await n(e,t)});var Wd=M.command("template").description("Generate page templates / initial content");Wd.command("new <name>").description("Generate EDS page initial content (sections + blocks + metadata), DA push optional").option("--path <path>","Content path (default: /templates/<name>)").option("--title <title>","Page title").option("--description <text>","Page description").option("--blocks <list>","Comma-separated block ids to seed",e=>e.split(",").map(t=>t.trim())).option("--area <area>","Site area / template label (stored in metadata)").option("--authoring <model>","Force authoring model: da | gdrive | sharepoint | ue").option("--push","Push the page to DA (da.live)").option("--org <org>","DA org (else from .edsrc.json)").option("--site <site>","DA site (else from .edsrc.json)").option("--yes","Skip prompts").action(async(e,t)=>{let{templateNew:n}=await Promise.resolve().then(()=>(Pn(),En));await n(e,t)});M.command("init").description("Set up a freshly cloned EDS boilerplate for your authoring model (interactive)").option("--name <name>","Project name (kebab-case)").option("--authoring <model>","Authoring model: ue | da | gdrive | sharepoint").option("--mountpoint <url>","Content source URL (document models)").option("--org <org>","DA org (authoring=da)").option("--site <site>","DA site (authoring=da)").option("--no-ci","Skip the GitHub Actions CI workflow").option("--no-env","Skip the local-dev .env (aem up config)").option("--no-xwalk","Skip xwalk.json (UE multi-field)").option("--yes","Skip prompts; apply with flags/defaults").action(async e=>{let{initProject:t}=await Promise.resolve().then(()=>(Mt(),Ot));await t(e)});var qd=M.command("migrate").description("Migrate from classic AEM to EDS");qd.command("component [dir]").description("Migrate a classic AEM component's dialog into an EDS block + UE model").option("--name <name>","Block name (otherwise inferred from the component)").option("--clientlib <dir>","Path to the component's clientlib (otherwise auto-detected)").option("--yes","Skip confirmation prompts").action(async(e,t)=>{let{migrateComponent:n}=await Promise.resolve().then(()=>(Fn(),Dn));await n(e,t)});var Kd=M.command("model").description("Compose Universal Editor models");Kd.command("add <block> [partials...]").description("Add reusable field groups (partials) to a block's UE model").option("--yes","Skip prompts").action(async(e,t,n)=>{let{modelAdd:o}=await Promise.resolve().then(()=>(Hn(),Bn));await o(e,t,n)});var Xd=M.command("schema").description("Structured data (JSON-LD) for blocks");Xd.command("block <name>").description("Inject a JSON-LD (schema.org) builder into a block's decorate()").option("--type <type>","schema.org type (Article, FAQPage, Product, ...)").option("--yes","Skip prompts").action(async(e,t)=>{let{schemaBlock:n}=await Promise.resolve().then(()=>(zn(),Gn));await n(e,t)});var Vd=M.command("track").description("Instrument blocks for analytics");Vd.command("block <name>").description("Add dataLayer tracking (click + form submit) to a block's decorate()").option("--no-click","Skip click tracking").option("--no-submit","Skip form-submit tracking").action(async(e,t)=>{let{trackBlock:n}=await Promise.resolve().then(()=>(at(),rt));await n(e,t)});var Fa=M.command("ue").description("Universal Editor - readiness check + editor deep link");Fa.command("check").description("Check whether blocks are Universal-Editor-ready (offline)").action(async()=>{let{ueCheck:e}=await Promise.resolve().then(()=>(dt(),lt));await e()});Fa.command("open [path]").description("Open a page in the hosted Universal Editor (preview host from git)").option("--org <slug>","IMS org slug (skips the org picker)").option("--ref <branch>","Branch/ref for the preview host (default: main)").option("--url <host>","Override the delivery host (e.g. main--repo--owner.aem.page)").option("--no-open","Print the link without opening the browser").action(async(e,t)=>{let{ueOpen:n}=await Promise.resolve().then(()=>(dt(),lt));await n(e,t)});var tn=M.command("block").description("Manage EDS blocks");tn.command("create <name>").description("Scaffold a new EDS block (with Universal Editor model by default)").option("--no-ue-model","Skip the Universal Editor model (generated by default)").action(async(e,t)=>{let{createBlock:n}=await Promise.resolve().then(()=>(Kn(),qn));await n(e,t)});tn.command("from-design [design]").description("Generate an EDS block from a design: a Figma/Stitch/Canva URL, or a local SVG/PNG export (quota-free, no MCP). Interactive wizard when run with no argument.").option("--name <name>","Override the inferred block name").option("--agent <type>","Force agent type (claude|cursor|codex|none)").option("--dry-run","Generate prompt only, do not invoke agent").option("--source <type>","Content source: document|ue|cf|mixed (default: document)").option("--widths <list>","Design frame widths for preview breakpoints (e.g. 390,768,1440)").option("--no-ue-model","Skip the Universal Editor model (generated by default)").option("--screenshot","Add a screenshot MCP call for pixel verification (opt-in; costs a call)").option("--mcp","Force the Figma MCP adapter even when a REST token is set").option("--refresh","Ignore the cached design snapshot and re-fetch").option("--serve","Auto-start the live preview after generating (non-interactive runs only)").option("--yes","Skip confirmation prompts").action(async(e,t)=>{let{blockFromDesign:n}=await Promise.resolve().then(()=>(uo(),mo));await n(e,t)});tn.command("list").description("List all blocks in the project").action(async e=>{let{listBlocks:t}=await Promise.resolve().then(()=>(ba(),ha));await t({...e,json:M.opts().json})});tn.command("preview [name]").description("Serve a live, breakpoint-switchable preview of a block \u2014 or a gallery of all blocks when no name is given").option("--port <port>","Port to serve on (default: 8777, falls back if taken)").option("--widths <list>","Comma-separated breakpoint widths (e.g. 375,768,1280)").option("--no-open","Do not open the browser automatically").action(async(e,t)=>{let n=await Promise.resolve().then(()=>(gt(),ft));e?await n.previewBlock(e,t):await n.galleryPreview(t)});var qe=M.command("scaffold").description("Scaffold standard UE components and blocks").action(async()=>{let{scaffoldInteractive:e}=await Promise.resolve().then(()=>(re(),ce));await e()});qe.command("ue").description("Scaffold default-content UE components + a field-reference block (all 17 fields)").action(async()=>{let{scaffoldUe:e}=await Promise.resolve().then(()=>(re(),ce));await e()});qe.command("blocks [names...]").description("Scaffold standard blocks (hero, cards, columns, accordion, embed) with UE models").action(async e=>{let{scaffoldBlocks:t}=await Promise.resolve().then(()=>(re(),ce));await t(e)});qe.command("ci").description("Scaffold a GitHub Actions workflow (doctor + audits + project lint/build)").action(async()=>{let{scaffoldCi:e}=await Promise.resolve().then(()=>(re(),ce));await e()});qe.command("helpers [names...]").description("Scaffold scripts/utils.js with chosen EDS helpers (interactive picker)").action(async e=>{let{scaffoldHelpers:t}=await Promise.resolve().then(()=>(re(),ce));await t(e)});qe.command("env").description("Write a local-dev .env for `aem up` (AEM_OPEN / AEM_PORT / AEM_PAGES_URL)").option("--open <path>","AEM_OPEN - path opened on start (default: /)").option("--port <port>","AEM_PORT - proxy port (default: 3007)").option("--pages-url <url>","AEM_PAGES_URL - content origin (default: from git remote)").option("--yes","Skip prompts; use flags/defaults").action(async e=>{let{scaffoldEnv:t}=await Promise.resolve().then(()=>(re(),ce));await t(e)});qe.command("xwalk").description("Write xwalk.json enabling Universal Editor multi-field support").action(async()=>{let{scaffoldXwalk:e}=await Promise.resolve().then(()=>(re(),ce));await e()});M.command("integrate [type]").description("Add a third-party service (GTM, GA4, chat, consent) to scripts/delayed.js").action(async e=>{let{integrate:t}=await Promise.resolve().then(()=>(ho(),go));await t(e)});var Yd=M.command("figma").description("Figma MCP integration");Yd.command("setup").description("Configure Figma MCP for your AI agent").action(async()=>{let{figmaSetup:e}=await Promise.resolve().then(()=>(wo(),bo));await e()});M.command("doctor").description("Audit your EDS project for common issues").action(async()=>{let{doctor:e}=await Promise.resolve().then(()=>(vo(),yo));await e({json:M.opts().json})});var La=M.command("audit").description("Run project audits");La.command("loading").description("Check loading order (eager/lazy/delayed phases, LCP budget)").action(async()=>{let{auditLoading:e}=await Promise.resolve().then(()=>($o(),xo));await e({json:M.opts().json})});La.command("security").description("Scan for vulnerabilities (npm audit) and exploit patterns (XSS, secrets, tabnabbing)").action(async()=>{let{auditSecurity:e}=await Promise.resolve().then(()=>(Eo(),jo));await e({json:M.opts().json})});M.command("preview [paths...]").description("Preview pages via Admin API (interactive wizard when run with no paths)").option("--org <org>","GitHub org/owner").option("--site <site>","Repository name").option("--ref <ref>","Git ref (default: main)").action(async(e,t)=>{if(!e||e.length===0){let{adminWizard:o}=await Promise.resolve().then(()=>(en(),Zt));await o("preview");return}let{preview:n}=await Promise.resolve().then(()=>(Qt(),To));await n(e,t)});M.command("publish [paths...]").description("Publish pages to live via Admin API (interactive wizard when run with no paths)").option("--org <org>","GitHub org/owner").option("--site <site>","Repository name").option("--ref <ref>","Git ref (default: main)").action(async(e,t)=>{if(!e||e.length===0){let{adminWizard:o}=await Promise.resolve().then(()=>(en(),Zt));await o("publish");return}let{publish:n}=await Promise.resolve().then(()=>(Do(),Ro));await n(e,t)});(async()=>{try{if(process.argv.slice(2).length===0)if(process.stdout.isTTY){let{mainMenu:e}=await Promise.resolve().then(()=>(Da(),Ra));await e()}else M.outputHelp();else await M.parseAsync()}catch(e){i.error(e instanceof Error?e.message:String(e)),process.exitCode=1}})();