aem-eds-kit 0.4.60 → 0.4.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/dist/bin/eds.js +39 -27
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
### Added
|
|
10
|
+
- **dataLayer events on the site** (EDS-099): GitHub, npm, Quick start,
|
|
11
|
+
copied commands, search, mega menu, FAQ, sections, scroll depth and
|
|
12
|
+
outbound links, ready for GTM / GA4 (`docs/site-analytics.md`).
|
|
13
|
+
- **Mega menu and search on the site** (EDS-097): Product, Docs and Guides
|
|
14
|
+
panels on desktop, and a search overlay (⌘K / Ctrl+K or `/`) over every
|
|
15
|
+
page and section, built by `scripts/site-search-index.mjs`.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **White areas around generated blocks** (EDS-101): the prompt (0.7.3) puts
|
|
19
|
+
full-width backgrounds on the section, past the boilerplate's 1200px
|
|
20
|
+
wrapper and its 40px margin; the preview frame posts its height
|
|
21
|
+
(`eds-preview-size`) so tools can size it to the block.
|
|
22
|
+
- **GitHub and npm icons in the desktop nav** (EDS-095): the site's nav
|
|
23
|
+
buttons had text only on desktop, while the mobile menu showed the GitHub
|
|
24
|
+
mark and npm logo; both now show them.
|
|
25
|
+
- **`eds` run by Electron as Node** (EDS-093), as the aem-eds-studio desktop
|
|
26
|
+
app does, failed every command with "unknown command '…/eds.js'": commander
|
|
27
|
+
read the script path as the command. argv is now always parsed Node-style.
|
|
28
|
+
|
|
29
|
+
## [0.4.60] - 2026-11-06
|
|
30
|
+
|
|
9
31
|
### Changed
|
|
10
32
|
- **Illustrations on the site** (EDS-077): design sources → `eds` → block,
|
|
11
33
|
the command workflow (start → build → check → ship), one per audit card,
|
|
@@ -533,6 +555,7 @@ Initial CLI scaffold: `block create`, `block from-figma`, `block list`,
|
|
|
533
555
|
`figma setup`, `doctor`, `preview`, `publish`. Not published.
|
|
534
556
|
|
|
535
557
|
[Unreleased]: https://github.com/piotrgodycki/aem-eds-kit/commits/main
|
|
558
|
+
[0.4.60]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.60
|
|
536
559
|
[0.4.48]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.48
|
|
537
560
|
[0.4.26]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.26
|
|
538
561
|
[0.4.25]: https://www.npmjs.com/package/aem-eds-kit/v/0.4.25
|
package/README.md
CHANGED
|
@@ -471,7 +471,7 @@ eds draft discard hero # drop it; blocks/ u
|
|
|
471
471
|
|
|
472
472
|
`accept --commit` (or `--branch <name>`, created if missing) commits only `blocks/<name>/`, with the review rounds in the message (`v1: first version`, `v2: "bigger headline, orange buttons"`). `preview` and `accept` take a version (`eds draft preview hero 2`, `eds draft accept hero 1 --branch feature/hero`; default: the latest). `refine` starts from the latest version, or `--from <n>`, and reuses the agent and model that made the draft unless you pass `--agent` / `--model`.
|
|
473
473
|
|
|
474
|
-
**For tools: `--json`.** `block from-design` and the `draft` commands take the global `--json` flag and print **one JSON event per line on stdout** (the usual output stays on stderr). It never prompts, so pass the design, the name and `--draft`. Every event has `v` (the schema version, currently `1`) and `type`, and the stream ends with one `result`. [aem-eds-studio](https://github.com/piotrgodycki/aem-eds-studio) reads it.
|
|
474
|
+
**For tools: `--json`.** `block from-design` and the `draft` commands take the global `--json` flag and print **one JSON event per line on stdout** (the usual output stays on stderr). It never prompts, so pass the design, the name and `--draft`. Every event has `v` (the schema version, currently `1`) and `type`, and the stream ends with one `result`. [aem-eds-studio](https://github.com/piotrgodycki/aem-eds-studio) reads it. A tool can run `dist/bin/eds.js` with Node or with Electron as Node (`ELECTRON_RUN_AS_NODE=1`), as the studio's desktop app does. The preview's block frame (`/__eds_preview_frame`) posts `{ type: "eds-preview-size", height }` to its parent, so an embedding tool can size it to the block.
|
|
475
475
|
|
|
476
476
|
```bash
|
|
477
477
|
eds --json block from-design "<design link>" --name hero --draft
|
package/dist/bin/eds.js
CHANGED
|
@@ -7,10 +7,10 @@ ${Wl()}
|
|
|
7
7
|
${Ul(Il(),e)}
|
|
8
8
|
`}function j(e,t){let n=_.red("\u258A"),o=t?` ${W.dim(t)}`:"";return`
|
|
9
9
|
${n} ${W.bold(e)}${o}
|
|
10
|
-
`}function R(e,t,n,o=0){let i=o?Et(t,o):t,r=n?` ${W.dim(n)}`:"";return` ${Y[e]} ${i}${r}`}function P(e,t,n=0){let o=n?Et(e,n):e,i=t?` ${W.dim(t)}`:"";return` ${_.accent("\u2714")} ${o}${i}`}function I(e){return e.reduce((t,n)=>Math.max(t,$r(n)),0)}function
|
|
10
|
+
`}function R(e,t,n,o=0){let i=o?Et(t,o):t,r=n?` ${W.dim(n)}`:"";return` ${Y[e]} ${i}${r}`}function P(e,t,n=0){let o=n?Et(e,n):e,i=t?` ${W.dim(t)}`:"";return` ${_.accent("\u2714")} ${o}${i}`}function I(e){return e.reduce((t,n)=>Math.max(t,$r(n)),0)}function z(e,t=_.red){let n=I(e),o=t(`\u256D${"\u2500".repeat(n+2)}\u256E`),i=t(`\u2570${"\u2500".repeat(n+2)}\u256F`),r=e.map(a=>`${t("\u2502")} ${Et(a,n)} ${t("\u2502")}`).join(`
|
|
11
11
|
`);return`${o}
|
|
12
12
|
${r}
|
|
13
|
-
${i}`}function je(e){let t=[];return e.pass&&t.push(`${Y.pass} ${e.pass} passed`),e.warn&&t.push(`${Y.warn} ${e.warn} ${
|
|
13
|
+
${i}`}function je(e){let t=[];return e.pass&&t.push(`${Y.pass} ${e.pass} passed`),e.warn&&t.push(`${Y.warn} ${e.warn} ${zl(e.warn,"warning")}`),e.fail&&t.push(`${Y.fail} ${e.fail} failed`),e.info&&t.push(`${Y.info} ${e.info} info`),t.join(W.dim(" "))}function zl(e,t){return e===1?t:`${t}s`}var _,Y,Ol,_l,Sr,xr,Gl,H=v(()=>{"use strict";f();_={red:W.hex("#FA0F00"),ember:W.hex("#FF4B1F"),orange:W.hex("#FF7B00"),blue:W.hex("#2680EB"),accent:W.hex("#ff5a36"),dotOrange:W.hex("#F24E1E"),dotPurple:W.hex("#A259FF"),dotBlue:W.hex("#1ABCFE"),dotGreen:W.hex("#0ACF83"),dotPink:W.hex("#FF7262"),ok:W.hex("#2D9D78"),warn:W.hex("#E68619"),err:W.hex("#D7373F"),info:W.hex("#2680EB")},Y={pass:_.ok("\u2713"),warn:_.warn("\u26A0"),fail:_.err("\u2717"),info:_.info("\u2139"),bullet:W.dim("\u2022"),arrow:W.dim("\u21B3"),figma:_.dotPurple("\u25C6")};Ol=/\[[0-9;]*m/g;_l=5;Sr={prefix:"",style:{highlight:e=>W.hex("#ff5a36").bold(e)}};xr=["\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"],Gl=["#ff3b1e","#ff5a36","#ff7d52"]});import hn from"chalk";function Jl(){let e=process.env.EDS_LOG_LEVEL?.toLowerCase();return e&&e in go?e:"info"}function Pe(e){return Pr?e==="error":go[e]>=go[jr]}function Ct(e,t){if(!B.enabled)return;let n=yr(t).trim();n&&B.emit({type:"log",level:e,message:n})}var go,jr,Pr,wn,s,N=v(()=>{"use strict";f();Se();H();go={debug:0,info:1,warn:2,error:3,silent:4};jr=Jl(),Pr=!1,wn=!1;s={setLevel(e){jr=e},setQuiet(e){Pr=e},debug(...e){Pe("debug")&&Ct("debug",e),Pe("debug")&&console.error(hn.gray("[debug]"),...e)},info(...e){Ct("info",e),Pe("info")&&console.error(...e)},logoOnce(e){wn||(wn=!0,Pe("info")&&console.error(e))},async logoOnceAnimated(e){wn||(wn=!0,Pe("info")&&console.error(A(e)))},success(...e){Ct("success",e),Pe("info")&&console.error(hn.green("\u2713"),...e)},warn(...e){Ct("warn",e),Pe("warn")&&console.error(hn.yellow("\u26A0"),...e)},error(...e){Ct("error",e),Pe("error")&&console.error(hn.red("\u2717"),...e)}}});function ho(e,t,n="main"){return`https://${n}--${t}--${e}.aem.page/`}function wo(){return"https://github.com/apps/aem-code-sync/installations/new"}function Er(e,t){return["repo","create",e,"--template",t.template,t.private?"--private":"--public",...t.clone?["--clone"]:[]]}var tt,Z,bn=v(()=>{"use strict";f();tt="eds-sandbox",Z={document:"adobe/aem-boilerplate",ue:"adobe-rnd/aem-boilerplate-xwalk"}});import{existsSync as yo}from"fs";import{readdir as Tr,rm as bo}from"fs/promises";import Cr from"path";function Ar(e,t=!1){let n=(e??(t?Z.ue:Z.document)).trim(),o=ql[n.toLowerCase()]??n,i=a=>/xwalk/i.test(a);if(/^[\w.-]+\/[\w.-]+$/.test(o)&&!yo(o))return{url:`https://github.com/${o}.git`,label:o,ue:i(o)};let r=o.match(/github\.com[/:]([\w.-]+\/[\w.-]+?)(?:\.git)?\/?$/)?.[1];return{url:o,label:r??o,ue:i(o)}}async function Rr(e){if(!yo(e))return!0;try{return(await Tr(e)).length===0}catch{return!1}}async function Dr(e,t,n={}){let{execa:o}=await import("execa"),i=(d,m,p="pipe")=>o("git",d,{cwd:m,stdio:p}),r=yo(t),a=n.ref?["--branch",n.ref]:[];try{n.keepHistory?await i(["clone",...a,"--origin","upstream",e.url,t],void 0,n.stdio):await i(["clone","--depth","1",...a,e.url,t],void 0,n.stdio)}catch(d){if(!r)await bo(t,{recursive:!0,force:!0});else for(let u of await Tr(t))await bo(Cr.join(t,u),{recursive:!0,force:!0});let m=d;if(m.code==="ENOENT")throw new Error("git isn't installed (or not on PATH).");let p=(m.stderr??"").trim().split(`
|
|
14
14
|
`).pop()||m.shortMessage||String(d);throw/could not read Username|Repository not found|not found/i.test(p)?new Error(`Couldn't clone ${e.label}: the repo doesn't exist, or it's private (check the name; for a private repo use an SSH URL or set up git credentials).`):new Error(`Couldn't clone ${e.label}: ${p}`)}let c=(await i(["rev-parse","HEAD"],t)).stdout.trim(),l=!1;if(!n.keepHistory){await bo(Cr.join(t,".git"),{recursive:!0,force:!0}),await i(["init","--quiet"],t),await i(["symbolic-ref","HEAD","refs/heads/main"],t),await i(["add","-A"],t);try{await i(["commit","--quiet","-m",`Initial commit from ${e.label}@${c.slice(0,7)}`],t)}catch{l=!0}}return n.remote&&await i(["remote","add","origin",n.remote],t),{commit:c,uncommitted:l}}var yn,ql,Fr=v(()=>{"use strict";f();bn();yn="hlxsites/aem-boilerplate-commerce",ql={commerce:yn,document:Z.document,doc:Z.document,da:Z.document,ue:Z.ue,xwalk:Z.ue,crosswalk:Z.ue}});var q={};U(q,{checkbox:()=>id,confirm:()=>od,input:()=>nd,isEscape:()=>Zl,isExit:()=>ed,select:()=>td});import{emitKeypressEvents as Kl}from"readline";import{checkbox as Vl,confirm as Xl,input as Yl,select as Ql}from"@inquirer/prompts";function vn(e){let t={...Sr,...e.theme??{}};return{...e,theme:t}}function kn(e,t){let n=process.stdin;if(!n.isTTY)return e(t??{});let o=new AbortController;t?.signal?.addEventListener("abort",()=>o.abort(),{once:!0}),Kl(n);let i=(a,c)=>{c?.name==="escape"&&o.abort()};n.on("keypress",i);let r=e({...t,signal:o.signal});return Promise.resolve(r).catch(()=>{}).finally(()=>n.off("keypress",i)),r}function Zl(e){return e instanceof Error&&e.name==="AbortPromptError"}function ed(e){return e instanceof Error&&e.name==="ExitPromptError"}var td,nd,od,id,K=v(()=>{"use strict";f();H();td=(e,t)=>kn(n=>Ql(vn(e),n),t),nd=(e,t)=>kn(n=>Yl(vn(e),n),t),od=(e,t)=>kn(n=>Xl(vn(e),n),t),id=(e,t)=>kn(n=>Vl(vn(e),n),t)});import{z as L}from"zod";var Og,vo,Lr,Mg,He,nt=v(()=>{"use strict";f();Og=L.object({fileKey:L.string().min(1),nodeId:L.string().optional(),fileName:L.string().optional()}),vo=L.object({agent:L.enum(["claude","cursor","codex","ollama","omlx","local"]).optional(),local:L.object({baseUrl:L.string().url().optional(),model:L.string().optional(),contextTokens:L.number().int().positive().optional(),apiKey:L.string().optional()}).optional(),model:L.string().optional(),figma:L.object({mcpEndpoint:L.string().url().optional(),token:L.string().optional(),restPerMinute:L.number().int().positive().optional()}).optional(),admin:L.object({org:L.string().optional(),site:L.string().optional(),ref:L.string().default("main")}).optional()}),Lr=L.object({root:L.string(),hasFstab:L.boolean(),hasBlocks:L.boolean(),hasHeadHtml:L.boolean()}),Mg=L.object({figmaFileKey:L.string(),figmaNodeId:L.string().optional(),lastSyncedAt:L.string().datetime(),promptVersion:L.string(),agentUsed:L.string().optional(),breakpoints:L.array(L.object({width:L.number(),label:L.string().optional(),source:L.enum(["figma","scrape","default"]).optional()})).optional()}),He=/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/});import{existsSync as Tt}from"fs";import Ee from"path";function E(e=process.cwd()){let t=Ee.resolve(e),{root:n}=Ee.parse(t);for(;t!==n;){if(Nr.some(o=>Tt(Ee.join(t,o))))return t;t=Ee.dirname(t)}if(Nr.some(o=>Tt(Ee.join(n,o))))return n}function Or(e){return Lr.parse({root:e,hasFstab:Tt(Ee.join(e,"fstab.yaml")),hasBlocks:Tt(Ee.join(e,"blocks")),hasHeadHtml:Tt(Ee.join(e,"head.html"))})}var Nr,V=v(()=>{"use strict";f();nt();Nr=["fstab.yaml","head.html","helix-query.yaml","component-definition.json","paths.json","scripts/scripts.js","scripts/aem.js"]});import{existsSync as rd}from"fs";import{mkdir as sd,writeFile as ad}from"fs/promises";import Mr from"path";async function xn(e){let t=Mr.join(e,".github","workflows","eds.yml");return rd(t)?{path:_r,created:!1}:(await sd(Mr.dirname(t),{recursive:!0}),await ad(t,cd),{path:_r,created:!0})}var _r,cd,ko=v(()=>{"use strict";f();_r=".github/workflows/eds.yml",cd=`name: EDS checks
|
|
15
15
|
|
|
16
16
|
# Generated by aem-eds-kit (\`eds scaffold ci\`). Runs the project's own
|
|
@@ -62,8 +62,8 @@ AEM_PAGES_URL=${o}
|
|
|
62
62
|
`:"";return await Ur(t,`${n}${o}.env
|
|
63
63
|
`),!0}async function $n(e,t={}){let n=Br.join(e,".env"),o=!Ir(n);o&&await Ur(n,dd(t));let i=await md(e);return{path:".env",created:o,gitignoreUpdated:i}}var xo=v(()=>{"use strict";f()});import{existsSync as Hr}from"fs";import{readFile as pd,writeFile as Gr}from"fs/promises";import Sn from"path";function jn(e){return e!=="ue"}function Wr(e,t){return`https://content.da.live/${e}/${t}/`}function ud(e){return`mountpoints:
|
|
64
64
|
/: ${e}
|
|
65
|
-
`}async function
|
|
66
|
-
`}async function
|
|
65
|
+
`}async function zr(e,t){return await Gr(Sn.join(e,"fstab.yaml"),ud(t)),"fstab.yaml"}function fd(e){return`${JSON.stringify({mappings:[`/content/${e}/:/`],includes:[`/content/${e}/`]},null,2)}
|
|
66
|
+
`}async function Jr(e,t){return await Gr(Sn.join(e,"paths.json"),fd(t)),"paths.json"}function gd(e){if(/content\.da\.live|\/\/da\.live\//i.test(e))return"da";if(/drive\.google\.com|docs\.google\.com/i.test(e))return"gdrive";if(/sharepoint\.com|onedrive\.live\.com|1drv\.ms/i.test(e))return"sharepoint";if(/adobeaemcloud\.(com|net)|\/bin\/franklin\.delivery/i.test(e))return"ue"}async function qr(e){let t=Sn.join(e,"fstab.yaml");if(Hr(t)){let n=(await pd(t,"utf-8")).match(/https?:\/\/[^\s"']+/)?.[0],o=n&&gd(n);if(o)return o}if(Hr(Sn.join(e,"paths.json")))return"ue"}var Ce,Kr=v(()=>{"use strict";f();Ce={ue:"Universal Editor (crosswalk)",da:"Document Authoring (da.live)",gdrive:"Document Authoring (Google Drive)",sharepoint:"Document Authoring (SharePoint)"}});import{existsSync as hd}from"fs";import{writeFile as wd}from"fs/promises";import bd from"path";function vd(){return`${JSON.stringify(yd,null,2)}
|
|
67
67
|
`}async function Pn(e){let t=bd.join(e,"xwalk.json");return hd(t)?{path:"xwalk.json",created:!1}:(await wd(t,vd()),{path:"xwalk.json",created:!0})}var yd,$o=v(()=>{"use strict";f();yd={public:{xwalk:{"multi-field":{enabled:!0}}}}});function ot(e){let t=e.trim().match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?\/?$/i);return t?{owner:t[1],repo:t[2]}:null}function it(e,t,n="main"){return`${n}--${t}--${e}.aem.page`}function Vr({host:e,path:t="/",org:n}){let o=e.replace(/^https?:\/\//,"").replace(/\/+$/,""),i=t.startsWith("/")?t:`/${t}`;return`https://experience.adobe.com/#/${n?`@${n}/`:""}aem/editor/canvas/${o}${i}`}var En=v(()=>{"use strict";f()});function At(e){return`${JSON.stringify(e,null,2)}
|
|
68
68
|
`}function jo(e){return Ge.find(t=>t.id===e)}var So,Xr,Yr,Ge,Po=v(()=>{"use strict";f();So=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:e,model:n}}}}}),Xr=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block",template:{name:e,filter:n}}}}}),Yr=(e,t,n)=>({title:e,id:t,plugins:{xwalk:{page:{resourceType:"core/franklin/components/block/v1/block/item",template:{name:e,model:n}}}}}),Ge=[{id:"hero",title:"Hero",js:`// Block: hero
|
|
69
69
|
export default function decorate(block) {
|
|
@@ -341,11 +341,11 @@ export default function decorate(block) {
|
|
|
341
341
|
padding: var(--spacing-l, 32px) 0;
|
|
342
342
|
}
|
|
343
343
|
`});var we={};U(we,{scaffoldBlocks:()=>ms,scaffoldCi:()=>ps,scaffoldEnv:()=>fs,scaffoldHelpers:()=>us,scaffoldInteractive:()=>Ed,scaffoldUe:()=>An,scaffoldXwalk:()=>gs});import{existsSync as ls}from"fs";import{mkdir as ds,readFile as Pd,writeFile as We}from"fs/promises";import me from"path";async function Cn(e){if(!ls(e))return null;try{return JSON.parse(await Pd(e,"utf-8"))}catch{return null}}async function Tn(e,t){await We(e,`${JSON.stringify(t,null,2)}
|
|
344
|
-
`)}async function An(){let e=E();if(!e){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold - Universal Editor"));let t=[],n=me.join(e,"blocks","field-reference");await ds(n,{recursive:!0}),await We(me.join(n,"field-reference.js"),ss),await We(me.join(n,"field-reference.css"),as),await We(me.join(n,"_field-reference.json"),Co()),t.push("blocks/field-reference/ (all 17 fields + multifield)");let o=me.join(e,"component-definition.json"),i=me.join(e,"component-models.json"),r=me.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"}}}}}],c=cs(await Cn(o),is,a);await Tn(o,c),t.push("component-definition.json (default content + field-reference)");let l=await Cn(i)??[],d=JSON.parse(Co()).models[0],m=To(l,[...rs,d]);await Tn(i,m),t.push("component-models.json (title / image / button / field-reference)");let p=Dt(await Cn(r),["field-reference"]);await Tn(r,p),t.push("component-filters.json (section filter)"),s.info(j("Created / merged"));let u=t.map(h=>h.split(" ")[0]),g=I(u);for(let h of t){let[$,...w]=h.split(" ");s.info(P($,w.join(" ").replace(/^\((.*)\)$/,"$1"),g))}s.info(""),s.info(
|
|
345
|
-
`),!0}catch{return!1}}async function Ad(e,t){let n=[];for(let o of["README.md","index.html","head.html"]){let i=Dn.join(e,o);if(Ro(i))try{let r=await Do(i,"utf-8"),a=r.replace(/aem-boilerplate/gi,t);a!==r&&(await hs(i,a),n.push(o))}catch{}}return n}async function Rd(e){let{confirm:t}=await Promise.resolve().then(()=>(K(),q)),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)."}),s.info(j("Next steps (outside the repo)"));for(let o=0;o<n.length;o++){let i=n[o];s.info(` ${_.accent(String(o+1))} ${Rn.bold(i.title)}`),i.url&&s.info(` ${Rn.cyan(i.url)}`),s.info(` ${Rn.dim(i.note)}`),await t({message:" Done / skip?",default:!0})}}async function Dd(e={}){let t=E();if(!t){s.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 s.logoOnceAnimated("Project setup");let{input:n,select:o,confirm:i}=await Promise.resolve().then(()=>(K(),q)),r=!e.yes,a=Dn.basename(t),c=Dn.join(t,"package.json");if(Ro(c))try{let w=JSON.parse(await Do(c,"utf-8")).name??"";w&&!/aem-boilerplate/i.test(w)&&(a=w)}catch{}let l=e.name&&rt(e.name)||rt(r?await n({message:"1/4 Project name",default:rt(a),validate:w=>!!rt(w)||"Use letters, numbers and dashes"}):a),d=e.authoring?void 0:await qr(t);if(!e.authoring&&!r&&!d){s.error("Couldn't detect the authoring model (no fstab.yaml mountpoint or paths.json). Pass --authoring ue|da|gdrive|sharepoint."),process.exitCode=1;return}d&&s.info(Rn.dim(` Detected: ${Ce[d]}`));let m=e.authoring??(r?await o({message:"2/4 Authoring model",default:d,choices:[{name:Ce.ue,value:"ue"},{name:Ce.da,value:"da"},{name:Ce.gdrive,value:"gdrive"},{name:Ce.sharepoint,value:"sharepoint"}]}):d),p=e.mountpoint;if(jn(m)&&!p)if(m==="da"&&(e.org||r)){let w=e.org??await n({message:" DA org",validate:b=>!!b.trim()||"Required"}),y=e.site??(r?await n({message:" DA site",default:l}):l);p=Wr(w.trim(),rt(y))}else m!=="da"&&r&&(p=(await n({message:` ${m==="gdrive"?"Google Drive folder URL":"SharePoint folder URL"}`,validate:y=>/^https?:\/\//.test(y.trim())||"Paste the folder URL"})).trim());let u=e.ci??(r?await i({message:"4/4 Add GitHub Actions CI (audits gatekeeper)?",default:!0}):!0);s.info(j("Summary"));let g=I(["name","authoring","mountpoint","ci"]);if(s.info(P("name",l,g)),s.info(P("authoring",Ce[m],g)),p?s.info(P("mountpoint",p,g)):jn(m)&&s.info(P("mountpoint","(skipped - set it in fstab.yaml later)",g)),s.info(P("ci",u?"yes":"no",g)),s.info(""),r&&!await i({message:"Apply this setup?",default:!0})){s.info("Cancelled.");return}let h=[];await Td(t,l)&&h.push("package.json (name)");for(let w of await Ad(t,l))h.push(`${w} (renamed)`);if(jn(m)&&p&&h.push(await
|
|
344
|
+
`)}async function An(){let e=E();if(!e){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold - Universal Editor"));let t=[],n=me.join(e,"blocks","field-reference");await ds(n,{recursive:!0}),await We(me.join(n,"field-reference.js"),ss),await We(me.join(n,"field-reference.css"),as),await We(me.join(n,"_field-reference.json"),Co()),t.push("blocks/field-reference/ (all 17 fields + multifield)");let o=me.join(e,"component-definition.json"),i=me.join(e,"component-models.json"),r=me.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"}}}}}],c=cs(await Cn(o),is,a);await Tn(o,c),t.push("component-definition.json (default content + field-reference)");let l=await Cn(i)??[],d=JSON.parse(Co()).models[0],m=To(l,[...rs,d]);await Tn(i,m),t.push("component-models.json (title / image / button / field-reference)");let p=Dt(await Cn(r),["field-reference"]);await Tn(r,p),t.push("component-filters.json (section filter)"),s.info(j("Created / merged"));let u=t.map(h=>h.split(" ")[0]),g=I(u);for(let h of t){let[$,...w]=h.split(" ");s.info(P($,w.join(" ").replace(/^\((.*)\)$/,"$1"),g))}s.info(""),s.info(z(["Universal Editor scaffold ready"]))}async function ms(e){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold \u2014 standard blocks"));let n;if(e?.length){n=e.map(d=>jo(d.trim())).filter(d=>!!d);let l=e.filter(d=>!jo(d.trim()));l.length&&s.warn(`Unknown block(s): ${l.join(", ")}. Available: ${Ge.map(d=>d.id).join(", ")}`)}else n=Ge;let o=[],i=[];for(let l of n){let d=me.join(t,"blocks",l.id);if(ls(d)){i.push(l.id);continue}await ds(d,{recursive:!0}),await We(me.join(d,`${l.id}.js`),l.js),await We(me.join(d,`${l.id}.css`),l.css),await We(me.join(d,`_${l.id}.json`),l.model),o.push(l.id)}let r=me.join(t,"component-filters.json"),a=Dt(await Cn(r),n.map(l=>l.id));await Tn(r,a),s.info(j("Blocks"));let c=I([...o,...i,"component-filters"]);for(let l of o)s.info(P(l,"created",c));for(let l of i)s.info(R("warn",l,"already exists \u2014 skipped",c));s.info(""),s.info(z([`${o.length} block(s) scaffolded + registered`]))}async function ps(){let e=E();if(!e){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold - CI workflow"));let t=await xn(e);s.info(j("GitHub Actions")),t.created?s.info(P(t.path,"doctor + audit loading + audit security + lint/build")):s.info(R("warn",t.path,"already exists - skipped")),s.info(""),s.info(z([t.created?"CI workflow scaffolded - commit it and it runs on every PR":"CI workflow left untouched"]))}async function us(e){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold - helpers"));let n=e?.length?e:void 0;if(!n)if(process.stdout.isTTY){let{checkbox:i}=await Promise.resolve().then(()=>(K(),q));n=await i({message:"Which helpers?",choices:Rt.map(r=>({name:r.label,value:r.id,checked:!0}))})}else n=Eo;if(!n.length){s.info("Nothing selected.");return}let o=await ns(t,n);s.info(j("Helpers")),o.created?s.info(P(o.path,o.helpers.join(", "))):s.info(R("warn",o.path,"already exists - skipped")),s.info(""),s.info(z([o.created?`${o.helpers.length} helper(s) -> scripts/utils.js`:"Helpers left untouched"]))}async function fs(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold - .env"));let n=e.pagesUrl;if(n===void 0)try{let{execa:a}=await import("execa"),c=await a("git",["remote","get-url","origin"],{cwd:t}),l=ot(c.stdout.trim());n=l?`https://${it(l.owner,l.repo)}`:""}catch{n=""}let o=e.open??"/",i=e.port??"3007";if(!e.yes&&process.stdout.isTTY){let{input:a}=await Promise.resolve().then(()=>(K(),q));o=await a({message:"AEM_OPEN (path opened on start)",default:o}),i=await a({message:"AEM_PORT",default:String(i)}),n=await a({message:"AEM_PAGES_URL (content origin)",default:n})}let r=await $n(t,{open:o,port:i,pagesUrl:n});s.info(j(".env")),r.created?s.info(P(r.path,`AEM_OPEN=${o} AEM_PORT=${i}`)):s.info(R("warn",r.path,"already exists - left untouched")),r.gitignoreUpdated&&s.info(P(".gitignore","added .env")),s.info(""),s.info(z([r.created?".env ready for `aem up`":".env left untouched"]))}async function gs(){let e=E();if(!e){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Scaffold - xwalk.json"));let t=await Pn(e);s.info(j("xwalk.json")),t.created?s.info(P(t.path,"multi-field enabled")):s.info(R("warn",t.path,"already exists - left untouched")),s.info(""),s.info(z([t.created?"xwalk.json ready (UE multi-field)":"xwalk.json left untouched"]))}async function Ed(){let{select:e,checkbox:t}=await Promise.resolve().then(()=>(K(),q));s.logoOnce(A("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 fs();if(n==="xwalk")return gs();if((n==="ue"||n==="both")&&await An(),n==="blocks"||n==="both"){let o=await t({message:"Which blocks?",choices:Ge.map(i=>({name:i.title,value:i.id,checked:!0}))});await ms(o)}n==="ci"&&await ps(),n==="helpers"&&await us()}var ue=v(()=>{"use strict";f();N();V();Po();ko();xo();os();Ao();$o();En();H()});var Ft={};U(Ft,{initProject:()=>Dd});import{existsSync as Ro}from"fs";import{readFile as Do,writeFile as hs}from"fs/promises";import Dn from"path";import Rn from"chalk";async function Cd(e){try{let{execa:t}=await import("execa"),n=await t("git",["remote","get-url","origin"],{cwd:e}),o=ot(n.stdout.trim());return o?`https://${it(o.owner,o.repo)}`:""}catch{return""}}async function Td(e,t){let n=Dn.join(e,"package.json");if(!Ro(n))return!1;try{let o=JSON.parse(await Do(n,"utf-8"));return o.name=t,await hs(n,`${JSON.stringify(o,null,2)}
|
|
345
|
+
`),!0}catch{return!1}}async function Ad(e,t){let n=[];for(let o of["README.md","index.html","head.html"]){let i=Dn.join(e,o);if(Ro(i))try{let r=await Do(i,"utf-8"),a=r.replace(/aem-boilerplate/gi,t);a!==r&&(await hs(i,a),n.push(o))}catch{}}return n}async function Rd(e){let{confirm:t}=await Promise.resolve().then(()=>(K(),q)),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)."}),s.info(j("Next steps (outside the repo)"));for(let o=0;o<n.length;o++){let i=n[o];s.info(` ${_.accent(String(o+1))} ${Rn.bold(i.title)}`),i.url&&s.info(` ${Rn.cyan(i.url)}`),s.info(` ${Rn.dim(i.note)}`),await t({message:" Done / skip?",default:!0})}}async function Dd(e={}){let t=E();if(!t){s.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 s.logoOnceAnimated("Project setup");let{input:n,select:o,confirm:i}=await Promise.resolve().then(()=>(K(),q)),r=!e.yes,a=Dn.basename(t),c=Dn.join(t,"package.json");if(Ro(c))try{let w=JSON.parse(await Do(c,"utf-8")).name??"";w&&!/aem-boilerplate/i.test(w)&&(a=w)}catch{}let l=e.name&&rt(e.name)||rt(r?await n({message:"1/4 Project name",default:rt(a),validate:w=>!!rt(w)||"Use letters, numbers and dashes"}):a),d=e.authoring?void 0:await qr(t);if(!e.authoring&&!r&&!d){s.error("Couldn't detect the authoring model (no fstab.yaml mountpoint or paths.json). Pass --authoring ue|da|gdrive|sharepoint."),process.exitCode=1;return}d&&s.info(Rn.dim(` Detected: ${Ce[d]}`));let m=e.authoring??(r?await o({message:"2/4 Authoring model",default:d,choices:[{name:Ce.ue,value:"ue"},{name:Ce.da,value:"da"},{name:Ce.gdrive,value:"gdrive"},{name:Ce.sharepoint,value:"sharepoint"}]}):d),p=e.mountpoint;if(jn(m)&&!p)if(m==="da"&&(e.org||r)){let w=e.org??await n({message:" DA org",validate:b=>!!b.trim()||"Required"}),y=e.site??(r?await n({message:" DA site",default:l}):l);p=Wr(w.trim(),rt(y))}else m!=="da"&&r&&(p=(await n({message:` ${m==="gdrive"?"Google Drive folder URL":"SharePoint folder URL"}`,validate:y=>/^https?:\/\//.test(y.trim())||"Paste the folder URL"})).trim());let u=e.ci??(r?await i({message:"4/4 Add GitHub Actions CI (audits gatekeeper)?",default:!0}):!0);s.info(j("Summary"));let g=I(["name","authoring","mountpoint","ci"]);if(s.info(P("name",l,g)),s.info(P("authoring",Ce[m],g)),p?s.info(P("mountpoint",p,g)):jn(m)&&s.info(P("mountpoint","(skipped - set it in fstab.yaml later)",g)),s.info(P("ci",u?"yes":"no",g)),s.info(""),r&&!await i({message:"Apply this setup?",default:!0})){s.info("Cancelled.");return}let h=[];await Td(t,l)&&h.push("package.json (name)");for(let w of await Ad(t,l))h.push(`${w} (renamed)`);if(jn(m)&&p&&h.push(await zr(t,p)),m==="ue"&&(await An(),h.push(await Jr(t,l))),u){let w=await xn(t);h.push(w.created?w.path:`${w.path} (exists, skipped)`)}if(e.env!==!1){let w=await $n(t,{pagesUrl:await Cd(t)});h.push(w.created?".env (aem up config)":".env (exists, skipped)")}if(e.xwalk!==!1&&m==="ue"){let w=await Pn(t);h.push(w.created?`${w.path} (UE multi-field)`:`${w.path} (exists, skipped)`)}s.info(j("Configured"));let $=I(h.map(w=>w.split(" ")[0]));for(let w of h){let[y,...b]=w.split(" ");s.info(P(y,b.join(" ").replace(/^\((.*)\)$/,"$1"),$))}s.info(""),r&&await Rd(m),s.info(z([`"${l}" set up for ${Ce[m]}`]))}var rt,Lt=v(()=>{"use strict";f();N();V();ko();xo();Kr();$o();En();H();ue();rt=e=>e.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")});var Fo={};U(Fo,{newProject:()=>Fd});import ws from"path";import bs from"chalk";async function Fd(e,t={}){await s.logoOnceAnimated("New project");let n=!t.yes,{input:o,select:i,confirm:r}=await Promise.resolve().then(()=>(K(),q)),a=e?.trim();if(!a){if(!n){s.error("Pass a folder: `eds new <dir>`."),process.exitCode=1;return}a=(await o({message:"Folder for the new project",default:"my-eds-site",validate:g=>!!g.trim()||"Required"})).trim()}let c=t.boilerplate;!c&&!t.ue&&n&&(c=await i({message:"Which boilerplate?",choices:[{name:`Document Authoring / DA (${Z.document})`,value:Z.document},{name:`Universal Editor / crosswalk (${Z.ue})`,value:Z.ue},{name:`Adobe Commerce storefront (${yn})`,value:yn}]}));let l=Ar(c,t.ue),d=ws.resolve(a);if(!await Rr(d)){s.error(`${a} already exists and isn't empty - refusing to clone into it.`),process.exitCode=1;return}s.info(j("Cloning",`${l.label}${t.ref?`@${t.ref}`:""} \u2192 ${a}`));let m;try{m=await Dr(l,d,{ref:t.ref,keepHistory:t.keepHistory,remote:t.remote,stdio:n?"inherit":"pipe"})}catch(g){s.error(g.message),process.exitCode=1;return}let p=I(["folder","source","history","origin"]);if(s.info(j("Project ready")),s.info(P("folder",d,p)),s.info(P("source",`${l.label} @ ${m.commit.slice(0,7)}`,p)),s.info(P("history",t.keepHistory?"boilerplate history kept (remote: upstream)":m.uncommitted?"fresh, files staged (set git user.name / user.email, then commit)":"fresh (one initial commit)",p)),s.info(P("origin",t.remote??"not set (git remote add origin <url>)",p)),s.info(""),t.install??(n?await r({message:"Install dependencies (npm install)?",default:!0}):!1))try{let{execa:g}=await import("execa");await g("npm",["install"],{cwd:d,stdio:n?"inherit":"pipe"}),s.success("Dependencies installed.")}catch(g){s.warn(`npm install failed: ${g.message.split(`
|
|
346
346
|
`)[0]}`)}if(n&&await r({message:`Configure authoring now (eds init in ${a})?`,default:!0})){let g=process.cwd();try{process.chdir(d);let{initProject:h}=await Promise.resolve().then(()=>(Lt(),Ft));await h({name:ws.basename(d),...l.ue?{authoring:"ue"}:{}})}finally{process.chdir(g)}return}s.info(bs.dim(` Next: cd ${a} && eds init`)),s.info(bs.dim(" Then push it to your own GitHub repo and install AEM Code Sync to get a preview URL."))}var Lo=v(()=>{"use strict";f();Fr();N();bn();H()});function at(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 Ld(e){return`${st}/repos/${e}/generate`}async function Fn(e){let t=await fetch(`${st}/user`,{headers:at(e)});if(!t.ok)throw new Error(`GitHub auth failed: ${t.status}`);return(await t.json()).login}async function ys(e,t,n){let o=await fetch(`${st}/repos/${t}/${n}`,{headers:at(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 vs(e,t,n){let o=await fetch(Ld(t),{method:"POST",headers:at(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 i=await o.json();return{fullName:i.full_name,htmlUrl:i.html_url,cloneUrl:i.clone_url}}async function ks(e,t,n,o){await fetch(`${st}/repos/${t}/${n}/topics`,{method:"PUT",headers:at(e),body:JSON.stringify({names:o})})}async function xs(e,t,n){let o=await fetch(`${st}/repos/${t}/${n}`,{method:"DELETE",headers:at(e)});if(!o.ok&&o.status!==204)throw new Error(`delete failed: ${o.status} ${await o.text()}`)}async function $s(e,t,n){let o=encodeURIComponent(`user:${t} topic:${n} fork:true`),i=await fetch(`${st}/search/repositories?q=${o}&per_page=100`,{headers:at(e)});if(!i.ok)throw new Error(`search failed: ${i.status}`);return(await i.json()).items.map(a=>a.full_name)}var st,Ss=v(()=>{"use strict";f();st="https://api.github.com"});import{existsSync as js}from"fs";import{mkdir as Nd,readFile as Od,rm as Md,writeFile as _d}from"fs/promises";import Id from"os";import Ps from"path";async function Cs(){let e=process.env.GITHUB_TOKEN||process.env.GH_TOKEN;if(e)return e;if(js(Nt))try{return JSON.parse(await Od(Nt,"utf-8")).token??null}catch{return null}return null}async function No(e){await Nd(Es,{recursive:!0,mode:448}),await _d(Nt,`${JSON.stringify({token:e},null,2)}
|
|
347
|
-
`,{mode:384})}async function Ts(){js(Nt)&&await Md(Nt)}async function As(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:Ln,scope:e.join(" ")})});if(!t.ok)throw new Error(`device code request failed: ${t.status}`);return await t.json()}async function Rs(e,t,n){let o=Math.max(t,1),i=Date.now()+n*1e3;for(;Date.now()<i;){await new Promise(c=>setTimeout(c,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:Ln,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 Es,Nt,Ln,Ds=v(()=>{"use strict";f();Es=Ps.join(Id.homedir(),".eds"),Nt=Ps.join(Es,"github.json"),Ln=process.env.EDS_GITHUB_CLIENT_ID??""});var
|
|
348
|
-
`).filter(Boolean):[]}}catch(o){s.error(`List failed: ${o.message}`),process.exitCode=1;return}if(s.info(j("Sandboxes",`${t.length} tagged ${tt}`)),t.length===0){s.info(ae.dim(" None yet. Create one with `eds sandbox new <name>`."));return}let n=I(t);for(let o of t){let[i,r]=o.split("/");s.info(P(o,ho(i,r),n))}}async function qd(e,t={}){let n=await Mo();if(!n)return _o();let o=t.org??n.login,i=`${o}/${e}`;if(!t.yes){let{confirm:r}=await Promise.resolve().then(()=>(K(),q));if(!await r({message:`Permanently delete ${i}? This cannot be undone.`,default:!1})){s.info("Cancelled.");return}}try{n.mode==="api"?await xs(n.token,o,e):await be("gh",["repo","delete",i,"--yes"])}catch(r){s.error(`Delete failed: ${r.message}`),s.info(ae.dim(" Deleting needs the delete_repo scope (re-run `eds sandbox login`, or `gh auth refresh -s delete_repo`).")),process.exitCode=1;return}s.info(j("Deleted")),s.info(P(i,"removed"))}var
|
|
347
|
+
`,{mode:384})}async function Ts(){js(Nt)&&await Md(Nt)}async function As(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:Ln,scope:e.join(" ")})});if(!t.ok)throw new Error(`device code request failed: ${t.status}`);return await t.json()}async function Rs(e,t,n){let o=Math.max(t,1),i=Date.now()+n*1e3;for(;Date.now()<i;){await new Promise(c=>setTimeout(c,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:Ln,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 Es,Nt,Ln,Ds=v(()=>{"use strict";f();Es=Ps.join(Id.homedir(),".eds"),Nt=Ps.join(Es,"github.json"),Ln=process.env.EDS_GITHUB_CLIENT_ID??""});var ze={};U(ze,{sandboxList:()=>Jd,sandboxLogin:()=>Gd,sandboxLogout:()=>Wd,sandboxNew:()=>zd,sandboxRm:()=>qd});import Ud from"path";import ae from"chalk";async function be(e,t,n={}){let{execa:o}=await import("execa");return((await o(e,t,n)).stdout??"").toString().trim()}async function Oo(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{await be(t,[e],{stdio:"ignore"})}catch{}}async function Bd(){try{return await be("gh",["auth","status"]),await be("gh",["api","user","-q",".login"])}catch{return null}}async function Mo(){let e=await Cs();if(e)try{return{mode:"api",token:e,login:await Fn(e)}}catch{}let t=await Bd();return t?{mode:"gh",login:t}:null}async function Hd(e,t,n){if(e.mode==="api")return ys(e.token,t,n);try{return await be("gh",["repo","view",`${t}/${n}`,"--json","name"]),!0}catch{return!1}}function _o(){s.error("Not authenticated with GitHub."),s.info(" Run `eds sandbox login` to authorize GitHub, or install + `gh auth login`."),process.exitCode=1}async function Gd(){await s.logoOnceAnimated("Sandbox - GitHub login");let{input:e}=await Promise.resolve().then(()=>(K(),q));if(Ln){let n=await As(["repo","delete_repo"]);s.info(j("Authorize GitHub")),s.info(P("code",n.user_code)),s.info(P("open",n.verification_uri)),s.info(""),await Oo(n.verification_uri),s.info(ae.dim(" Waiting for you to authorize in the browser..."));try{let o=await Rs(n.device_code,n.interval,n.expires_in);await No(o),s.success(`Authorized as ${await Fn(o)}.`)}catch(o){s.error(`Device flow failed: ${o.message}`),process.exitCode=1}return}s.info(j("Authorize GitHub (least-privilege token)")),s.info(" Create a fine-grained token limited to your sandboxes only:"),s.info(` ${ae.cyan("https://github.com/settings/personal-access-tokens/new")}`),s.info(ae.dim(" - Resource owner: a dedicated sandbox org (recommended) or your account")),s.info(ae.dim(" - Repository access: All repositories in that org (to create new sandboxes),")),s.info(ae.dim(" or Only select repositories to manage existing ones")),s.info(ae.dim(" - Permissions: Administration = Read and write, Contents = Read and write,")),s.info(ae.dim(" Metadata = Read. Set a short expiry.")),s.info(ae.dim(" Tip: `eds sandbox new --org <sandbox-org>` so nothing in your personal account is touched.")),s.info(""),await(await Promise.resolve().then(()=>(K(),q))).confirm({message:"Open the token page?",default:!0})&&await Oo("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 Fn(t);await No(t),s.success(`Authorized as ${n}.`)}catch{s.error("That token didn't work (check the scopes)."),process.exitCode=1}}async function Wd(){await Ts(),s.success("Signed out (stored GitHub token removed).")}async function zd(e,t={}){let n=await Mo();if(!n)return _o();await s.logoOnceAnimated("Sandbox");let o=!t.yes,{select:i,confirm:r}=await Promise.resolve().then(()=>(K(),q)),a=t.boilerplate;a||(t.ue?a=Z.ue:o?a=await i({message:"Which boilerplate?",choices:[{name:"Document Authoring (adobe/aem-boilerplate)",value:Z.document},{name:"Universal Editor / crosswalk (adobe-rnd/aem-boilerplate-xwalk)",value:Z.ue}]}):a=Z.document);let c=t.private??!1;t.private===void 0&&o&&(c=await i({message:"Visibility?",choices:[{name:"Public",value:!1},{name:"Private",value:!0}],default:!1}));let l=t.org??n.login;if(await Hd(n,l,e)){s.error(`A repository ${l}/${e} already exists - refusing to touch it.`),s.info(ae.dim(" Pick another name, or remove it first (e.g. `eds sandbox rm` for a sandbox).")),process.exitCode=1;return}s.info(j("Creating sandbox",`${l}/${e} \xB7 ${a}`));try{if(n.mode==="api"){let d=await vs(n.token,a,{owner:l,name:e,private:c});await ks(n.token,l,e,[tt]),s.info(ae.dim(" Cloning...")),await be("git",["clone",d.cloneUrl,e],{stdio:"inherit"})}else{let d=t.org?`${t.org}/${e}`:e;await be("gh",Er(d,{template:a,private:c,clone:!0}),{stdio:"inherit"});try{await be("gh",["repo","edit",`${l}/${e}`,"--add-topic",tt])}catch{}}}catch(d){s.error(`Create failed: ${d.message}`),process.exitCode=1;return}if(s.info(""),s.info(j("Sandbox ready")),s.info(P("repo",`https://github.com/${l}/${e}`)),s.info(P("preview",ho(l,e))),s.info(""),o){if(await r({message:"Open the AEM Code Sync install page now?",default:!0})&&await Oo(wo()),await r({message:`Configure authoring now (eds init in ./${e})?`,default:!0})){let d=process.cwd();try{process.chdir(Ud.join(d,e));let{initProject:m}=await Promise.resolve().then(()=>(Lt(),Ft));await m({})}finally{process.chdir(d)}}}else s.info(ae.dim(` Install AEM Code Sync: ${wo()}`)),s.info(ae.dim(` Configure authoring: cd ${e} && eds init`));s.info(""),s.info(z([`Sandbox "${e}" ready - tear down with \`eds sandbox rm ${e}\``]))}async function Jd(){let e=await Mo();if(!e)return _o();let t=[];try{if(e.mode==="api")t=await $s(e.token,e.login,tt);else{let o=await be("gh",["repo","list","--topic",tt,"--limit","100","--json","nameWithOwner","-q",".[].nameWithOwner"]);t=o?o.split(`
|
|
348
|
+
`).filter(Boolean):[]}}catch(o){s.error(`List failed: ${o.message}`),process.exitCode=1;return}if(s.info(j("Sandboxes",`${t.length} tagged ${tt}`)),t.length===0){s.info(ae.dim(" None yet. Create one with `eds sandbox new <name>`."));return}let n=I(t);for(let o of t){let[i,r]=o.split("/");s.info(P(o,ho(i,r),n))}}async function qd(e,t={}){let n=await Mo();if(!n)return _o();let o=t.org??n.login,i=`${o}/${e}`;if(!t.yes){let{confirm:r}=await Promise.resolve().then(()=>(K(),q));if(!await r({message:`Permanently delete ${i}? This cannot be undone.`,default:!1})){s.info("Cancelled.");return}}try{n.mode==="api"?await xs(n.token,o,e):await be("gh",["repo","delete",i,"--yes"])}catch(r){s.error(`Delete failed: ${r.message}`),s.info(ae.dim(" Deleting needs the delete_repo scope (re-run `eds sandbox login`, or `gh auth refresh -s delete_repo`).")),process.exitCode=1;return}s.info(j("Deleted")),s.info(P(i,"removed"))}var Je=v(()=>{"use strict";f();N();Ss();Ds();bn();H()});import{existsSync as Kd}from"fs";import{readFile as Vd}from"fs/promises";import Xd from"path";import{parse as Yd}from"yaml";async function Fs(e){let t=Xd.join(e,"fstab.yaml");if(Kd(t))try{let o=(Yd(await Vd(t,"utf-8"))??{}).mountpoints?.["/"],i=typeof o=="string"?o:o?.url??"",r=i.match(/content\.da\.live\/([^/]+)\/([^/]+)/);return r?{model:"da",org:r[1],site:r[2],mountpoint:i}:/drive\.google\.com/.test(i)?{model:"gdrive",mountpoint:i}:/sharepoint\.com|-my\.sharepoint/.test(i)?{model:"sharepoint",mountpoint:i}:{model:"document",mountpoint:i}}catch{}return{model:"ue"}}var Ls=v(()=>{"use strict";f()});function Qd(e,t,n){let o=n.replace(/^\/+/,"").replace(/\.html$/i,"");return`https://admin.da.live/source/${e}/${t}/${o}.html`}function Ns(e,t,n){let o=n.replace(/^\/+/,"").replace(/\.html$/i,"");return`https://da.live/edit#/${e}/${t}/${o}`}async function Os(e,t,n,o,i){let r=Qd(e,t,n),a=new FormData;a.append("data",new Blob([o],{type:"text/html"}),"content.html");let c={};i&&(c.Authorization=`Bearer ${i}`);let l=await fetch(r,{method:"POST",body:a,headers:c});if(!l.ok)throw new Error(`DA push failed: ${l.status} ${l.statusText}`);return r}var Ms=v(()=>{"use strict";f()});function Zd(e){return` <div class="${e}">
|
|
349
349
|
<div>
|
|
350
350
|
<div>${e} content</div>
|
|
351
351
|
</div>
|
|
@@ -369,10 +369,10 @@ ${[n,...o,i].join(`
|
|
|
369
369
|
</body>
|
|
370
370
|
`}var Is=v(()=>{"use strict";f()});import{existsSync as tm}from"fs";import{readFile as nm}from"fs/promises";import om from"path";function im(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 rm(e,t){let n=om.join(e,"blocks",t,`_${t}.json`);if(!tm(n))return{};try{let o=JSON.parse(await nm(n,"utf-8")),i=Array.isArray(o.models)?o.models:[],a=(i.find(l=>l.id===t)??i[0])?.fields??[],c={};for(let l of a)l.component!=="tab"&&(c[l.name]=l.component==="container"?[]:im(l));return c}catch{return{}}}async function Us(e,t){let n=[];for(let i of t.blocks)n.push({name:i,model:i,fields:await rm(e,i)});let o={title:t.title,template:t.name,components:n};return`${JSON.stringify(o,null,2)}
|
|
371
371
|
`}var Bs=v(()=>{"use strict";f()});var Bo={};U(Bo,{templateNew:()=>pm});import{existsSync as Uo}from"fs";import{mkdir as sm,readFile as Hs,readdir as am,writeFile as Io}from"fs/promises";import Te from"path";import Ot from"chalk";async function lm(e){let t=Te.join(e,"blocks");return Uo(t)?(await am(t,{withFileTypes:!0})).filter(n=>n.isDirectory()).map(n=>n.name):[]}async function dm(e){let t=Te.join(e,".edsrc.json");if(!Uo(t))return{};try{return JSON.parse(await Hs(t,"utf-8")).admin??{}}catch{return{}}}async function mm(e,t){if(!t.length)return!1;let n=Te.join(e,"component-filters.json"),o=null;if(Uo(n))try{o=JSON.parse(await Hs(n,"utf-8"))}catch{o=null}let i=Dt(o,t);return await Io(n,`${JSON.stringify(i,null,2)}
|
|
372
|
-
`),!0}async function pm(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await s.logoOnceAnimated("Page template");let{input:o,select:i,confirm:r}=await Promise.resolve().then(()=>(K(),q)),a=!t.yes,c=await Fs(n),l=t.authoring??c.model,d=cm(e),m=t.title??(a?await o({message:"Page title",default:e}):e),p=t.description??(a?await o({message:"Description (optional)"}):""),u=t.path??`/templates/${d}`,g=t.blocks;if(!g&&a){let y=await lm(n),b=y.length?y:Ge.map(O=>O.id),T=[],D=!0;for(;D;){let O=await i({message:`Add a block in order (${T.length} so far)`,choices:[...b.map(ne=>({name:ne,value:ne})),{name:T.length?"- done -":"- done (empty page) -",value:"__done"}]});O==="__done"?D=!1:T.push(O)}g=T}let h=g??[],$=_s({title:m,description:p||void 0,blocks:h,area:t.area}),w=Te.join("templates",`${d}.html`);if(await sm(Te.join(n,"templates"),{recursive:!0}),await Io(Te.join(n,w),$),s.info(j("Page template",`${u} \xB7 ${l}`)),s.info(P(w,`${h.length} block(s) + metadata`)),l==="da"){let y=await dm(n),b=t.org??y.org??c.org,T=t.site??y.site??c.site;if(t.push??(a?await r({message:"Push to DA (da.live)?",default:!0}):!0))if(!b||!T)s.warn("No DA org/site. Pass --org/--site or set admin in .edsrc.json.");else try{await Os(b,T,u,$,process.env.DA_TOKEN),s.info(P("pushed to DA",Ns(b,T,u)))}catch(O){s.error(`DA push failed: ${O.message}`),s.info(Ot.dim(" Open projects allow anonymous writes; others need DA_TOKEN."))}}else if(l==="gdrive"||l==="sharepoint"){let y=l==="gdrive"?"a Google Doc":"a Word doc";s.info(""),s.info(Ot.dim(` Document model: import ${w} into ${y} in your mounted folder,`)),s.info(Ot.dim(" then preview/publish. (Share the folder + install aem-code-sync first.)"))}else if(l==="ue"){let y=Te.join("templates",`${d}.json`);await Io(Te.join(n,y),await Us(n,{title:m,name:d,blocks:h})),s.info(P(y,`initial content (${h.length} component(s), in order)`)),await mm(n,h)&&s.info(P("component-filters.json","seeded blocks allowed in Universal Editor")),s.info(""),s.info(Ot.dim(" Universal Editor: use the template JSON as the page's initial content, then")),s.info(Ot.dim(" author it in the Universal Editor (wire the repo to AEM)."))}s.info(""),s.info(
|
|
372
|
+
`),!0}async function pm(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await s.logoOnceAnimated("Page template");let{input:o,select:i,confirm:r}=await Promise.resolve().then(()=>(K(),q)),a=!t.yes,c=await Fs(n),l=t.authoring??c.model,d=cm(e),m=t.title??(a?await o({message:"Page title",default:e}):e),p=t.description??(a?await o({message:"Description (optional)"}):""),u=t.path??`/templates/${d}`,g=t.blocks;if(!g&&a){let y=await lm(n),b=y.length?y:Ge.map(O=>O.id),T=[],D=!0;for(;D;){let O=await i({message:`Add a block in order (${T.length} so far)`,choices:[...b.map(ne=>({name:ne,value:ne})),{name:T.length?"- done -":"- done (empty page) -",value:"__done"}]});O==="__done"?D=!1:T.push(O)}g=T}let h=g??[],$=_s({title:m,description:p||void 0,blocks:h,area:t.area}),w=Te.join("templates",`${d}.html`);if(await sm(Te.join(n,"templates"),{recursive:!0}),await Io(Te.join(n,w),$),s.info(j("Page template",`${u} \xB7 ${l}`)),s.info(P(w,`${h.length} block(s) + metadata`)),l==="da"){let y=await dm(n),b=t.org??y.org??c.org,T=t.site??y.site??c.site;if(t.push??(a?await r({message:"Push to DA (da.live)?",default:!0}):!0))if(!b||!T)s.warn("No DA org/site. Pass --org/--site or set admin in .edsrc.json.");else try{await Os(b,T,u,$,process.env.DA_TOKEN),s.info(P("pushed to DA",Ns(b,T,u)))}catch(O){s.error(`DA push failed: ${O.message}`),s.info(Ot.dim(" Open projects allow anonymous writes; others need DA_TOKEN."))}}else if(l==="gdrive"||l==="sharepoint"){let y=l==="gdrive"?"a Google Doc":"a Word doc";s.info(""),s.info(Ot.dim(` Document model: import ${w} into ${y} in your mounted folder,`)),s.info(Ot.dim(" then preview/publish. (Share the folder + install aem-code-sync first.)"))}else if(l==="ue"){let y=Te.join("templates",`${d}.json`);await Io(Te.join(n,y),await Us(n,{title:m,name:d,blocks:h})),s.info(P(y,`initial content (${h.length} component(s), in order)`)),await mm(n,h)&&s.info(P("component-filters.json","seeded blocks allowed in Universal Editor")),s.info(""),s.info(Ot.dim(" Universal Editor: use the template JSON as the page's initial content, then")),s.info(Ot.dim(" author it in the Universal Editor (wire the repo to AEM)."))}s.info(""),s.info(z([`"${d}" template (${l}) - preview with \`eds preview ${u}\``]))}var cm,Ho=v(()=>{"use strict";f();N();V();Po();Ao();Ls();Ms();Is();Bs();H();cm=e=>e.trim().toLowerCase().replace(/[^a-z0-9-/]+/g,"-").replace(/^-+|-+$/g,"")});import{existsSync as Nn}from"fs";import{readFile as Gs,readdir as Ws}from"fs/promises";import qe from"path";async function um(e){let t=[],n=async o=>{for(let i of await Ws(o,{withFileTypes:!0})){let r=qe.join(o,i.name);i.isDirectory()?await n(r):t.push(r)}};return Nn(e)&&await n(e),t}async function zs(e){if(!Nn(e))return null;let t=await Ws(e,{withFileTypes:!0}),n=t.find(i=>i.isDirectory()&&/clientlib/i.test(i.name));return n?qe.join(e,n.name):t.some(i=>i.isFile()&&i.name.endsWith(".css"))?e:null}async function Js(e){let t=await um(e),n=t.filter(a=>/\.(less|scss|sass)$/i.test(a)).map(a=>qe.relative(e,a)),o,i=qe.join(e,"css.txt");if(Nn(i)){let a=(await Gs(i,"utf-8")).split(`
|
|
373
373
|
`).map(d=>d.trim()),c=e,l=[];for(let d of a){if(!d)continue;let m=d.match(/^#base\s*=\s*(.+)$/);m?c=qe.join(e,m[1].trim()):d.startsWith("#")||l.push(d)}o=l.map(d=>qe.join(c,d)).filter(d=>Nn(d)&&d.endsWith(".css"))}else o=t.filter(a=>a.endsWith(".css"));let r=[];for(let a of o)r.push(await Gs(a,"utf-8"));return{css:r.join(`
|
|
374
374
|
|
|
375
|
-
`),files:o.map(a=>qe.relative(e,a)),preprocessed:n}}var qs=v(()=>{"use strict";f()});import{XMLParser as fm}from"fast-xml-parser";function oe(e){return Object.keys(e).find(t=>t!==":@")??""}function Q(e){let t=oe(e),n=e[t];return Array.isArray(n)?n:[]}function gm(e){return e[":@"]??{}}function hm(e){return typeof e=="string"?e.replace(/^\{[^}]+\}/,""):e}function C(e,t){return hm(gm(e)[`@_${t}`])}function wm(e,t){let n=C(t,"multiple")==="true"||C(t,"multiple")==="{Boolean}true";return e.endsWith("/form/pagefield")?"aem-content":e.includes("experience-fragment")||e.endsWith("/xffield")?"aem-experience-fragment":e.endsWith("/cfpicker")?"aem-content-fragment":e.endsWith("/form/textfield")||e.endsWith("/form/colorfield")||e.includes("/autocomplete")?"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 bm(e){return e.endsWith("/form/hidden")||e.endsWith("/foundation/heading")||e.endsWith("/foundation/text")}function ym(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 Go(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 Ke(e,t){return(e??"").replace(/^\.\//,"").trim()||t}function km(e){let t=Q(e).find(n=>oe(n)==="items");return t?Q(t).map(n=>{let o=C(n,"value")??"";return{name:C(n,"text")??C(n,"jcr:title")??o,value:o}}):[]}function Mt(e,t,n){let{unmapped:o,counter:i}=n;for(let r of e){let a=C(r,"sling:resourceType")??"";if(a.endsWith("/foundation/include")){let l=n.includeDepth<8?n.resolveInclude?.(C(r,"path")??""):null;l&&Mt(l,t,{...n,includeDepth:n.includeDepth+1});continue}if(bm(a))continue;if(a.endsWith("/foundation/tabs")){let l=Q(r).find(d=>oe(d)==="items");for(let d of l?Q(l):[]){let m=C(d,"jcr:title");t.push({component:"tab",name:Ke(void 0,oe(d)),label:m}),Mt(Q(d),t,n)}continue}if(a.endsWith("/form/multifield")){let l=[];Mt(Q(r),l,n);let d=Q(r).find(p=>oe(p)==="field"),m=Ke(C(r,"name")??(d?C(d,"name"):void 0),`items${i.i++}`);t.push({component:"container",name:m,label:C(r,"fieldLabel")??"Items",multi:!0,collapsible:!0,fields:l});continue}let c=a?wm(a,r):null;if(c){let l=Ke(C(r,"name"),`field${i.i++}`),d={component:c,name:l},m=Go(c);m&&(d.valueType=m);let p=C(r,"fieldLabel")??C(r,"text");if(p&&(d.label=p),c==="select"||c==="radio-group"||c==="multiselect"){let g=km(r),h=Q(r).find(w=>oe(w)==="datasource"),$=h?C(h,"sling:resourceType")??"":"";g.length?d.options=g:/heading|allowedtypes/i.test($)?d.options=vm:(d.component="text",d.valueType="string",n.datasourced.add(l))}let u=c==="boolean"?C(r,"checked"):C(r,"value");u!==void 0&&u!==""&&(d.value=c==="boolean"?u==="true":u),t.push(d);continue}a&&C(r,"name")&&!ym(a)&&o.add(a),Mt(Q(r),t,n)}}function Wo(e){return e.filter((t,n)=>t.component!=="tab"||e[n+1]&&e[n+1].component!=="tab")}function On(e){let t=new Set,n=[];for(let o of e){if(o.component!=="tab"){if(t.has(o.name))continue;t.add(o.name)}n.push(o.fields?{...o,fields:On(o.fields)}:o)}return n}function _t(e){return new fm({ignoreAttributes:!1,attributeNamePrefix:"@_",preserveOrder:!0,removeNSPrefix:!1,trimValues:!0}).parse(e)}function Ks(e,t={}){let n=_t(e).find(a=>oe(a)==="jcr:root"),o=[],i=new Set,r=new Set;return n&&Mt(Q(n),o,{unmapped:i,datasourced:r,counter:{i:1},resolveInclude:t.resolveInclude,includeDepth:0}),{fields:Wo(On(o)),unmapped:[...i],datasourced:[...r]}}function ct(e){let t=0;for(let n of e)n.component!=="tab"&&(t+=1,n.fields&&(t+=ct(n.fields)));return t}var vm,Mn=v(()=>{"use strict";f();vm=["h1","h2","h3","h4","h5","h6"].map(e=>({name:e.toUpperCase(),value:e}))});function It(e){return(C(e,"xtype")??"").toLowerCase()}function Ut(e){let t=Q(e).find(n=>oe(n)==="items");return t?C(t,"jcr:primaryType")==="cq:WidgetCollection"||!C(t,"xtype")?Q(t):[t]:Q(e).filter(n=>/^cq:/.test(C(n,"jcr:primaryType")??""))}function $m(e){let t=Q(e).find(n=>oe(n)==="options");return t?Q(t).map(n=>{let o=C(n,"value")??"";return{name:C(n,"text")??o,value:o}}):[]}function Vs(e,t,n){let o=C(e,"name")??C(e,"key"),i=null,r,a=Ke(o,`field${n.counter.i++}`);switch(t){case"textfield":case"colorfield":case"":i="text";break;case"textarea":i="textarea";break;case"richtext":i="richtext";break;case"numberfield":i="number";break;case"checkbox":i="boolean";break;case"datetime":case"datefield":i="date-time";break;case"pathfield":case"browsefield":i="aem-content";break;case"tags":case"tagsinputfield":i="aem-tag";break;case"smartimage":case"html5smartimage":case"smartfile":case"html5smartfile":case"fileupload":i="reference",a=Ke(C(e,"fileReferenceParameter")??o,a);break;case"selection":{let p=(C(e,"type")??"select").toLowerCase();r=$m(e),p==="checkbox"?i=r.length?"checkbox-group":"boolean":p==="radio"?i="radio-group":i="select",i!=="boolean"&&!r.length&&(i="text",n.datasourced.add(a));break}default:return null}let c={component:i,name:a},l=Go(i);l&&(c.valueType=l);let d=C(e,"fieldLabel")??C(e,"boxLabel")??C(e,"title");d&&(c.label=d),r?.length&&i!=="text"&&(c.options=r);let m=i==="boolean"?C(e,"checked")??C(e,"defaultValue"):C(e,"defaultValue")??C(e,"value");return m!==void 0&&m!==""&&(c.value=i==="boolean"?m==="true":m),c}function Ve(e,t,n){for(let o of e){let i=It(o);if(xm.has(i))continue;if(oe(o)==="items"||C(o,"jcr:primaryType")==="cq:WidgetCollection"){Ve(Q(o),t,n);continue}if(i==="slingscriptinclude"){/^rte\./.test(C(o,"script")??"")?t.push({component:"richtext",name:"text",valueType:"string",label:"Text"}):n.unmapped.add("xtype:slingscriptinclude");continue}if(i==="cqinclude"){let a=(C(o,"path")??"").replace(/\.(infinity|\d+)?\.?json$/,""),c=n.depth<8?n.resolveInclude?.(a):null;c&&Ve(c,t,{...n,depth:n.depth+1});continue}if(i==="tabpanel"){for(let a of Ut(o)){if(It(a)==="cqinclude"){Ve([a],t,n);continue}t.push({component:"tab",name:oe(a),label:C(a,"title")}),Ve(Ut(a),t,n)}continue}if(i==="multifield"){let a=Q(o).find(d=>oe(d)==="fieldConfig"),c=Ke(C(o,"name"),`items${n.counter.i++}`);if(a&&!Jo.has(It(a))&&!C(a,"name")&&!C(a,"key")){let d=Vs(a,It(a),n);if(d){t.push({...d,name:c,label:C(o,"fieldLabel")??d.label,multi:!0});continue}}let l=[];a&&Ve(Jo.has(It(a))?Ut(a):[a],l,n),t.push({component:"container",name:c,label:C(o,"fieldLabel")??"Items",multi:!0,collapsible:!0,fields:l});continue}if(Jo.has(i)||C(o,"jcr:primaryType")==="cq:Panel"||!i&&!C(o,"name")&&Ut(o).length){Ve(Ut(o),t,n);continue}let r=C(o,"name")||C(o,"key")?Vs(o,i,n):null;r?t.push(r):i&&n.unmapped.add(`xtype:${i}`)}}function Xs(e){return/jcr:primaryType="cq:(Dialog|TabPanel|Panel|Widget)"/.test(e)||/\sxtype="/.test(e)}function Ys(e,t={}){let n=_t(e).find(r=>oe(r)==="jcr:root"),o=[],i={unmapped:new Set,datasourced:new Set,counter:{i:1},resolveInclude:t.resolveInclude,depth:0};return n&&Ve([n],o,i),{fields:Wo(On(o)),unmapped:[...i.unmapped],datasourced:[...i.datasourced]}}var Jo,xm,Qs=v(()=>{"use strict";f();Mn();Jo=new Set(["dialog","panel","dialogfieldset","multifieldpanel","fieldset"]),xm=new Set(["hidden","static","displayfield","label","box","componentstyles"])});import{existsSync as lt,readFileSync as Zs}from"fs";import{readFile as Sm}from"fs/promises";import ie from"path";import{XMLParser as jm}from"fast-xml-parser";function Pm(e){return[ie.join(e,"_cq_dialog",".content.xml"),ie.join(e,"_cq_dialog.xml"),ie.join(e,"cq:dialog",".content.xml")].find(n=>lt(n))??null}function Em(e){return[ie.join(e,"dialog.xml"),ie.join(e,"dialog",".content.xml")].find(n=>lt(n))??null}function ea(e,t){let n=ie.join(e,".content.xml");if(lt(n))try{let r=(new jm({ignoreAttributes:!1,attributeNamePrefix:"@_"}).parse(Zs(n,"utf-8"))["jcr:root"]??{})[`@_${t}`];return typeof r=="string"?r.replace(/^\{[^}]+\}/,""):void 0}catch{return}}async function ta(e){return ea(e,"jcr:title")}function zo(e){return ea(e,"sling:resourceSuperType")}function Cm(e){let t=ie.resolve(e);for(;t!==ie.dirname(t);){if(ie.basename(t)==="jcr_root")return t;t=ie.dirname(t)}return null}function na(e,t){let n=e.replace(/^\/mnt\/overlay\//,"/").replace(/^\/(apps|libs)\//,"").replace(/^\//,"").split("/").map(i=>i.replace(/^([a-z]+):/,"_$1_")).join("/"),o=[];for(let i of t)o.push(ie.join(i,"apps",n),ie.join(i,"libs",n),ie.join(i,n));return o}function Tm(e){let t=new Map,n=o=>{if(!t.has(o))try{let i=_t(Zs(o,"utf-8")).find(r=>oe(r)==="jcr:root");t.set(o,i?Q(i):null)}catch{t.set(o,null)}return t.get(o)??null};return o=>{if(!o||o.includes("${"))return null;for(let i of na(o,e)){let r=i.split(ie.sep);for(let a=r.length;a>1;a--){let c=r.slice(0,a).join(ie.sep),l=lt(ie.join(c,".content.xml"))?ie.join(c,".content.xml"):lt(`${c}.xml`)?`${c}.xml`:null;if(!l)continue;let d=n(l);for(let m of r.slice(a)){let p=d?.find(u=>oe(u)===m);d=p?[p]:null}if(d)return d;break}}return null}}async function oa(e,t=[]){let n=Cm(e),o=[...n?[n]:[],...t],i=Tm(o),r=e,a,c=null;for(let l=0;l<8;l++){let d=Pm(r),m=d?null:Em(r),p=d??m;if(p){let h=await Sm(p,"utf-8"),$=m&&Xs(h)?"classic":"touch",w=$==="classic"?Ys(h,{resolveInclude:i}):Ks(h,{resolveInclude:i});if(ct(w.fields)>0)return{...w,inheritedFrom:a,dialogKind:$};c??={...w,dialogKind:$}}let u=zo(r),g=u?na(u,o).find(h=>lt(h)):void 0;if(!u||!g)break;r=g,a=u}return c}function ia(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)}
|
|
375
|
+
`),files:o.map(a=>qe.relative(e,a)),preprocessed:n}}var qs=v(()=>{"use strict";f()});import{XMLParser as fm}from"fast-xml-parser";function oe(e){return Object.keys(e).find(t=>t!==":@")??""}function Q(e){let t=oe(e),n=e[t];return Array.isArray(n)?n:[]}function gm(e){return e[":@"]??{}}function hm(e){return typeof e=="string"?e.replace(/^\{[^}]+\}/,""):e}function C(e,t){return hm(gm(e)[`@_${t}`])}function wm(e,t){let n=C(t,"multiple")==="true"||C(t,"multiple")==="{Boolean}true";return e.endsWith("/form/pagefield")?"aem-content":e.includes("experience-fragment")||e.endsWith("/xffield")?"aem-experience-fragment":e.endsWith("/cfpicker")?"aem-content-fragment":e.endsWith("/form/textfield")||e.endsWith("/form/colorfield")||e.includes("/autocomplete")?"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 bm(e){return e.endsWith("/form/hidden")||e.endsWith("/foundation/heading")||e.endsWith("/foundation/text")}function ym(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 Go(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 Ke(e,t){return(e??"").replace(/^\.\//,"").trim()||t}function km(e){let t=Q(e).find(n=>oe(n)==="items");return t?Q(t).map(n=>{let o=C(n,"value")??"";return{name:C(n,"text")??C(n,"jcr:title")??o,value:o}}):[]}function Mt(e,t,n){let{unmapped:o,counter:i}=n;for(let r of e){let a=C(r,"sling:resourceType")??"";if(a.endsWith("/foundation/include")){let l=n.includeDepth<8?n.resolveInclude?.(C(r,"path")??""):null;l&&Mt(l,t,{...n,includeDepth:n.includeDepth+1});continue}if(bm(a))continue;if(a.endsWith("/foundation/tabs")){let l=Q(r).find(d=>oe(d)==="items");for(let d of l?Q(l):[]){let m=C(d,"jcr:title");t.push({component:"tab",name:Ke(void 0,oe(d)),label:m}),Mt(Q(d),t,n)}continue}if(a.endsWith("/form/multifield")){let l=[];Mt(Q(r),l,n);let d=Q(r).find(p=>oe(p)==="field"),m=Ke(C(r,"name")??(d?C(d,"name"):void 0),`items${i.i++}`);t.push({component:"container",name:m,label:C(r,"fieldLabel")??"Items",multi:!0,collapsible:!0,fields:l});continue}let c=a?wm(a,r):null;if(c){let l=Ke(C(r,"name"),`field${i.i++}`),d={component:c,name:l},m=Go(c);m&&(d.valueType=m);let p=C(r,"fieldLabel")??C(r,"text");if(p&&(d.label=p),c==="select"||c==="radio-group"||c==="multiselect"){let g=km(r),h=Q(r).find(w=>oe(w)==="datasource"),$=h?C(h,"sling:resourceType")??"":"";g.length?d.options=g:/heading|allowedtypes/i.test($)?d.options=vm:(d.component="text",d.valueType="string",n.datasourced.add(l))}let u=c==="boolean"?C(r,"checked"):C(r,"value");u!==void 0&&u!==""&&(d.value=c==="boolean"?u==="true":u),t.push(d);continue}a&&C(r,"name")&&!ym(a)&&o.add(a),Mt(Q(r),t,n)}}function Wo(e){return e.filter((t,n)=>t.component!=="tab"||e[n+1]&&e[n+1].component!=="tab")}function On(e){let t=new Set,n=[];for(let o of e){if(o.component!=="tab"){if(t.has(o.name))continue;t.add(o.name)}n.push(o.fields?{...o,fields:On(o.fields)}:o)}return n}function _t(e){return new fm({ignoreAttributes:!1,attributeNamePrefix:"@_",preserveOrder:!0,removeNSPrefix:!1,trimValues:!0}).parse(e)}function Ks(e,t={}){let n=_t(e).find(a=>oe(a)==="jcr:root"),o=[],i=new Set,r=new Set;return n&&Mt(Q(n),o,{unmapped:i,datasourced:r,counter:{i:1},resolveInclude:t.resolveInclude,includeDepth:0}),{fields:Wo(On(o)),unmapped:[...i],datasourced:[...r]}}function ct(e){let t=0;for(let n of e)n.component!=="tab"&&(t+=1,n.fields&&(t+=ct(n.fields)));return t}var vm,Mn=v(()=>{"use strict";f();vm=["h1","h2","h3","h4","h5","h6"].map(e=>({name:e.toUpperCase(),value:e}))});function It(e){return(C(e,"xtype")??"").toLowerCase()}function Ut(e){let t=Q(e).find(n=>oe(n)==="items");return t?C(t,"jcr:primaryType")==="cq:WidgetCollection"||!C(t,"xtype")?Q(t):[t]:Q(e).filter(n=>/^cq:/.test(C(n,"jcr:primaryType")??""))}function $m(e){let t=Q(e).find(n=>oe(n)==="options");return t?Q(t).map(n=>{let o=C(n,"value")??"";return{name:C(n,"text")??o,value:o}}):[]}function Vs(e,t,n){let o=C(e,"name")??C(e,"key"),i=null,r,a=Ke(o,`field${n.counter.i++}`);switch(t){case"textfield":case"colorfield":case"":i="text";break;case"textarea":i="textarea";break;case"richtext":i="richtext";break;case"numberfield":i="number";break;case"checkbox":i="boolean";break;case"datetime":case"datefield":i="date-time";break;case"pathfield":case"browsefield":i="aem-content";break;case"tags":case"tagsinputfield":i="aem-tag";break;case"smartimage":case"html5smartimage":case"smartfile":case"html5smartfile":case"fileupload":i="reference",a=Ke(C(e,"fileReferenceParameter")??o,a);break;case"selection":{let p=(C(e,"type")??"select").toLowerCase();r=$m(e),p==="checkbox"?i=r.length?"checkbox-group":"boolean":p==="radio"?i="radio-group":i="select",i!=="boolean"&&!r.length&&(i="text",n.datasourced.add(a));break}default:return null}let c={component:i,name:a},l=Go(i);l&&(c.valueType=l);let d=C(e,"fieldLabel")??C(e,"boxLabel")??C(e,"title");d&&(c.label=d),r?.length&&i!=="text"&&(c.options=r);let m=i==="boolean"?C(e,"checked")??C(e,"defaultValue"):C(e,"defaultValue")??C(e,"value");return m!==void 0&&m!==""&&(c.value=i==="boolean"?m==="true":m),c}function Ve(e,t,n){for(let o of e){let i=It(o);if(xm.has(i))continue;if(oe(o)==="items"||C(o,"jcr:primaryType")==="cq:WidgetCollection"){Ve(Q(o),t,n);continue}if(i==="slingscriptinclude"){/^rte\./.test(C(o,"script")??"")?t.push({component:"richtext",name:"text",valueType:"string",label:"Text"}):n.unmapped.add("xtype:slingscriptinclude");continue}if(i==="cqinclude"){let a=(C(o,"path")??"").replace(/\.(infinity|\d+)?\.?json$/,""),c=n.depth<8?n.resolveInclude?.(a):null;c&&Ve(c,t,{...n,depth:n.depth+1});continue}if(i==="tabpanel"){for(let a of Ut(o)){if(It(a)==="cqinclude"){Ve([a],t,n);continue}t.push({component:"tab",name:oe(a),label:C(a,"title")}),Ve(Ut(a),t,n)}continue}if(i==="multifield"){let a=Q(o).find(d=>oe(d)==="fieldConfig"),c=Ke(C(o,"name"),`items${n.counter.i++}`);if(a&&!zo.has(It(a))&&!C(a,"name")&&!C(a,"key")){let d=Vs(a,It(a),n);if(d){t.push({...d,name:c,label:C(o,"fieldLabel")??d.label,multi:!0});continue}}let l=[];a&&Ve(zo.has(It(a))?Ut(a):[a],l,n),t.push({component:"container",name:c,label:C(o,"fieldLabel")??"Items",multi:!0,collapsible:!0,fields:l});continue}if(zo.has(i)||C(o,"jcr:primaryType")==="cq:Panel"||!i&&!C(o,"name")&&Ut(o).length){Ve(Ut(o),t,n);continue}let r=C(o,"name")||C(o,"key")?Vs(o,i,n):null;r?t.push(r):i&&n.unmapped.add(`xtype:${i}`)}}function Xs(e){return/jcr:primaryType="cq:(Dialog|TabPanel|Panel|Widget)"/.test(e)||/\sxtype="/.test(e)}function Ys(e,t={}){let n=_t(e).find(r=>oe(r)==="jcr:root"),o=[],i={unmapped:new Set,datasourced:new Set,counter:{i:1},resolveInclude:t.resolveInclude,depth:0};return n&&Ve([n],o,i),{fields:Wo(On(o)),unmapped:[...i.unmapped],datasourced:[...i.datasourced]}}var zo,xm,Qs=v(()=>{"use strict";f();Mn();zo=new Set(["dialog","panel","dialogfieldset","multifieldpanel","fieldset"]),xm=new Set(["hidden","static","displayfield","label","box","componentstyles"])});import{existsSync as lt,readFileSync as Zs}from"fs";import{readFile as Sm}from"fs/promises";import ie from"path";import{XMLParser as jm}from"fast-xml-parser";function Pm(e){return[ie.join(e,"_cq_dialog",".content.xml"),ie.join(e,"_cq_dialog.xml"),ie.join(e,"cq:dialog",".content.xml")].find(n=>lt(n))??null}function Em(e){return[ie.join(e,"dialog.xml"),ie.join(e,"dialog",".content.xml")].find(n=>lt(n))??null}function ea(e,t){let n=ie.join(e,".content.xml");if(lt(n))try{let r=(new jm({ignoreAttributes:!1,attributeNamePrefix:"@_"}).parse(Zs(n,"utf-8"))["jcr:root"]??{})[`@_${t}`];return typeof r=="string"?r.replace(/^\{[^}]+\}/,""):void 0}catch{return}}async function ta(e){return ea(e,"jcr:title")}function Jo(e){return ea(e,"sling:resourceSuperType")}function Cm(e){let t=ie.resolve(e);for(;t!==ie.dirname(t);){if(ie.basename(t)==="jcr_root")return t;t=ie.dirname(t)}return null}function na(e,t){let n=e.replace(/^\/mnt\/overlay\//,"/").replace(/^\/(apps|libs)\//,"").replace(/^\//,"").split("/").map(i=>i.replace(/^([a-z]+):/,"_$1_")).join("/"),o=[];for(let i of t)o.push(ie.join(i,"apps",n),ie.join(i,"libs",n),ie.join(i,n));return o}function Tm(e){let t=new Map,n=o=>{if(!t.has(o))try{let i=_t(Zs(o,"utf-8")).find(r=>oe(r)==="jcr:root");t.set(o,i?Q(i):null)}catch{t.set(o,null)}return t.get(o)??null};return o=>{if(!o||o.includes("${"))return null;for(let i of na(o,e)){let r=i.split(ie.sep);for(let a=r.length;a>1;a--){let c=r.slice(0,a).join(ie.sep),l=lt(ie.join(c,".content.xml"))?ie.join(c,".content.xml"):lt(`${c}.xml`)?`${c}.xml`:null;if(!l)continue;let d=n(l);for(let m of r.slice(a)){let p=d?.find(u=>oe(u)===m);d=p?[p]:null}if(d)return d;break}}return null}}async function oa(e,t=[]){let n=Cm(e),o=[...n?[n]:[],...t],i=Tm(o),r=e,a,c=null;for(let l=0;l<8;l++){let d=Pm(r),m=d?null:Em(r),p=d??m;if(p){let h=await Sm(p,"utf-8"),$=m&&Xs(h)?"classic":"touch",w=$==="classic"?Ys(h,{resolveInclude:i}):Ks(h,{resolveInclude:i});if(ct(w.fields)>0)return{...w,inheritedFrom:a,dialogKind:$};c??={...w,dialogKind:$}}let u=Jo(r),g=u?na(u,o).find(h=>lt(h)):void 0;if(!u||!g)break;r=g,a=u}return c}function ia(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)}
|
|
376
376
|
`}function ra(e,t){let o=t.some(i=>i.component==="container"&&i.multi)?` // This block was migrated from a classic AEM component with a multifield.
|
|
377
377
|
// Each child row is one repeated item - enhance them here.
|
|
378
378
|
[...block.children].forEach((row) => {
|
|
@@ -401,8 +401,8 @@ ${r.slice(c)}`,{js:r,changed:!0}}var la,ca,ma=v(()=>{"use strict";f();la="analyt
|
|
|
401
401
|
/* TODO: review selectors and scope them under .${e} (and port any LESS/SCSS). */
|
|
402
402
|
|
|
403
403
|
${t.trim()}
|
|
404
|
-
`}function fa(e,t=0){let n=[];for(let o of e){let i=" ".repeat(t);if(o.component==="tab")n.push(`${i}${_.blue("\u25B8")} ${o.label??o.name}`);else{let r=o.options?.length?` (${o.options.length} options)`:"",a=o.multi?" \xB7multi":"",c=o.label?`- ${o.label}`:"";n.push(`${i}${_.accent(o.component)}${a} ${o.name}${r} ${c}`),o.fields?.length&&n.push(...fa(o.fields,t+1))}}return n}async function Mm(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await s.logoOnceAnimated("Migrate component");let{input:o,confirm:i}=await Promise.resolve().then(()=>(K(),q)),r=!t.yes,a=e;if(!a&&r&&(a=await o({message:"Path to the classic component folder",validate:b=>qo(b.trim())||"Folder not found"})),!a){s.error("Provide the path to the classic component folder."),process.exitCode=1;return}a=Ae.resolve(a.trim());let c=(t.superRoot??"").split(",").map(b=>b.trim()).filter(Boolean).map(b=>Ae.resolve(b)),l=await oa(a,c);if(!l){let b=
|
|
405
|
-
`),s.info(j("Model updated",`blocks/${c}/_${c}.json`)),s.info(P("partials",m.map(b=>b.id).join(", "))),s.info(P("fields added",w.length?w.join(", "):"(none)")),y.length&&s.info(R("warn","skipped (exists)",y.join(", "))),s.info(""),s.info(
|
|
404
|
+
`}function fa(e,t=0){let n=[];for(let o of e){let i=" ".repeat(t);if(o.component==="tab")n.push(`${i}${_.blue("\u25B8")} ${o.label??o.name}`);else{let r=o.options?.length?` (${o.options.length} options)`:"",a=o.multi?" \xB7multi":"",c=o.label?`- ${o.label}`:"";n.push(`${i}${_.accent(o.component)}${a} ${o.name}${r} ${c}`),o.fields?.length&&n.push(...fa(o.fields,t+1))}}return n}async function Mm(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}await s.logoOnceAnimated("Migrate component");let{input:o,confirm:i}=await Promise.resolve().then(()=>(K(),q)),r=!t.yes,a=e;if(!a&&r&&(a=await o({message:"Path to the classic component folder",validate:b=>qo(b.trim())||"Folder not found"})),!a){s.error("Provide the path to the classic component folder."),process.exitCode=1;return}a=Ae.resolve(a.trim());let c=(t.superRoot??"").split(",").map(b=>b.trim()).filter(Boolean).map(b=>Ae.resolve(b)),l=await oa(a,c);if(!l){let b=Jo(a);b?(s.error(`No dialog here: this is a proxy of ${b}, and that component isn't under ${c.length?"the given --super-root":"this jcr_root"}.`),s.info(" Pass --super-root <jcr_root that contains it>, e.g. a checkout of adobe/aem-core-wcm-components (content/src/content/jcr_root).")):s.error(`No Touch UI dialog (_cq_dialog/.content.xml) found in ${a}.`),process.exitCode=1;return}if(ct(l.fields)===0){s.warn("Dialog found but no mappable fields were detected."),l.unmapped.length&&s.info(`Unmapped resourceTypes: ${l.unmapped.join(", ")}`),process.exitCode=1;return}let d=await ta(a)??Ae.basename(a),m=t.name&&_n(t.name)||_n(r?await o({message:"Block name",default:_n(d)}):d);l.dialogKind==="classic"&&s.info(` ${_.blue("\u21B3")} Classic UI dialog (dialog.xml) - mapped from its xtypes`),l.inheritedFrom&&s.info(` ${_.blue("\u21B3")} Dialog inherited from ${l.inheritedFrom} (proxy component; overlay changes not applied)`),s.info(j("Mapped fields",`${ct(l.fields)} from dialog`));for(let b of fa(l.fields))s.info(` ${b}`);if(l.unmapped.length&&(s.info(""),s.warn(`Skipped (unrecognised): ${l.unmapped.join(", ")}`)),l.datasourced.length&&s.warn(`Options come from a datasource, migrated as text (add static options if needed): ${l.datasourced.join(", ")}`),s.info(""),r&&!await i({message:`Generate block "${m}"?`,default:!0})){s.info("Cancelled.");return}let p=Ae.join(n,"blocks",m);if(qo(p)){s.error(`Block "${m}" already exists at blocks/${m}. Use --name to pick another.`),process.exitCode=1;return}let u=t.clientlib?Ae.resolve(t.clientlib.trim()):await zs(a),g=sa(m),h="empty - add styles from clientlib / rendered CSS",$=[];if(u&&qo(u)){let b=await Js(u);b.css.trim()&&(g=Om(m,b.css,b.files),h=`from clientlib (${b.files.length} file(s)) - review & scope`),$=b.preprocessed}await Nm(p,{recursive:!0}),await Ko(Ae.join(p,`${m}.js`),ra(m,l.fields)),await Ko(Ae.join(p,`${m}.css`),g),await Ko(Ae.join(p,`_${m}.json`),ia(m,d,l.fields)),s.info(j("Created"));let w=[`${m}.js`,`${m}.css`,`_${m}.json`],y=I(w);if(s.info(P(`${m}.js`,"decorator stub (port HTL logic)",y)),s.info(P(`${m}.css`,h,y)),s.info(P(`_${m}.json`,"Universal Editor model",y)),$.length&&(s.info(""),s.warn(`LESS/SCSS found (needs a build, not copied): ${$.join(", ")}`)),s.info(""),r&&await i({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:T}=await Promise.resolve().then(()=>(Ht(),Bt));await T(m,{})}s.info(z([`"${m}" migrated. Next: add CSS, then \`eds block preview ${m}\``]))}var _n,Xo=v(()=>{"use strict";f();N();qs();aa();Mn();V();H();_n=e=>e.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")});function se(e,t){return e?e+t.charAt(0).toUpperCase()+t.slice(1):t}var re,ga=v(()=>{"use strict";f();re={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 ei(e){return dt.find(t=>t.id===e)}var _m,Im,Um,Bm,ha,wa,Yo,ba,Qo,Zo,Hm,Gm,Wm,zm,Jm,dt,ti=v(()=>{"use strict";f();ga();_m=[{name:"H1",value:"h1"},{name:"H2",value:"h2"},{name:"H3",value:"h3"},{name:"H4",value:"h4"},{name:"H5",value:"h5"},{name:"H6",value:"h6"}],Im=[{name:"Same tab",value:"_self"},{name:"New tab",value:"_blank"}],Um=[{name:"Default",value:""},{name:"Primary",value:"primary"},{name:"Secondary",value:"secondary"}],Bm=[{name:"Highlight",value:"highlight"},{name:"Dark",value:"dark"},{name:"Centered",value:"centered"},{name:"Full width",value:"full-width"}],ha=(e="")=>[re.text(se(e,"title"),"Title"),re.select(se(e,"titleType"),"Heading level",_m,"h2")],wa=(e="")=>[re.text(se(e,"eyebrow"),"Eyebrow")],Yo=(e="")=>[re.reference(se(e,"image"),"Image"),re.text(se(e,"imageAlt"),"Alt text")],ba=(e="")=>[re.richtext(se(e,"text"),"Text")],Qo=(e="")=>[re.text(se(e,"linkText"),"Link text"),re.aemContent(se(e,"link"),"Link"),re.select(se(e,"linkTarget"),"Open in",Im,"_self")],Zo=(e="")=>[...Qo(e),re.select(se(e,"ctaStyle"),"Style",Um,"")],Hm=(e="")=>[re.container(se(e,"ctas")||"ctas","Buttons",Zo())],Gm=(e="")=>[re.multiselect(se(e,"classes"),"Styles",Bm)],Wm=(e="")=>[re.aemContent(se(e,"url"),"URL (video / embed)")],zm=(e="")=>[...Yo(e),...wa(e),...ha(e),...ba(e),...Zo(e)],Jm=(e="")=>[...Yo(e),re.text(se(e,"title"),"Title"),re.richtext(se(e,"description"),"Description"),...Qo(e)],dt=[{id:"heading",label:"Heading (title + level)",build:ha},{id:"eyebrow",label:"Eyebrow (kicker line)",build:wa},{id:"image",label:"Image (reference + alt)",build:Yo},{id:"richtext",label:"Rich text body",build:ba},{id:"link",label:"Link (text + url + target)",build:Qo},{id:"cta",label:"CTA (link + style)",build:Zo},{id:"cta-group",label:"CTA group (repeatable buttons)",build:Hm},{id:"classes",label:"Section styles (CSS modifiers)",build:Gm},{id:"embed",label:"Embed / video (URL)",build:Wm},{id:"teaser",label:"Teaser (image + eyebrow + title + text + CTA)",build:zm},{id:"card",label:"Card (image + title + description + link)",build:Jm}]});var ii={};U(ii,{modelAdd:()=>Vm});import{existsSync as ni}from"fs";import{readFile as qm,writeFile as Km}from"fs/promises";import oi from"path";async function Vm(e,t,n={}){let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Model - add partials"));let{select:i,checkbox:r}=await Promise.resolve().then(()=>(K(),q)),a=!n.yes,c=e;if(!c&&a){let{readdir:b}=await import("fs/promises"),T=oi.join(o,"blocks"),D=ni(T)?(await b(T,{withFileTypes:!0})).filter(O=>O.isDirectory()&&ni(oi.join(T,O.name,`_${O.name}.json`))).map(O=>O.name):[];if(D.length===0){s.error("No block with a _<name>.json model found. Create one with `eds block create`."),process.exitCode=1;return}c=await i({message:"Which block's model?",choices:D.map(O=>({name:O,value:O}))})}if(!c){s.error("Provide a block name."),process.exitCode=1;return}let l=oi.join(o,"blocks",c,`_${c}.json`);if(!ni(l)){s.error(`No model at blocks/${c}/_${c}.json. Create the block first.`),process.exitCode=1;return}let d=t;d.length===0&&a&&(d=await r({message:"Which partials to add?",choices:dt.map(b=>({name:b.label,value:b.id}))}));let m=d.map(b=>ei(b.trim())).filter(b=>!!b),p=d.filter(b=>!ei(b.trim()));if(p.length&&s.warn(`Unknown partial(s): ${p.join(", ")}. Available: ${dt.map(b=>b.id).join(", ")}`),m.length===0){s.info("Nothing to add.");return}let u;try{u=JSON.parse(await qm(l,"utf-8"))}catch{s.error(`Could not parse ${l}.`),process.exitCode=1;return}let g=Array.isArray(u.models)?u.models:[],h=g.find(b=>b.id===c)??g[0];if(!h){s.error("Model has no `models[]` entry to add fields to."),process.exitCode=1;return}h.fields=Array.isArray(h.fields)?h.fields:[];let $=new Set(h.fields.map(b=>b.name)),w=[],y=[];for(let b of m)for(let T of b.build()){if($.has(T.name)){y.push(T.name);continue}$.add(T.name),h.fields.push(T),w.push(T.name)}await Km(l,`${JSON.stringify(u,null,2)}
|
|
405
|
+
`),s.info(j("Model updated",`blocks/${c}/_${c}.json`)),s.info(P("partials",m.map(b=>b.id).join(", "))),s.info(P("fields added",w.length?w.join(", "):"(none)")),y.length&&s.info(R("warn","skipped (exists)",y.join(", "))),s.info(""),s.info(z([`${w.length} field(s) added to "${c}"`]))}var ri=v(()=>{"use strict";f();N();ti();V();H()});function va(e){return In.find(t=>t.id.toLowerCase()===e.toLowerCase())}function ka(e,t){if(e.includes(ya))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",i=n.index+n[0].length,r=`
|
|
406
406
|
// --- ${ya}: ${t.id}) ---
|
|
407
407
|
{
|
|
408
408
|
const root = ${o};
|
|
@@ -491,7 +491,7 @@ ${t.trim()}
|
|
|
491
491
|
position: i + 1,
|
|
492
492
|
text: li.textContent?.trim(),
|
|
493
493
|
})),
|
|
494
|
-
}`}]});var si={};U(si,{schemaBlock:()=>tp});import{existsSync as Xm}from"fs";import{readFile as Ym,writeFile as Qm}from"fs/promises";import Zm from"path";import ep from"chalk";async function tp(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Schema - JSON-LD"));let o=Zm.join(n,"blocks",e,`${e}.js`);if(!Xm(o)){s.error(`Block "${e}" not found (no blocks/${e}/${e}.js).`),process.exitCode=1;return}let i=t.type;if(!i&&!t.yes){let{select:c}=await Promise.resolve().then(()=>(K(),q));i=await c({message:"Which schema.org type?",choices:In.map(l=>({name:`${l.id} - ${l.label}`,value:l.id}))})}let r=i?va(i):void 0;if(!r){s.error(`Unknown schema type "${i}". Options: ${In.map(c=>c.id).join(", ")}`),process.exitCode=1;return}let a=ka(await Ym(o,"utf-8"),r);if(!a.changed){s.warn(`Not added: ${a.reason}.`);return}await Qm(o,a.js),s.info(j("JSON-LD added")),s.info(P(`blocks/${e}/${e}.js`,`${r.id} (${r.label})`)),s.info(""),s.info(ep.dim(" Review the generated object - some fields are heuristic or TODO. Validate at search.google.com/test/rich-results."))}var ai=v(()=>{"use strict";f();N();V();xa();H()});function op(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 $a(e){return op(e,np)!==null}function Sa(e){return Array.isArray(e)?e.map(t=>t&&typeof t=="object"?t.id:void 0).filter(t=>typeof t=="string"):[]}function ja(e){let t=!!e.configPresent["component-definition.json"]&&!!e.configPresent["component-models.json"],n=new Set(e.modelIds),o=e.blocks.map(i=>{let r=i.hasModelFile||n.has(i.name);return{name:i.name,editable:r,reason:r?void 0:"no UE model (_<name>.json or component-models entry)"}});return{isUeProject:t,blocks:o}}var ci,np,Pa=v(()=>{"use strict";f();ci=["component-definition.json","component-models.json","component-filters.json"],np="urn:adobe:aue:system:aemconnection"});var
|
|
494
|
+
}`}]});var si={};U(si,{schemaBlock:()=>tp});import{existsSync as Xm}from"fs";import{readFile as Ym,writeFile as Qm}from"fs/promises";import Zm from"path";import ep from"chalk";async function tp(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Schema - JSON-LD"));let o=Zm.join(n,"blocks",e,`${e}.js`);if(!Xm(o)){s.error(`Block "${e}" not found (no blocks/${e}/${e}.js).`),process.exitCode=1;return}let i=t.type;if(!i&&!t.yes){let{select:c}=await Promise.resolve().then(()=>(K(),q));i=await c({message:"Which schema.org type?",choices:In.map(l=>({name:`${l.id} - ${l.label}`,value:l.id}))})}let r=i?va(i):void 0;if(!r){s.error(`Unknown schema type "${i}". Options: ${In.map(c=>c.id).join(", ")}`),process.exitCode=1;return}let a=ka(await Ym(o,"utf-8"),r);if(!a.changed){s.warn(`Not added: ${a.reason}.`);return}await Qm(o,a.js),s.info(j("JSON-LD added")),s.info(P(`blocks/${e}/${e}.js`,`${r.id} (${r.label})`)),s.info(""),s.info(ep.dim(" Review the generated object - some fields are heuristic or TODO. Validate at search.google.com/test/rich-results."))}var ai=v(()=>{"use strict";f();N();V();xa();H()});function op(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 $a(e){return op(e,np)!==null}function Sa(e){return Array.isArray(e)?e.map(t=>t&&typeof t=="object"?t.id:void 0).filter(t=>typeof t=="string"):[]}function ja(e){let t=!!e.configPresent["component-definition.json"]&&!!e.configPresent["component-models.json"],n=new Set(e.modelIds),o=e.blocks.map(i=>{let r=i.hasModelFile||n.has(i.name);return{name:i.name,editable:r,reason:r?void 0:"no UE model (_<name>.json or component-models entry)"}});return{isUeProject:t,blocks:o}}var ci,np,Pa=v(()=>{"use strict";f();ci=["component-definition.json","component-models.json","component-filters.json"],np="urn:adobe:aue:system:aemconnection"});var zt={};U(zt,{ueCheck:()=>lp,ueOpen:()=>dp});import{existsSync as Wt}from"fs";import{readFile as Ea,readdir as ip}from"fs/promises";import Gt from"path";import Un from"chalk";async function rp(e){if(!Wt(e))return null;try{return JSON.parse(await Ea(e,"utf-8"))}catch{return null}}async function sp(e){let t=Gt.join(e,"blocks");return Wt(t)?(await ip(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>({name:o.name,hasModelFile:Wt(Gt.join(t,o.name,`_${o.name}.json`))})):[]}async function ap(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 cp(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 lp(){let e=E();if(!e){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Universal Editor - readiness"));let t={};for(let p of ci)t[p]=Wt(Gt.join(e,p));let n=await rp(Gt.join(e,"component-models.json")),o=await sp(e),{isUeProject:i,blocks:r}=ja({configPresent:t,blocks:o,modelIds:Sa(n)});s.info(j("Universal Editor config"));let a=[...ci],c=I(a);for(let p of a)s.info(R(t[p]?"pass":"fail",p,void 0,c));if(!i){s.info(""),s.warn("This doesn't look like a Universal Editor (crosswalk) project - run `eds scaffold ue` first."),process.exitCode=1;return}let l=Gt.join(e,"head.html");if(Wt(l)){let p=$a(await Ea(l,"utf-8"));s.info(R(p?"pass":"info","head.html",p?"aemconnection present":"no aemconnection (fine for cloud author)"))}if(s.info(j("Blocks",`${r.length} found`)),r.length===0)s.info(Un.dim(" No blocks yet."));else{let p=I(r.map(u=>u.name));for(let u of r)s.info(R(u.editable?"pass":"warn",u.name,u.reason,p))}let d=r.filter(p=>p.editable).length,m=r.length-d;s.info(""),s.info(je({pass:d,warn:m})),s.info(Un.dim(" Open a page in the editor with `eds ue open <path>`."))}async function dp(e,t={}){let n=E()??process.cwd(),o=e??t.path??"/",i=t.url;if(!i){let a=await cp(n),c=a?ot(a):null;if(!c){s.error("Couldn't determine the preview host from git."),s.info(Un.dim(" Pass it explicitly: `eds ue open <path> --url main--<repo>--<owner>.aem.page`")),process.exitCode=1;return}i=it(c.owner,c.repo,t.ref??"main")}let r=Vr({host:i,path:o,org:t.org});s.info(j("Universal Editor")),s.info(P("page",`${i}${o.startsWith("/")?"":"/"}${o}`)),s.info(P("open",r)),t.open!==!1?await ap(r):s.info(Un.dim(" (use without --no-open to launch the browser)"))}var Jt=v(()=>{"use strict";f();N();V();Pa();En();H()});var di={};U(di,{createBlock:()=>fp,ueModelFor:()=>Ta});import{existsSync as mp}from"fs";import{mkdir as pp,writeFile as li}from"fs/promises";import qt from"path";import Ca from"chalk";function up(e){return e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function Ta(e){let t=up(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)}
|
|
495
495
|
`}async function fp(e,t={}){if(!He.test(e)){s.error(`Invalid block name "${e}". Use kebab-case (e.g., "hero-banner", "card-list").`),process.exitCode=1;return}let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}let o=qt.join(n,"blocks",e);if(mp(o)){s.error(`Block "${e}" already exists at ${o}`),process.exitCode=1;return}await pp(o,{recursive:!0});let i=`export default function decorate(block) {
|
|
496
496
|
// TODO: implement ${e} block
|
|
497
497
|
}
|
|
@@ -519,7 +519,7 @@ Write \`${t}/${e}.js\`, \`${t}/${e}.css\`, the Universal Editor model \`${t}/_${
|
|
|
519
519
|
${r.trimEnd()}
|
|
520
520
|
=== END FILE ===`)}return o.join(`
|
|
521
521
|
|
|
522
|
-
`)}var Bn,Kt,Re,wi,hi,jp,Fa,Vt=v(()=>{"use strict";f();Bn=["ollama","omlx","local"],Kt={ollama:"http://127.0.0.1:11434",omlx:"http://127.0.0.1:8000/v1",local:"http://127.0.0.1:8080/v1"},Re={ollama:"Ollama",omlx:"oMLX",local:"local OpenAI-compatible server"},wi=32768;hi=e=>e.replace(/\/+$/,"");jp=/^=+\s*FILE:\s*(.+?)\s*=+\s*$/,Fa=/^=+\s*END FILE\s*=+\s*$/});import{existsSync as Hn}from"fs";import{readFile as Ep}from"fs/promises";import{homedir as mt}from"os";import pt from"path";async function yi(e){let{execaCommand:t}=await import("execa");try{return(await t(`which ${e}`)).stdout.trim()||void 0}catch{return}}function Ha(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 i=Ha(o);if(i)return i}}async function vi(e){for(let t of e)try{if(!Hn(t))continue;let n=await Ep(t,"utf-8");try{let o=Ha(JSON.parse(n));if(o)return o}catch{}if(n.toLowerCase().includes("figma"))return"figma"}catch{}}async function ki(e){let t=E()??void 0,n=(await ce(t)).local,o=n?.baseUrl??Kt[e],i=await La(e,o);if(!i)return;let r=n?.model??Na(i);if(!r){s.warn(`${Re[e]} at ${o} has no models - pull one first (e.g. \`ollama pull qwen2.5-coder:14b\`).`);return}return{type:e,path:o,baseUrl:o,model:r,hasFigmaMcp:!1}}async function Gn(e){if(e&&ye(e)){let t=await ki(e);if(t)return t;s.warn(`${Re[e]} isn't reachable - is it running?`);return}if(e){let t=bi.find(n=>n.type===e);if(t){let n=await yi(t.binary);if(n){let o=await vi(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Hn(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}s.warn(`Preferred agent "${e}" not found in PATH`)}}for(let t of bi){let n=await yi(t.binary);if(n){let o=await vi(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Hn(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}}for(let t of Bn.filter(n=>n!=="local")){let n=await ki(t);if(n)return n}}async function Wn(){let e=[];for(let t of bi){let n=await yi(t.binary);if(n){let o=await vi(t.mcpConfigPaths);e.push({type:t.type,path:n,configDir:Hn(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o})}}for(let t of Bn.filter(n=>n!=="local")){let n=await ki(t);n&&e.push(n)}return e}var bi,
|
|
522
|
+
`)}var Bn,Kt,Re,wi,hi,jp,Fa,Vt=v(()=>{"use strict";f();Bn=["ollama","omlx","local"],Kt={ollama:"http://127.0.0.1:11434",omlx:"http://127.0.0.1:8000/v1",local:"http://127.0.0.1:8080/v1"},Re={ollama:"Ollama",omlx:"oMLX",local:"local OpenAI-compatible server"},wi=32768;hi=e=>e.replace(/\/+$/,"");jp=/^=+\s*FILE:\s*(.+?)\s*=+\s*$/,Fa=/^=+\s*END FILE\s*=+\s*$/});import{existsSync as Hn}from"fs";import{readFile as Ep}from"fs/promises";import{homedir as mt}from"os";import pt from"path";async function yi(e){let{execaCommand:t}=await import("execa");try{return(await t(`which ${e}`)).stdout.trim()||void 0}catch{return}}function Ha(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 i=Ha(o);if(i)return i}}async function vi(e){for(let t of e)try{if(!Hn(t))continue;let n=await Ep(t,"utf-8");try{let o=Ha(JSON.parse(n));if(o)return o}catch{}if(n.toLowerCase().includes("figma"))return"figma"}catch{}}async function ki(e){let t=E()??void 0,n=(await ce(t)).local,o=n?.baseUrl??Kt[e],i=await La(e,o);if(!i)return;let r=n?.model??Na(i);if(!r){s.warn(`${Re[e]} at ${o} has no models - pull one first (e.g. \`ollama pull qwen2.5-coder:14b\`).`);return}return{type:e,path:o,baseUrl:o,model:r,hasFigmaMcp:!1}}async function Gn(e){if(e&&ye(e)){let t=await ki(e);if(t)return t;s.warn(`${Re[e]} isn't reachable - is it running?`);return}if(e){let t=bi.find(n=>n.type===e);if(t){let n=await yi(t.binary);if(n){let o=await vi(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Hn(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}s.warn(`Preferred agent "${e}" not found in PATH`)}}for(let t of bi){let n=await yi(t.binary);if(n){let o=await vi(t.mcpConfigPaths);return{type:t.type,path:n,configDir:Hn(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o}}}for(let t of Bn.filter(n=>n!=="local")){let n=await ki(t);if(n)return n}}async function Wn(){let e=[];for(let t of bi){let n=await yi(t.binary);if(n){let o=await vi(t.mcpConfigPaths);e.push({type:t.type,path:n,configDir:Hn(t.configDir)?t.configDir:void 0,hasFigmaMcp:!!o,figmaMcpServerName:o})}}for(let t of Bn.filter(n=>n!=="local")){let n=await ki(t);n&&e.push(n)}return e}var bi,zn=v(()=>{"use strict";f();fe();N();V();Vt();bi=[{type:"claude",binary:"claude",configDir:pt.join(mt(),".claude"),mcpConfigPaths:[pt.join(mt(),".claude","plugins.json"),pt.join(mt(),".claude.json")]},{type:"cursor",binary:"cursor",configDir:pt.join(mt(),".cursor"),mcpConfigPaths:[pt.join(mt(),".cursor","mcp.json")]},{type:"codex",binary:"codex",configDir:pt.join(mt(),".codex"),mcpConfigPaths:[]}]});import{mkdir as za,readFile as xi,writeFile as Ja}from"fs/promises";import{tmpdir as Cp}from"os";import ge from"path";import Tp from"readline";import{stripVTControlCharacters as Ap}from"util";import ee from"chalk";async function Xt(e,t){let n=t?ge.join(t,"tmp"):Cp(),o=ge.join(n,"eds-cli");await za(o,{recursive:!0});let i=`from-design-${Date.now()}.md`,r=ge.join(o,i);return await Ja(r,e,"utf-8"),r}function Ga(e,t){return Buffer.byteLength(e,"utf-8")<=Rp?e:`Your full task is in the file ${t}. Read that whole file first and follow its instructions exactly - it replaces this message.`}async function ut(e,t,n,o,i){let{execa:r}=await import("execa"),a=await xi(t,"utf-8");try{if(ye(e.type))return await Dp(e,a,n,o,i);switch(e.type){case"claude":{s.info(`Running Claude Code ${ee.dim("- live log:")}`);let c=[...e.figmaMcpServerName?[e.figmaMcpServerName]:[],"figma-sse","figma-desktop","figma","Figma","plugin_figma_figma"],l=[...new Set(c.map(p=>`mcp__${p}`)),"Edit","Write","Read"].join(","),m=r("claude",["-p","--model",o??"haiku","--output-format","stream-json","--verbose","--allowedTools",l],{cwd:n,buffer:!1,input:a,stdio:["pipe","pipe","inherit"]});await Lp(m,n);break}case"cursor":{s.info("Running Cursor agent..."),await r("cursor",["--prompt",Ga(a,t)],{cwd:n,stdio:B.enabled?["inherit",2,"inherit"]:"inherit"});break}case"codex":{s.info("Running Codex..."),await r("codex",[Ga(a,t)],{cwd:n,stdio:B.enabled?["inherit",2,"inherit"]:"inherit"});break}}return!0}catch(c){let l=(c instanceof Error?c.message:String(c)).split(`
|
|
523
523
|
`)[0].slice(0,300);return s.error(`Agent ${e.type} failed: ${l}`),!1}}async function Dp(e,t,n,o,i){let r=e.type,a=i?.blockName;if(!a)throw new Error("A local model needs the block name to save its files.");let c=o??e.model;if(!c)throw new Error(`No model chosen for ${Re[r]} - set local.model in config.`);let l=t,d=[];if(i?.designFile){let F=ge.resolve(n,i.designFile),xe=ge.extname(F).toLowerCase();xe===".svg"?l+=`
|
|
524
524
|
|
|
525
525
|
## The design (${i.designFile})
|
|
@@ -533,15 +533,15 @@ The design (${i.designFile}) is attached as an image. A model without vision can
|
|
|
533
533
|
## The block as it is now
|
|
534
534
|
Change these files; reply with every file you change, complete.
|
|
535
535
|
|
|
536
|
-
${await Ba(n,a)}`),l+=_a(a);let m=i?.contextTokens??wi,p=Oa(l)+d.length*1500+6e3;p>m&&s.warn(`The prompt needs about ${p} tokens of context but ${m} are configured - raise local.contextTokens${r==="ollama"?"":" and the server's own context length"}, or use a smaller design.`);let u=(await import("ora")).default,g=Date.now(),h=()=>`${Math.round((Date.now()-g)/1e3)}s`;s.info(`Running ${Re[r]} ${ee.dim(`${c} \xB7 ${e.baseUrl}`)}`);let $=u({text:`waiting for the model ${ee.dim(h())}`,color:"yellow"}).start(),w=0,y=setInterval(()=>{$.text=`${w?`writing \xB7 ${w} chars`:"reading the prompt"} ${ee.dim(h())}`},300),b;try{b=await Ma({type:r,baseUrl:e.baseUrl??Kt[r],model:c,prompt:l,images:d,apiKey:i?.apiKey,contextTokens:Math.max(m,r==="ollama"?p:0),onToken:F=>{w+=F.length}})}finally{clearInterval(y),$.stop()}let T=ge.join(n,"tmp","eds-cli",`local-reply-${Date.now()}.md`);await
|
|
536
|
+
${await Ba(n,a)}`),l+=_a(a);let m=i?.contextTokens??wi,p=Oa(l)+d.length*1500+6e3;p>m&&s.warn(`The prompt needs about ${p} tokens of context but ${m} are configured - raise local.contextTokens${r==="ollama"?"":" and the server's own context length"}, or use a smaller design.`);let u=(await import("ora")).default,g=Date.now(),h=()=>`${Math.round((Date.now()-g)/1e3)}s`;s.info(`Running ${Re[r]} ${ee.dim(`${c} \xB7 ${e.baseUrl}`)}`);let $=u({text:`waiting for the model ${ee.dim(h())}`,color:"yellow"}).start(),w=0,y=setInterval(()=>{$.text=`${w?`writing \xB7 ${w} chars`:"reading the prompt"} ${ee.dim(h())}`},300),b;try{b=await Ma({type:r,baseUrl:e.baseUrl??Kt[r],model:c,prompt:l,images:d,apiKey:i?.apiKey,contextTokens:Math.max(m,r==="ollama"?p:0),onToken:F=>{w+=F.length}})}finally{clearInterval(y),$.stop()}let T=ge.join(n,"tmp","eds-cli",`local-reply-${Date.now()}.md`);await za(ge.dirname(T),{recursive:!0}),await Ja(T,b.text,"utf-8");let D=Ia(b.text),{written:O,rejected:ne}=await Ua(n,a,D),Ue=[h(),b.outputTokens?`${b.outputTokens} tokens out`:`${b.text.length} chars`].join(" \xB7 ");for(let F of O)s.info(` ${_.accent("\u270E")} ${ee.cyan(F)}`);for(let F of ne)s.warn(`Ignored a file outside blocks/${a}/: ${F}`);return O.length?s.info(`${_.accent("\u2713")} ${_.accent("model finished")} ${ee.dim(Ue)}`):s.warn(`The model replied but no files could be read from it (${Ue}). Raw reply: ${ge.relative(n,T)}`),!0}function Fp(e){return e.includes("figma")?e.split("__").pop()??e:e.toLowerCase()}async function Lp(e,t){let n=(await import("ora")).default,o=Date.now(),i=()=>`${Math.round((Date.now()-o)/1e3)}s`,r=n({text:`thinking ${ee.dim(i())}`,color:"yellow"}).start(),a="thinking",c=setInterval(()=>{r.text=`${a} ${ee.dim(i())}`},300),l=new Map,d=p=>{r.stop(),s.info(` ${p}`),r.start()},m;try{if(e.stdout){let p=Tp.createInterface({input:e.stdout});for await(let u of p){let g=u.trim();if(!g)continue;let h;try{h=JSON.parse(g)}catch{continue}let $=Array.isArray(h.message?.content)?h.message.content:[];if(h.type==="assistant"){for(let w of $)if(w.type==="text"&&"text"in w){let y=w.text.trim().split(`
|
|
537
537
|
`)[0].slice(0,100);y&&d(ee.dim(y))}else if(w.type==="tool_use"&&"name"in w){let y="id"in w&&w.id?w.id:`${Math.random()}`;l.set(y,{tool:w.name,label:Np(w.name,w.input,t),start:Date.now()}),a=Fp(w.name)}}else if(h.type==="user"){for(let w of $)if(w.type==="tool_result"&&"tool_use_id"in w&&w.tool_use_id){let y=l.get(w.tool_use_id);if(y){let b=`${((Date.now()-y.start)/1e3).toFixed(1)}s`,T="is_error"in w&&w.is_error?` ${ee.red("failed")}`:"";d(`${y.label} ${ee.dim(b)}${T}`),B.emit({type:"agent",tool:y.tool,label:Ap(y.label),durationMs:Date.now()-y.start,...T?{failed:!0}:{}}),l.delete(w.tool_use_id)}}}else if(h.type==="result"){let w=typeof h.duration_ms=="number"?`${(h.duration_ms/1e3).toFixed(1)}s`:"",y=typeof h.total_cost_usd=="number"?`$${h.total_cost_usd.toFixed(3)}`:"";m=[w,y].filter(Boolean).join(" \xB7 ")||"done",B.emit({type:"agent-result",...typeof h.duration_ms=="number"?{durationMs:h.duration_ms}:{},...typeof h.total_cost_usd=="number"?{costUsd:h.total_cost_usd}:{}})}}}for(let p of l.values())d(`${p.label} ${ee.dim("\u2026")}`);clearInterval(c),m?r.succeed(`${_.accent("agent finished")} ${ee.dim(m)}`):r.stop()}catch(p){throw clearInterval(c),r.stop(),p}await e}function Np(e,t,n){let o=i=>{let r=t?.[i];return typeof r!="string"?"":r.startsWith(n)?ge.relative(n,r):ge.basename(r)};if(e.includes("figma")){let i=e.split("__").pop()??e;return`${Y.figma} ${ee.bold(i)} ${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 i=typeof t?.command=="string"?t.command.split(`
|
|
538
|
-
`)[0].slice(0,70):"";return ee.dim(`$ ${i}`)}default:return`${_.blue("\u2192")} ${e}`}}var Rp,Wa,$i=v(()=>{"use strict";f();Se();N();H();Vt();Rp=96*1024;Wa={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp"}});import{existsSync as
|
|
539
|
-
`)}async function Ya(e){let t=Va(e);if(!
|
|
538
|
+
`)[0].slice(0,70):"";return ee.dim(`$ ${i}`)}default:return`${_.blue("\u2192")} ${e}`}}var Rp,Wa,$i=v(()=>{"use strict";f();Se();N();H();Vt();Rp=96*1024;Wa={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp"}});import{existsSync as Jn}from"fs";import{cp as Si,mkdir as ji,readFile as Op,readdir as Ka,rename as qa,rm as Yt,writeFile as Mp}from"fs/promises";import De from"path";async function ft(e,t){let n=Xa(e,t);return Jn(n)?JSON.parse(await Op(n,"utf-8")):null}async function Ei(e,t){await ji(Qt(e,t.name),{recursive:!0}),await Mp(Xa(e,t.name),`${JSON.stringify(t,null,2)}
|
|
539
|
+
`)}async function Ya(e){let t=Va(e);if(!Jn(t))return[];let n=[];for(let o of await Ka(t,{withFileTypes:!0})){if(!o.isDirectory())continue;let i=await ft(e,o.name);i&&n.push(i)}return n.sort((o,i)=>o.name.localeCompare(i.name))}async function Qa(e,t,n){let o=Pi(e,t),i=De.join(Qt(e,t),".stash");await Yt(i,{recursive:!0,force:!0});let r=Jn(o);return r&&(await ji(De.dirname(i),{recursive:!0}),await qa(o,i)),n!==void 0&&await Si(Fe(e,t,n),o,{recursive:!0}),async()=>{await Yt(o,{recursive:!0,force:!0}),r&&await qa(i,o)}}async function Za(e,t,n){let o=await ft(e,t)??{name:t,status:"open",source:n.source,versions:[]},i=(o.versions.at(-1)?.version??0)+1,r=Fe(e,t,i);await Yt(r,{recursive:!0,force:!0}),await ji(De.dirname(r),{recursive:!0}),await Si(Pi(e,t),r,{recursive:!0});let a=(await Ka(r)).sort();return o.status="open",o.versions.push({version:i,createdAt:new Date().toISOString(),...n.feedback?{feedback:n.feedback}:{},ok:n.ok,files:a}),await Ei(e,o),i}async function ec(e,t,n){let o=await ft(e,t);if(!o)throw new Error(`No draft "${t}".`);let i=n??o.versions.at(-1)?.version;if(!i||!o.versions.some(a=>a.version===i))throw new Error(`Draft "${t}" has no version ${n??""}.`.trim());let r=Pi(e,t);return await Yt(r,{recursive:!0,force:!0}),await Si(Fe(e,t,i),r,{recursive:!0}),o.status="accepted",o.accepted={version:i,at:new Date().toISOString()},await Ei(e,o),{draft:o,version:i}}async function tc(e,t,n){let o=await ft(e,t);o?.accepted&&(o.accepted.commit=n,await Ei(e,o))}async function nc(e,t){let n=Qt(e,t);return Jn(n)?(await Yt(n,{recursive:!0,force:!0}),!0):!1}function oc(e,t){let n=e.source.designRef?` from ${e.source.designRef}`:"",o=e.versions.filter(i=>i.version<=t).map(i=>`- v${i.version}: ${i.feedback?`"${i.feedback}"`:"first version"}`);return`feat(blocks): ${e.name}${n}
|
|
540
540
|
|
|
541
541
|
Accepted draft v${t} after ${o.length===1?"one version":`${o.length} versions`}:
|
|
542
542
|
${o.join(`
|
|
543
543
|
`)}
|
|
544
|
-
`}var Va,Qt,Xa,Fe,Pi,Ci=v(()=>{"use strict";f();Va=e=>De.join(e,"tmp","eds-cli","drafts"),Qt=(e,t)=>De.join(Va(e),t),Xa=(e,t)=>De.join(Qt(e,t),"draft.json"),Fe=(e,t,n)=>De.join(Qt(e,t),`v${n}`),Pi=(e,t)=>De.join(e,"blocks",t)});function ic(e){return e<=480?`${e} mobile`:e<=1024?`${e} tablet`:`${e} desktop`}function _p(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:ic(n),source:t})):[]}function rc(e,t){let n=_p(e,"figma");return n.length?n:Ip(t)}function Ip(e){if(!Array.isArray(e))return[];let t=new Set,n=[];for(let o of e){let i=Number(o?.width);if(!Number.isFinite(i)||i<=0||t.has(i))continue;t.add(i);let r=o.source,a=r==="figma"||r==="scrape"?r:"default";n.push({width:i,label:ic(i),source:a})}return n}var sc=v(()=>{"use strict";f()});import{existsSync as Up}from"fs";import{createRequire as Bp}from"module";import Hp from"path";import{pathToFileURL as ac}from"url";async function cc(e){try{return(await import("playwright")).chromium}catch{}let t=[e,process.cwd()].filter(n=>!!n);if(t.length)try{let o=Bp(ac(Hp.join(t[0],"package.json")).href).resolve("playwright",{paths:t});return(await import(ac(o).href)).chromium}catch{}throw new Error("Scraping needs Playwright. Install it in your project (`npm i -D playwright`) or globally (`npm i -g playwright`), then `npx playwright install chromium`.")}async function lc(e){let t=e.width??1440,n=await cc(e.projectRoot),o;try{o=await n.launch({headless:!0})}catch(i){let r=i instanceof Error?i.message:String(i);throw/Executable doesn't exist|install/i.test(r)?new Error("Chromium isn't installed for Playwright. Run `npx playwright install chromium`."):i}try{let i=e.storageStatePath&&Up(e.storageStatePath),a=await(await o.newContext({viewport:{width:t,height:900},deviceScaleFactor:1,...i?{storageState:e.storageStatePath}:{}})).newPage();await a.goto(e.url,{waitUntil:"networkidle",timeout:45e3}),await a.waitForTimeout(700);let c=await a.evaluate(Gp,{maxNodes:320,maxDepth:14,textCap:200}),l={source:`scrape:${e.provider}`,url:e.url,viewport:t,authenticated:!!i,title:c.title,root:c.root,nodeCount:c.nodeCount,truncated:c.truncated};return JSON.stringify(l,null,2)}finally{await o.close()}}async function dc(e){let n=await(await cc(e.projectRoot)).launch({headless:!1});try{let o=await n.newContext();await(await o.newPage()).goto(e.loginUrl,{waitUntil:"domcontentloaded",timeout:6e4}),await e.waitForUser(),await o.storageState({path:e.statePath})}finally{await n.close()}}function Gp(e){let t=new Set(["SCRIPT","STYLE","NOSCRIPT","LINK","META","HEAD","BR","TEMPLATE"]),n=0,o=!1,i=d=>!d||d==="none"||d==="normal"||d==="auto"||d==="0px"||d==="rgba(0, 0, 0, 0)"||d==="transparent";function r(d){let m="";for(let p of Array.from(d.childNodes))p.nodeType===3&&(m+=p.textContent??"");return m=m.replace(/\s+/g," ").trim(),m.length>e.textCap?`${m.slice(0,e.textCap)}\u2026`:m}function a(d){let m=getComputedStyle(d),p={},u=(h,$)=>{i($)||(p[h]=$)};u("display",m.display),(m.display.includes("flex")||m.display.includes("grid"))&&(u("flexDirection",m.flexDirection),u("justifyContent",m.justifyContent),u("alignItems",m.alignItems),u("gap",m.gap)),u("padding",m.padding),u("margin",m.margin),u("color",m.color),u("background",m.backgroundColor),m.backgroundImage&&m.backgroundImage!=="none"&&(p.backgroundImage=m.backgroundImage.slice(0,160)),u("fontFamily",m.fontFamily),u("fontSize",m.fontSize),u("fontWeight",m.fontWeight),u("lineHeight",m.lineHeight),u("letterSpacing",m.letterSpacing),u("textAlign",m.textAlign);let g=h=>h&&!h.startsWith("0px")&&!h.includes(" none")?h:"";if(m.border)g(m.border)&&(p.border=m.border);else for(let h of["borderTop","borderRight","borderBottom","borderLeft"])g(m[h])&&(p[h]=m[h]);return u("borderRadius",m.borderRadius),u("boxShadow",m.boxShadow),m.opacity&&m.opacity!=="1"&&(p.opacity=m.opacity),m.position&&m.position!=="static"&&(p.position=m.position),p}function c(d,m,p=""){if(n>=e.maxNodes)return o=!0,null;if(t.has(d.tagName))return null;let u=d.getBoundingClientRect(),g=getComputedStyle(d);if(g.display==="none"||g.visibility==="hidden"||g.opacity==="0"||u.width<1||u.height<1)return null;n++;let $={tag:d.tagName.toLowerCase(),rect:{x:Math.round(u.x),y:Math.round(u.y),w:Math.round(u.width),h:Math.round(u.height)}},w=(d.getAttribute("class")||"").trim().split(/\s+/).filter(Boolean).slice(0,3);w.length&&($.class=w.join(" "));let y=a(d);!y.background&&p&&u.width>=window.innerWidth*.9&&(y.inheritedBackground=p),Object.keys(y).length&&($.style=y);let b=y.background??p;if(d.tagName==="IMG"){let D=d;$.img={src:(D.currentSrc||D.src||"").slice(0,200),alt:D.alt||"",w:D.naturalWidth,h:D.naturalHeight}}let T=r(d);if(T&&($.text=T),m<e.maxDepth){let D=[];for(let O of Array.from(d.children)){let ne=c(O,m+1,b);ne&&D.push(ne)}D.length&&($.children=D)}return $}let l=c(document.body,0);return{title:document.title,root:l,nodeCount:n,truncated:o}}var Ti=v(()=>{"use strict";f()});import{mkdir as mc,readFile as Wp,rm as pc,stat as Jp,writeFile as zp}from"fs/promises";import fc from"path";function qn(e){return fc.join(e,"tmp","eds-cli","figma-rest-calls.json")}async function Kp(e,t,n){let o=`${e}.lock`;for(await mc(fc.dirname(e),{recursive:!0});;)try{await mc(o);break}catch{await Jp(o).then(r=>t()-r.mtimeMs,()=>0)>qp?await pc(o,{recursive:!0,force:!0}):await new Promise(r=>setTimeout(r,25))}try{return await n()}finally{await pc(o,{recursive:!0,force:!0})}}async function Vp(e){try{let t=JSON.parse(await Wp(e,"utf-8"));return Array.isArray(t)?t.filter(n=>typeof n=="number"):[]}catch{return[]}}async function Kn(e){let t=Math.max(1,e.perMinute??Ai),n=e.now??Date.now,o=e.sleep??(i=>new Promise(r=>setTimeout(r,i)));for(;;){let i=await Kp(e.logPath,n,async()=>{let r=n(),a=(await Vp(e.logPath)).filter(c=>r-c<uc);return a.length<t?(a.push(r),await zp(e.logPath,JSON.stringify(a)),0):Math.min(...a)+uc-r+50});if(i<=0)return;e.onWait?.(i),await o(i)}}var Ai,uc,qp,Vn=v(()=>{"use strict";f();Ai=10,uc=6e4,qp=1e4});function Xp(e){let t=Math.max(0,Math.round(e));if(t<60)return`${t} s`;if(t<3600)return`${Math.round(t/60)} min`;if(t<86400){let o=Math.round(t%3600/60);return`${Math.floor(t/3600)} h${o?` ${o} min`:""}`}let n=Math.round(t%86400/3600);return`${Math.floor(t/86400)} d${n?` ${n} h`:""}`}async function Fi(e,t,n,o=!1){await n?.();let i=await fetch(e,{headers:{"X-Figma-Token":t}});if(i.status!==429)return i;let r=l=>i.headers.get(l)??void 0,a=r("retry-after"),c=a!==void 0&&/^\d+$/.test(a)?Number(a):void 0;if(!o&&c!==void 0&&c<=60)return await Yp.sleep(c*1e3),Fi(e,t,n,!0);throw new Zt(c,r("x-figma-plan-tier"),r("x-figma-rate-limit-type"),r("x-figma-upgrade-link"))}async function wc(e){let{fileKey:t,nodeId:n,token:o}=e,i=n?`${Ri}/files/${t}/nodes?ids=${encodeURIComponent(n)}`:`${Ri}/files/${t}`,r=await Fi(i,o,e.pace);if(!r.ok){let a=await r.text().catch(()=>""),c=r.status===403?" (check the token scope: it needs file_content:read, and access to this file)":r.status===404?" (file or node not found \u2014 check the URL)":"";throw new Error(`Figma REST ${r.status} ${r.statusText}${c}${a?` \u2014 ${a.slice(0,200)}`:""}`)}return r.json()}async function bc(e){let{fileKey:t,nodeId:n,token:o,scale:i=1}=e;if(!n)throw new Error("A node id is required to render a Figma image.");let r=`${Ri}/images/${t}?ids=${encodeURIComponent(n)}&format=png&scale=${i}`,a=await Fi(r,o,e.pace);if(!a.ok){let m=await a.text().catch(()=>"");throw new Error(`Figma images ${a.status} ${a.statusText}${m?` \u2014 ${m.slice(0,200)}`:""}`)}let c=await a.json();if(c.err)throw new Error(`Figma images: ${c.err}`);let l=c.images?.[n]??Object.values(c.images??{}).find(Boolean);if(!l)throw new Error("Figma returned no image URL for that node.");let d=await fetch(l);if(!d.ok)throw new Error(`Fetching the rendered image failed: ${d.status} ${d.statusText}`);return Buffer.from(await d.arrayBuffer())}function Di(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 hc(e){let t=e?.find(n=>n.visible!==!1);if(t){if(t.type==="SOLID")return Di(t.color);if(t.type?.startsWith("GRADIENT")){let n=(t.gradientStops??[]).map(o=>Di(o.color)).filter(Boolean);return n.length?`gradient(${n.join(" \u2192 ")})`:"gradient"}return t.type==="IMAGE"?"image(placeholder)":t.type?.toLowerCase()}}function yc(e,t){if(!e||typeof e!="object")return null;let n={name:e.name,type:e.type};if(e.absoluteBoundingBox){let{width:a,height:c}=e.absoluteBoundingBox;a!=null&&c!=null&&(n.size={w:Math.round(a),h:Math.round(c)})}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=hc(e.fills);o&&(n.fill=o);let i=hc(e.strokes);i&&(n.stroke={color:i,weight:e.strokeWeight}),e.cornerRadius&&(n.radius=e.cornerRadius);let r=(e.effects??[]).filter(a=>a.visible!==!1&&(a.type==="DROP_SHADOW"||a.type==="INNER_SHADOW")).map(a=>`${a.type==="INNER_SHADOW"?"inset ":""}${a.offset?.x??0} ${a.offset?.y??0} ${a.radius??0} ${Di(a.color)??""}`.trim());if(r.length&&(n.shadows=r),e.type==="TEXT"&&e.characters!==void 0){n.text=e.characters;let a=e.style??{};n.font={family:a.fontFamily,size:a.fontSize,weight:a.fontWeight,lineHeight:a.lineHeightPx,letterSpacing:a.letterSpacing,align:a.textAlignHorizontal}}if(e.children?.length&&t<Qp){let a=e.children.slice(0,gc).map(c=>yc(c,t+1)).filter(Boolean);a.length&&(n.children=a),e.children.length>gc&&(n.childrenTruncated=e.children.length)}return n}function vc(e,t){let n=e,o;if(t&&n.nodes){let r=Object.keys(n.nodes)[0];o=r?n.nodes[r]?.document:void 0}if(o??=n.document,!o)throw new Error("Figma REST response had no document node to serialize.");let i={source:"figma-rest",file:n.name,root:yc(o,0)};return JSON.stringify(i,null,2)}var Ri,Zt,Yp,Qp,gc,Li=v(()=>{"use strict";f();Ri="https://api.figma.com/v1",Zt=class extends Error{constructor(n,o,i,r){let a=[o&&`plan tier: ${o}`,i&&`limit type: ${i}`].filter(Boolean).join(", ");super(`Figma REST rate limit reached${a?` (${a})`:""}${n!==void 0?`; resets in ${Xp(n)}`:""}`);this.retryAfterSeconds=n;this.planTier=o;this.limitType=i;this.upgradeLink=r;this.name="FigmaRateLimitError"}retryAfterSeconds;planTier;limitType;upgradeLink};Yp={sleep:e=>new Promise(t=>setTimeout(t,e))};Qp=12,gc=60});import{existsSync as Zp}from"fs";import{mkdir as eu,readFile as tu,writeFile as nu}from"fs/promises";import en from"path";function ou(e,t,n){let o=r=>r.replace(/[^a-z0-9._-]/gi,"-"),i=`${o(t)}__${o(n??"file")}.json`;return en.join(e,"tmp","eds-cli","design-cache",i)}function iu(e,t){let n=`scrape__${t.replace(/[^a-z0-9._-]/gi,"-").slice(0,120)}.json`;return en.join(e,"tmp","eds-cli","design-cache",n)}function Ni(e){return e==="framer"||e==="stitch"||e==="web"}async function kc(e){if(!Zp(e))return null;try{return await tu(e,"utf-8")}catch{return null}}async function xc(e,t){await eu(en.dirname(e),{recursive:!0}),await nu(e,t,"utf-8")}async function $c(e){let{figma:t,projectRoot:n}=e;if(e.localFile)return{design:{mode:"file",filePath:e.localFile},summary:`local file ${e.localFile}`};if(Ni(e.provider)&&e.designUrl){let r=iu(n,e.designUrl),a=en.relative(n,r);if(e.dryRun)return{design:{mode:"scrape",spec:`{ "note": "dry run \u2014 the live ${e.provider} page is scraped at generate time", "url": "${e.designUrl}" }`,cachePath:a},summary:`scrape (dry run) ${e.designUrl}`};if(!e.refresh){let c=await kc(r);if(c)return{design:{mode:"scrape",spec:c,cachePath:a},summary:`cache ${a}`}}try{let c=await lc({url:e.designUrl,provider:e.provider,projectRoot:n,storageStatePath:e.storageStatePath});return await xc(r,c),{design:{mode:"scrape",spec:c,cachePath:a},summary:`scrape \u2192 ${a}`}}catch(c){return{summary:"scrape failed",scrapeError:c instanceof Error?c.message:String(c)}}}if(!t?.fileKey)return{summary:"no design source"};let o=ou(n,t.fileKey,t.nodeId),i=en.relative(n,o);if(!e.refresh){let r=await kc(o);if(r)return{design:{mode:"spec",spec:r,cachePath:i},summary:`cache ${i}`}}if(e.token&&!e.preferMcp)try{let r=await wc({fileKey:t.fileKey,nodeId:t.nodeId,token:e.token,pace:()=>Kn({logPath:qn(n),perMinute:e.restPerMinute,onWait:e.onRestWait})}),a=vc(r,t.nodeId);return await xc(o,a),{design:{mode:"spec",spec:a,cachePath:i},summary:`REST \u2192 ${i}`}}catch(r){return r instanceof Zt?{summary:"REST rate-limited",restError:r.message,rateLimit:r}:{design:{mode:"mcp",cachePath:i},summary:"MCP (REST failed \u2014 1 call)",restError:r instanceof Error?r.message:String(r)}}return{design:{mode:"mcp",cachePath:i},summary:"MCP (1 call, cached)"}}var Sc=v(()=>{"use strict";f();Ti();Vn();Li()});function Xn(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];if(!ru.has(o))throw new Error(`Not a Figma file URL: "${e}". Use a design link (figma.com/design/<file>/\u2026?node-id=\u2026).`);let i,r;n[2]==="branch"&&n[3]?(i=n[3],r=n[4]?decodeURIComponent(n[4]):void 0):(i=n[1],r=n[2]?decodeURIComponent(n[2]):void 0);let a=t.searchParams.get("node-id"),c=a?su(a):void 0;return{fileKey:i,nodeId:c,fileName:r}}function su(e){return decodeURIComponent(e).replace(/-/g,":")}var ru,jc=v(()=>{"use strict";f();ru=new Set(["design","file","board","make","slides","proto"])});import{existsSync as au}from"fs";import{readFile as cu}from"fs/promises";import lu from"path";function Pc(e){try{return JSON.stringify(JSON.parse(e))}catch{return e}}function du(e,t,n){if(!e||e==="document"||e==="ue")return"";let o=t?` (model / persisted query: \`${t}\`)`:"",i="`${window.location.origin}/graphql/execute.json/<project>/<query>;path=<cfPath>`";return e==="cf"?`
|
|
544
|
+
`}var Va,Qt,Xa,Fe,Pi,Ci=v(()=>{"use strict";f();Va=e=>De.join(e,"tmp","eds-cli","drafts"),Qt=(e,t)=>De.join(Va(e),t),Xa=(e,t)=>De.join(Qt(e,t),"draft.json"),Fe=(e,t,n)=>De.join(Qt(e,t),`v${n}`),Pi=(e,t)=>De.join(e,"blocks",t)});function ic(e){return e<=480?`${e} mobile`:e<=1024?`${e} tablet`:`${e} desktop`}function _p(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:ic(n),source:t})):[]}function rc(e,t){let n=_p(e,"figma");return n.length?n:Ip(t)}function Ip(e){if(!Array.isArray(e))return[];let t=new Set,n=[];for(let o of e){let i=Number(o?.width);if(!Number.isFinite(i)||i<=0||t.has(i))continue;t.add(i);let r=o.source,a=r==="figma"||r==="scrape"?r:"default";n.push({width:i,label:ic(i),source:a})}return n}var sc=v(()=>{"use strict";f()});import{existsSync as Up}from"fs";import{createRequire as Bp}from"module";import Hp from"path";import{pathToFileURL as ac}from"url";async function cc(e){try{return(await import("playwright")).chromium}catch{}let t=[e,process.cwd()].filter(n=>!!n);if(t.length)try{let o=Bp(ac(Hp.join(t[0],"package.json")).href).resolve("playwright",{paths:t});return(await import(ac(o).href)).chromium}catch{}throw new Error("Scraping needs Playwright. Install it in your project (`npm i -D playwright`) or globally (`npm i -g playwright`), then `npx playwright install chromium`.")}async function lc(e){let t=e.width??1440,n=await cc(e.projectRoot),o;try{o=await n.launch({headless:!0})}catch(i){let r=i instanceof Error?i.message:String(i);throw/Executable doesn't exist|install/i.test(r)?new Error("Chromium isn't installed for Playwright. Run `npx playwright install chromium`."):i}try{let i=e.storageStatePath&&Up(e.storageStatePath),a=await(await o.newContext({viewport:{width:t,height:900},deviceScaleFactor:1,...i?{storageState:e.storageStatePath}:{}})).newPage();await a.goto(e.url,{waitUntil:"networkidle",timeout:45e3}),await a.waitForTimeout(700);let c=await a.evaluate(Gp,{maxNodes:320,maxDepth:14,textCap:200}),l={source:`scrape:${e.provider}`,url:e.url,viewport:t,authenticated:!!i,title:c.title,root:c.root,nodeCount:c.nodeCount,truncated:c.truncated};return JSON.stringify(l,null,2)}finally{await o.close()}}async function dc(e){let n=await(await cc(e.projectRoot)).launch({headless:!1});try{let o=await n.newContext();await(await o.newPage()).goto(e.loginUrl,{waitUntil:"domcontentloaded",timeout:6e4}),await e.waitForUser(),await o.storageState({path:e.statePath})}finally{await n.close()}}function Gp(e){let t=new Set(["SCRIPT","STYLE","NOSCRIPT","LINK","META","HEAD","BR","TEMPLATE"]),n=0,o=!1,i=d=>!d||d==="none"||d==="normal"||d==="auto"||d==="0px"||d==="rgba(0, 0, 0, 0)"||d==="transparent";function r(d){let m="";for(let p of Array.from(d.childNodes))p.nodeType===3&&(m+=p.textContent??"");return m=m.replace(/\s+/g," ").trim(),m.length>e.textCap?`${m.slice(0,e.textCap)}\u2026`:m}function a(d){let m=getComputedStyle(d),p={},u=(h,$)=>{i($)||(p[h]=$)};u("display",m.display),(m.display.includes("flex")||m.display.includes("grid"))&&(u("flexDirection",m.flexDirection),u("justifyContent",m.justifyContent),u("alignItems",m.alignItems),u("gap",m.gap)),u("padding",m.padding),u("margin",m.margin),u("color",m.color),u("background",m.backgroundColor),m.backgroundImage&&m.backgroundImage!=="none"&&(p.backgroundImage=m.backgroundImage.slice(0,160)),u("fontFamily",m.fontFamily),u("fontSize",m.fontSize),u("fontWeight",m.fontWeight),u("lineHeight",m.lineHeight),u("letterSpacing",m.letterSpacing),u("textAlign",m.textAlign);let g=h=>h&&!h.startsWith("0px")&&!h.includes(" none")?h:"";if(m.border)g(m.border)&&(p.border=m.border);else for(let h of["borderTop","borderRight","borderBottom","borderLeft"])g(m[h])&&(p[h]=m[h]);return u("borderRadius",m.borderRadius),u("boxShadow",m.boxShadow),m.opacity&&m.opacity!=="1"&&(p.opacity=m.opacity),m.position&&m.position!=="static"&&(p.position=m.position),p}function c(d,m,p=""){if(n>=e.maxNodes)return o=!0,null;if(t.has(d.tagName))return null;let u=d.getBoundingClientRect(),g=getComputedStyle(d);if(g.display==="none"||g.visibility==="hidden"||g.opacity==="0"||u.width<1||u.height<1)return null;n++;let $={tag:d.tagName.toLowerCase(),rect:{x:Math.round(u.x),y:Math.round(u.y),w:Math.round(u.width),h:Math.round(u.height)}},w=(d.getAttribute("class")||"").trim().split(/\s+/).filter(Boolean).slice(0,3);w.length&&($.class=w.join(" "));let y=a(d);!y.background&&p&&u.width>=window.innerWidth*.9&&(y.inheritedBackground=p),Object.keys(y).length&&($.style=y);let b=y.background??p;if(d.tagName==="IMG"){let D=d;$.img={src:(D.currentSrc||D.src||"").slice(0,200),alt:D.alt||"",w:D.naturalWidth,h:D.naturalHeight}}let T=r(d);if(T&&($.text=T),m<e.maxDepth){let D=[];for(let O of Array.from(d.children)){let ne=c(O,m+1,b);ne&&D.push(ne)}D.length&&($.children=D)}return $}let l=c(document.body,0);return{title:document.title,root:l,nodeCount:n,truncated:o}}var Ti=v(()=>{"use strict";f()});import{mkdir as mc,readFile as Wp,rm as pc,stat as zp,writeFile as Jp}from"fs/promises";import fc from"path";function qn(e){return fc.join(e,"tmp","eds-cli","figma-rest-calls.json")}async function Kp(e,t,n){let o=`${e}.lock`;for(await mc(fc.dirname(e),{recursive:!0});;)try{await mc(o);break}catch{await zp(o).then(r=>t()-r.mtimeMs,()=>0)>qp?await pc(o,{recursive:!0,force:!0}):await new Promise(r=>setTimeout(r,25))}try{return await n()}finally{await pc(o,{recursive:!0,force:!0})}}async function Vp(e){try{let t=JSON.parse(await Wp(e,"utf-8"));return Array.isArray(t)?t.filter(n=>typeof n=="number"):[]}catch{return[]}}async function Kn(e){let t=Math.max(1,e.perMinute??Ai),n=e.now??Date.now,o=e.sleep??(i=>new Promise(r=>setTimeout(r,i)));for(;;){let i=await Kp(e.logPath,n,async()=>{let r=n(),a=(await Vp(e.logPath)).filter(c=>r-c<uc);return a.length<t?(a.push(r),await Jp(e.logPath,JSON.stringify(a)),0):Math.min(...a)+uc-r+50});if(i<=0)return;e.onWait?.(i),await o(i)}}var Ai,uc,qp,Vn=v(()=>{"use strict";f();Ai=10,uc=6e4,qp=1e4});function Xp(e){let t=Math.max(0,Math.round(e));if(t<60)return`${t} s`;if(t<3600)return`${Math.round(t/60)} min`;if(t<86400){let o=Math.round(t%3600/60);return`${Math.floor(t/3600)} h${o?` ${o} min`:""}`}let n=Math.round(t%86400/3600);return`${Math.floor(t/86400)} d${n?` ${n} h`:""}`}async function Fi(e,t,n,o=!1){await n?.();let i=await fetch(e,{headers:{"X-Figma-Token":t}});if(i.status!==429)return i;let r=l=>i.headers.get(l)??void 0,a=r("retry-after"),c=a!==void 0&&/^\d+$/.test(a)?Number(a):void 0;if(!o&&c!==void 0&&c<=60)return await Yp.sleep(c*1e3),Fi(e,t,n,!0);throw new Zt(c,r("x-figma-plan-tier"),r("x-figma-rate-limit-type"),r("x-figma-upgrade-link"))}async function wc(e){let{fileKey:t,nodeId:n,token:o}=e,i=n?`${Ri}/files/${t}/nodes?ids=${encodeURIComponent(n)}`:`${Ri}/files/${t}`,r=await Fi(i,o,e.pace);if(!r.ok){let a=await r.text().catch(()=>""),c=r.status===403?" (check the token scope: it needs file_content:read, and access to this file)":r.status===404?" (file or node not found \u2014 check the URL)":"";throw new Error(`Figma REST ${r.status} ${r.statusText}${c}${a?` \u2014 ${a.slice(0,200)}`:""}`)}return r.json()}async function bc(e){let{fileKey:t,nodeId:n,token:o,scale:i=1}=e;if(!n)throw new Error("A node id is required to render a Figma image.");let r=`${Ri}/images/${t}?ids=${encodeURIComponent(n)}&format=png&scale=${i}`,a=await Fi(r,o,e.pace);if(!a.ok){let m=await a.text().catch(()=>"");throw new Error(`Figma images ${a.status} ${a.statusText}${m?` \u2014 ${m.slice(0,200)}`:""}`)}let c=await a.json();if(c.err)throw new Error(`Figma images: ${c.err}`);let l=c.images?.[n]??Object.values(c.images??{}).find(Boolean);if(!l)throw new Error("Figma returned no image URL for that node.");let d=await fetch(l);if(!d.ok)throw new Error(`Fetching the rendered image failed: ${d.status} ${d.statusText}`);return Buffer.from(await d.arrayBuffer())}function Di(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 hc(e){let t=e?.find(n=>n.visible!==!1);if(t){if(t.type==="SOLID")return Di(t.color);if(t.type?.startsWith("GRADIENT")){let n=(t.gradientStops??[]).map(o=>Di(o.color)).filter(Boolean);return n.length?`gradient(${n.join(" \u2192 ")})`:"gradient"}return t.type==="IMAGE"?"image(placeholder)":t.type?.toLowerCase()}}function yc(e,t){if(!e||typeof e!="object")return null;let n={name:e.name,type:e.type};if(e.absoluteBoundingBox){let{width:a,height:c}=e.absoluteBoundingBox;a!=null&&c!=null&&(n.size={w:Math.round(a),h:Math.round(c)})}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=hc(e.fills);o&&(n.fill=o);let i=hc(e.strokes);i&&(n.stroke={color:i,weight:e.strokeWeight}),e.cornerRadius&&(n.radius=e.cornerRadius);let r=(e.effects??[]).filter(a=>a.visible!==!1&&(a.type==="DROP_SHADOW"||a.type==="INNER_SHADOW")).map(a=>`${a.type==="INNER_SHADOW"?"inset ":""}${a.offset?.x??0} ${a.offset?.y??0} ${a.radius??0} ${Di(a.color)??""}`.trim());if(r.length&&(n.shadows=r),e.type==="TEXT"&&e.characters!==void 0){n.text=e.characters;let a=e.style??{};n.font={family:a.fontFamily,size:a.fontSize,weight:a.fontWeight,lineHeight:a.lineHeightPx,letterSpacing:a.letterSpacing,align:a.textAlignHorizontal}}if(e.children?.length&&t<Qp){let a=e.children.slice(0,gc).map(c=>yc(c,t+1)).filter(Boolean);a.length&&(n.children=a),e.children.length>gc&&(n.childrenTruncated=e.children.length)}return n}function vc(e,t){let n=e,o;if(t&&n.nodes){let r=Object.keys(n.nodes)[0];o=r?n.nodes[r]?.document:void 0}if(o??=n.document,!o)throw new Error("Figma REST response had no document node to serialize.");let i={source:"figma-rest",file:n.name,root:yc(o,0)};return JSON.stringify(i,null,2)}var Ri,Zt,Yp,Qp,gc,Li=v(()=>{"use strict";f();Ri="https://api.figma.com/v1",Zt=class extends Error{constructor(n,o,i,r){let a=[o&&`plan tier: ${o}`,i&&`limit type: ${i}`].filter(Boolean).join(", ");super(`Figma REST rate limit reached${a?` (${a})`:""}${n!==void 0?`; resets in ${Xp(n)}`:""}`);this.retryAfterSeconds=n;this.planTier=o;this.limitType=i;this.upgradeLink=r;this.name="FigmaRateLimitError"}retryAfterSeconds;planTier;limitType;upgradeLink};Yp={sleep:e=>new Promise(t=>setTimeout(t,e))};Qp=12,gc=60});import{existsSync as Zp}from"fs";import{mkdir as eu,readFile as tu,writeFile as nu}from"fs/promises";import en from"path";function ou(e,t,n){let o=r=>r.replace(/[^a-z0-9._-]/gi,"-"),i=`${o(t)}__${o(n??"file")}.json`;return en.join(e,"tmp","eds-cli","design-cache",i)}function iu(e,t){let n=`scrape__${t.replace(/[^a-z0-9._-]/gi,"-").slice(0,120)}.json`;return en.join(e,"tmp","eds-cli","design-cache",n)}function Ni(e){return e==="framer"||e==="stitch"||e==="web"}async function kc(e){if(!Zp(e))return null;try{return await tu(e,"utf-8")}catch{return null}}async function xc(e,t){await eu(en.dirname(e),{recursive:!0}),await nu(e,t,"utf-8")}async function $c(e){let{figma:t,projectRoot:n}=e;if(e.localFile)return{design:{mode:"file",filePath:e.localFile},summary:`local file ${e.localFile}`};if(Ni(e.provider)&&e.designUrl){let r=iu(n,e.designUrl),a=en.relative(n,r);if(e.dryRun)return{design:{mode:"scrape",spec:`{ "note": "dry run \u2014 the live ${e.provider} page is scraped at generate time", "url": "${e.designUrl}" }`,cachePath:a},summary:`scrape (dry run) ${e.designUrl}`};if(!e.refresh){let c=await kc(r);if(c)return{design:{mode:"scrape",spec:c,cachePath:a},summary:`cache ${a}`}}try{let c=await lc({url:e.designUrl,provider:e.provider,projectRoot:n,storageStatePath:e.storageStatePath});return await xc(r,c),{design:{mode:"scrape",spec:c,cachePath:a},summary:`scrape \u2192 ${a}`}}catch(c){return{summary:"scrape failed",scrapeError:c instanceof Error?c.message:String(c)}}}if(!t?.fileKey)return{summary:"no design source"};let o=ou(n,t.fileKey,t.nodeId),i=en.relative(n,o);if(!e.refresh){let r=await kc(o);if(r)return{design:{mode:"spec",spec:r,cachePath:i},summary:`cache ${i}`}}if(e.token&&!e.preferMcp)try{let r=await wc({fileKey:t.fileKey,nodeId:t.nodeId,token:e.token,pace:()=>Kn({logPath:qn(n),perMinute:e.restPerMinute,onWait:e.onRestWait})}),a=vc(r,t.nodeId);return await xc(o,a),{design:{mode:"spec",spec:a,cachePath:i},summary:`REST \u2192 ${i}`}}catch(r){return r instanceof Zt?{summary:"REST rate-limited",restError:r.message,rateLimit:r}:{design:{mode:"mcp",cachePath:i},summary:"MCP (REST failed \u2014 1 call)",restError:r instanceof Error?r.message:String(r)}}return{design:{mode:"mcp",cachePath:i},summary:"MCP (1 call, cached)"}}var Sc=v(()=>{"use strict";f();Ti();Vn();Li()});function Xn(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];if(!ru.has(o))throw new Error(`Not a Figma file URL: "${e}". Use a design link (figma.com/design/<file>/\u2026?node-id=\u2026).`);let i,r;n[2]==="branch"&&n[3]?(i=n[3],r=n[4]?decodeURIComponent(n[4]):void 0):(i=n[1],r=n[2]?decodeURIComponent(n[2]):void 0);let a=t.searchParams.get("node-id"),c=a?su(a):void 0;return{fileKey:i,nodeId:c,fileName:r}}function su(e){return decodeURIComponent(e).replace(/-/g,":")}var ru,jc=v(()=>{"use strict";f();ru=new Set(["design","file","board","make","slides","proto"])});import{existsSync as au}from"fs";import{readFile as cu}from"fs/promises";import lu from"path";function Pc(e){try{return JSON.stringify(JSON.parse(e))}catch{return e}}function du(e,t,n){if(!e||e==="document"||e==="ue")return"";let o=t?` (model / persisted query: \`${t}\`)`:"",i="`${window.location.origin}/graphql/execute.json/<project>/<query>;path=<cfPath>`";return e==="cf"?`
|
|
545
545
|
## Content source: Content Fragment
|
|
546
546
|
This block renders an AEM **Content Fragment**${o} - not inline-authored copy.
|
|
547
547
|
- UE model: use an \`aem-content-fragment\` field (e.g. \`name: "fragment"\`) for the CF reference.
|
|
@@ -722,6 +722,7 @@ ${d}
|
|
|
722
722
|
|
|
723
723
|
## EDS Block Conventions
|
|
724
724
|
- **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.
|
|
725
|
+
- **Backgrounds go on the section, not the block**: the boilerplate caps \`main > .section > div\` (the \`.${e.blockName}-wrapper\`) at \`max-width: 1200px\` with side padding, and gives \`main > .section\` a \`40px\` vertical margin. A background on \`.${e.blockName}\` therefore stops at 1200px and leaves the page colour (often white) at the sides and above/below. Paint any background that spans the frame on \`main > .section.${e.blockName}-container\` with \`margin: 0\` and \`padding-block\` for the spacing, and keep the wrapper as the content cap.
|
|
725
726
|
- **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.
|
|
726
727
|
- **No frameworks**: vanilla JS and CSS only
|
|
727
728
|
- **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.
|
|
@@ -779,7 +780,7 @@ Reuse them instead of hardcoding values:
|
|
|
779
780
|
${i}
|
|
780
781
|
}
|
|
781
782
|
\`\`\`
|
|
782
|
-
`:""}catch{return""}}var tn,gt,Oi=v(()=>{"use strict";f();ti();tn="0.7.
|
|
783
|
+
`:""}catch{return""}}var tn,gt,Oi=v(()=>{"use strict";f();ti();tn="0.7.3",gt={figma:"Figma",framer:"Framer",stitch:"Google Stitch",web:"Web page"}});import{existsSync as pu}from"fs";import{chmod as uu,mkdir as fu}from"fs/promises";import{homedir as gu}from"os";import Cc from"path";function Mi(e){return Cc.join(gu(),".eds","auth",`${e}.json`)}function Tc(e){return pu(Mi(e))}async function Ac(e){await fu(Cc.dirname(e),{recursive:!0,mode:448})}async function Rc(e){try{await uu(e,384)}catch{}}var Dc=v(()=>{"use strict";f()});import{emitKeypressEvents as hu}from"readline";async function nn(e){let t=process.stdin,n=Qn.menu&&t.isTTY;await new Promise(o=>{let i=!1,r=async l=>{i||(i=!0,process.off("SIGINT",a),process.off("SIGTERM",a),n&&(t.off("keypress",c),t.setRawMode(!1),t.pause()),await e(),l&&(B.emit({type:"result",ok:!0,exitCode:0}),process.exit(0)),o())},a=()=>{r(!0)},c=(l,d)=>{d?.ctrl&&d.name==="c"?r(!0):(d?.name==="escape"||d?.name==="return")&&r(!1)};process.on("SIGINT",a),process.on("SIGTERM",a),n&&(hu(t),t.setRawMode(!0),t.resume(),t.on("keypress",c))})}function on(){return Qn.menu&&process.stdin.isTTY?"Press Esc or Enter to stop and go back to the menu (Ctrl+C quits).":"Press Ctrl+C to stop."}var Qn,Zn=v(()=>{"use strict";f();Se();Qn={menu:!1}});function he(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function wu(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 eo(e){let{blockName:t}=e,n=wu(e.sampleContent);return`<!DOCTYPE html>
|
|
783
784
|
<html lang="en">
|
|
784
785
|
<head>
|
|
785
786
|
<meta charset="utf-8" />
|
|
@@ -810,6 +811,17 @@ ${n}
|
|
|
810
811
|
} catch (e) { console.error('block script failed \u2014 showing authored content only:', e); }
|
|
811
812
|
})();
|
|
812
813
|
</script>
|
|
814
|
+
<script>
|
|
815
|
+
// Tools that embed this frame (aem-eds-studio) size it to the block: post the
|
|
816
|
+
// content height to the parent whenever it changes.
|
|
817
|
+
(() => {
|
|
818
|
+
if (window.parent === window) return;
|
|
819
|
+
const main = document.querySelector('main');
|
|
820
|
+
const post = () => window.parent.postMessage({ type: 'eds-preview-size', height: Math.ceil(main.scrollHeight) }, '*');
|
|
821
|
+
if ('ResizeObserver' in window) new ResizeObserver(post).observe(main);
|
|
822
|
+
addEventListener('load', post);
|
|
823
|
+
})();
|
|
824
|
+
</script>
|
|
813
825
|
<script>
|
|
814
826
|
// Live reload: refresh when eds detects a change to the block.
|
|
815
827
|
try { new EventSource('/__eds_events').onmessage = () => location.reload(); } catch (e) { /* no SSE */ }
|
|
@@ -945,11 +957,11 @@ ${n}
|
|
|
945
957
|
</div></div>
|
|
946
958
|
</div>`}async function ve(e,t,n){let o=te.join(e,"blocks",t);if(!de(te.join(o,`${t}.css`))&&!de(te.join(o,`${t}.js`)))return null;let i=null,r=te.join(o,".eds-meta.json");if(de(r))try{i=JSON.parse(await rn(r,"utf-8"))}catch{}let a=te.join(o,`_${t}.preview.html`),c,l=!1;return de(a)?c=await rn(a,"utf-8"):(c=Uc(t),l=!0),{name:t,sampleContent:c,breakpoints:_c(n,i),figmaUrl:Ic(i),placeholder:l}}async function ht(e,t,n){return to(e,{},n,"127.0.0.1",async i=>{if(!i.startsWith(Ne))return;let r=i.slice(Ne.length);if(!/^[a-z0-9-]+$/i.test(r))return;let a=await ve(e,r,t);if(a)return{body:eo({blockName:r,breakpoints:a.breakpoints,sampleContent:a.sampleContent,frameRoute:Ne+r}),type:"text/html; charset=utf-8"}})}async function Ye(e){let t=te.join(e,"blocks");if(!de(t))return[];let n=await Pu(t,{withFileTypes:!0}),o=[];for(let i of n){if(!i.isDirectory()||Eu.has(i.name))continue;let r=te.join(t,i.name);(de(te.join(r,`${i.name}.css`))||de(te.join(r,`${i.name}.js`)))&&o.push(i.name)}return o.sort()}async function Bc(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 Hc(e,t={}){let n=E();if(!n)return s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1,null;let o=t.blockDir??te.join(n,"blocks",e);if(!de(o))return s.error(`Block "${e}" not found at ${te.relative(n,o)}/.`),process.exitCode=1,null;if(!de(te.join(o,`${e}.css`))&&!de(te.join(o,`${e}.js`)))return s.error(`Block "${e}" has no ${e}.css / ${e}.js to preview.`),process.exitCode=1,null;(e==="header"||e==="footer")&&(s.warn(`"${e}" is page chrome, not a content block \u2014 it won't render standalone here.`),s.info(Le.dim(` It fetches the ${e==="header"?"nav":"footer"} fragment and needs the full page runtime.`)),s.info(Le.dim(" Preview a content block instead (e.g. a block generated from a design).")));let i=null,r=te.join(o,".eds-meta.json");if(de(r))try{i=JSON.parse(await rn(r,"utf-8"))}catch{}let a=te.join(o,`_${e}.preview.html`),c,l=!1;de(a)?c=await rn(a,"utf-8"):(c=Uc(e),l=!0);let d=_c(t.widths,i),m=Ic(i),p="/__eds_preview_frame",u=eo({blockName:e,breakpoints:d,sampleContent:c,frameRoute:p}),g=Lc({blockName:e,breakpoints:d,sampleContent:c,figmaUrl:m,frameRoute:p,placeholder:l}),h=Number.parseInt(t.port??"8777",10),$=t.blockDir,w=$?async D=>{let O=`/blocks/${e}/`;if(!D.startsWith(O))return;let ne=te.join($,D.slice(O.length));if(!(!ne.startsWith($)||!de(ne)))return{body:await rn(ne,"utf-8"),type:Au(ne)}}:void 0,y=await to(n,{"/":{body:g,type:"text/html; charset=utf-8"},[p]:{body:u,type:"text/html; charset=utf-8"}},Number.isFinite(h)?h:8777,void 0,w);s.logoOnce(A(`Preview \u2014 ${e}`)),s.info(j("Live preview",y.url)),s.info(R("pass","breakpoints",`${d.map(D=>`${D.width}${D.figma?"\u2713":""}`).join(", ")}, Full`)),l&&s.info(R("warn","content",`placeholder \u2014 add blocks/${e}/_${e}.preview.html for real content`));let b,T=Mc(o,{recursive:!0},()=>{clearTimeout(b),b=setTimeout(()=>y.reload(),150)});return s.info(""),s.info(` ${Le.bold("\u279C")} ${Le.cyan(y.url)}`),s.info(R("pass","live reload","edits to the block refresh the browser")),B.emit({type:"preview",name:e,url:y.url,...t.version?{version:t.version}:{}}),t.open!==!1&&!B.enabled&&await Bc(y.url),{url:y.url,close:async()=>{T.close(),await y.close()}}}async function Ru(e,t={}){let n=await Hc(e,t);n&&(s.info(Le.dim(` ${on()}
|
|
947
959
|
`)),await nn(n.close))}async function Du(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n="/__eds_frame/",o=async d=>{if(d==="/"){let m=await Ye(t),p=[];for(let u of m){let g=await ve(t,u,e.widths);g&&p.push({blockName:u,breakpoints:g.breakpoints,frameRoute:n+u,figmaUrl:g.figmaUrl,placeholder:g.placeholder})}return{body:Fc(p),type:"text/html; charset=utf-8"}}if(d.startsWith(n)){let m=d.slice(n.length);if(!/^[a-z0-9-]+$/i.test(m))return;let p=await ve(t,m,e.widths);return p?{body:eo({blockName:m,breakpoints:p.breakpoints,sampleContent:p.sampleContent,frameRoute:n+m}),type:"text/html; charset=utf-8"}:void 0}},i=Number.parseInt(e.port??"8777",10),r=await to(t,{},Number.isFinite(i)?i:8777,"127.0.0.1",o),a=await Ye(t);s.logoOnce(A("Preview \u2014 gallery")),s.info(j("Live gallery",r.url)),s.info(R(a.length?"pass":"warn","blocks",a.length?a.join(", "):"none yet \u2014 generate one with eds block from-design"));let c,l=Mc(te.join(t,"blocks"),{recursive:!0},()=>{clearTimeout(c),c=setTimeout(()=>r.reload(),150)});s.info(""),s.info(` ${Le.bold("\u279C")} ${Le.cyan(r.url)}`),s.info(R("pass","live reload","new & edited blocks refresh the browser")),s.info(Le.dim(` ${on()}
|
|
948
|
-
`)),e.open!==!1&&await Bc(r.url),await nn(async()=>{l.close(),await r.close()})}var Eu,Cu,Tu,Au,Ne,Oe=v(()=>{"use strict";f();Se();N();Nc();Oc();V();Zn();H();Eu=new Set(["header","footer"]),Cu=[375,768,1280],Tu={".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".html":"text/html; charset=utf-8",".svg":"image/svg+xml"},Au=e=>Tu[te.extname(e).toLowerCase()]??"text/plain";Ne="/__eds_frame/"});var oo={};U(oo,{blockFromDesign:()=>Hu,detectProvider:()=>Wc,generateDraft:()=>Jc,verifyGeneratedBlock:()=>Hi,writeBlockMeta:()=>Bi});import{existsSync as le}from"fs";import{readFile as Me,readdir as Fu,writeFile as Lu}from"fs/promises";import X from"path";import{fileURLToPath as Nu}from"url";import S from"chalk";import no from"ora";function Ou(){let e=X.dirname(Nu(import.meta.url));return[X.resolve(e,"../../samples/hero.svg"),X.resolve(e,"../../../samples/hero.svg")].find(n=>le(n))??null}async function Mu(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 _u(e){let{input:t,select:n,confirm:o}=await Promise.resolve().then(()=>(K(),q)),i=await n({message:"1/7 Design source",choices:[{name:"Figma (REST / MCP / local)",value:"figma"},{name:"Framer (scraped, headless Chromium)",value:"framer"},{name:"Google Stitch (scraped, headless Chromium)",value:"stitch"},{name:"Any web page (a live site or HTML mock-up, scraped)",value:"web"}],default:"figma"}),r=await t({message:"2/7 Component name",validate:b=>He.test(b.trim())||"Use kebab-case, e.g. hero-banner"}),a=e??await t({message:`3/7 ${gt[i]} link`,validate:b=>{if(!b.trim())return"Paste the design link";if(i!=="figma")return/^https?:\/\//i.test(b.trim())||"Paste a public http(s) URL to the page";try{return Xn(b.trim()),!0}catch(T){return T.message}}}),c=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;(c==="cf"||c==="mixed")&&(l=(await t({message:" CF model / GraphQL persisted-query name (optional)"})).trim()||void 0);let d=await o({message:"5/7 Generate the Universal Editor model?",default:!0}),m=await o({message:"6/7 Add a screenshot MCP call for a pixel check? (off = one fewer MCP call)",default:!1}),p=await Wn(),u=await n({message:"7/7 Run with",choices:[...p.map(b=>({name:b.model?`${b.type} \xB7 ${b.model} (local)`:`${b.type}${i==="figma"&&!b.hasFigmaMcp?" (Figma MCP not detected)":""}`,value:`agent:${b.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=gt[i].toLowerCase();s.info(j("Summary"));let h=I(["component",g,"content","ue model","screenshot","run"]);s.info(P("component",r,h));let $=i==="figma"?(()=>{let b=Xn(a.trim());return b.nodeId?`node ${b.nodeId}`:b.fileKey})():a.trim();if(s.info(P(g,$,h)),s.info(P("content",c+(l?` (${l})`:""),h)),s.info(P("ue model",d?"yes":"no",h)),s.info(P("screenshot",m?"yes":"no (token-lean)",h)),s.info(P("run",u.replace("agent:",""),h)),s.info(""),!await o({message:"Generate this block?",default:!0}))return null;let y={figmaUrl:a.trim(),name:r,provider:i,source:c,cfHint:l,ueModel:d,screenshot:m};return u==="dry-run"?y.dryRun=!0:u==="none"?y.agent="none":(y.agent=u.replace("agent:",""),y.yes=!0),y}function Ui(e){return e&&e.replace(/[-_\s]+/g,"-").replace(/[^a-z0-9-]/gi,"").toLowerCase().replace(/^-+|-+$/g,"")||"design-block"}function Iu(e){try{let t=new URL(e);return t.pathname.split("/").filter(Boolean).pop()||t.hostname.split(".")[0]}catch{return""}}function Wc(e){if(e)try{let t=new URL(e),n=t.hostname.toLowerCase();if(n.includes("figma.com"))return"figma";if(n.includes("framer"))return"framer";if(n.includes("stitch"))return"stitch";if(t.protocol==="http:"||t.protocol==="https:")return"web"}catch{}}function Bu(e){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(e))return null;let t=X.isAbsolute(e)?e:X.resolve(process.cwd(),e);return!le(t)||!Uu.has(X.extname(t).toLowerCase())?null:t}async function Hu(e,t){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}await s.logoOnceAnimated("Design \u2192 EDS block");let o=e,i=t;if(!o&&i.sample){let M=Ou();if(!M){s.error("Bundled sample design not found (samples/hero.svg)."),process.exitCode=1;return}o=M,i={name:"hero",provider:"figma",...i},s.info(` ${Y.pass} Sample design ${S.dim("aem-eds-kit example hero")} ${S.dim("(bundled \xB7 no token \xB7 no MCP)")}`)}if(B.enabled&&(i={...i,yes:!0},!o)){s.error("--json needs a design (a URL or a local file) or --sample."),process.exitCode=1;return}if(!o){let M=await _u(o);if(!M){s.info("Cancelled.");return}o=M.figmaUrl,i={...i,...M}}let r=i.provider;if(r&&!(r in gt)){s.error(`Unknown --provider "${r}". Use: figma, framer, stitch or web.`),process.exitCode=1;return}if(i.source&&!Gc.includes(i.source)){s.error(`Unknown --source "${i.source}". Use: ${Gc.join(", ")}.`),process.exitCode=1;return}let a=r??Wc(o)??"figma",c=gt[a],l=Bu(o),d=l?l.startsWith(n+X.sep)?X.relative(n,l):l:void 0,m=null,p=d??o;if(l)s.info(` ${Y.pass} Local design file ${S.dim(d)} ${S.dim("(no Figma MCP)")}`);else if(a==="figma"){let M=no("Parsing Figma URL...").start();try{m=Xn(o),M.succeed(`Parsed Figma URL ${S.dim(m.nodeId?`node ${m.nodeId}`:`file ${m.fileKey}`)}`)}catch($e){M.fail($e.message),process.exitCode=1;return}}else s.info(` ${Y.pass} ${c} design ${S.dim(p)}`);let u=i.name||(l?Ui(X.basename(l,X.extname(l))):m?Ui(m.fileName):o?Ui(Iu(o)):"");if(!He.test(u)){s.error(`Invalid block name "${u}". Use --name with a kebab-case name (e.g., --name hero-banner).`),process.exitCode=1;return}!i.name&&m?.nodeId&&(s.warn(`Block name "${u}" came from the Figma file name, not the selected frame.`),s.info(S.dim(` Pass ${S.cyan("--name <kebab-case>")} for a cleaner block name.`)));let g=await ce(n),h=g.figma?.token??process.env.FIGMA_TOKEN??process.env.FIGMA_PAT,$;if(Ni(a)&&!l&&!i.dryRun&&(i.auth||i.authRefresh))if($=Mi(a),i.authRefresh||!Tc(a)){let M=(()=>{try{return new URL(o).origin}catch{return o}})();s.info(` ${S.dim("\u2192")} Opening ${S.cyan(c)} \u2014 click ${S.cyan("Sign In")} and log in, then come back here.`);let{input:$e}=await Promise.resolve().then(()=>(K(),q));try{await Ac($),await dc({loginUrl:M,statePath:$,projectRoot:n,waitForUser:async()=>{await $e({message:"Press Enter once you're signed in (you don't need to open the design)"})}}),await Rc($),s.info(` ${Y.pass} Session saved ${S.dim($)}`)}catch(Be){s.error(`Could not capture the ${c} session: ${Be instanceof Error?Be.message:String(Be)}`),process.exitCode=1;return}}else s.info(` ${Y.pass} Using saved ${c} session ${S.dim($)} ${S.dim("(--auth-refresh to re-login)")}`);let w=no("Resolving design source...").start(),y=await $c({figma:m,localFile:d,token:h,projectRoot:n,preferMcp:i.mcp,refresh:i.refresh,provider:a,designUrl:l?void 0:o,storageStatePath:$,dryRun:i.dryRun,restPerMinute:g.figma?.restPerMinute,onRestWait:M=>{w.text=`Resolving design source... waiting ${Math.ceil(M/1e3)} s for a Figma REST slot (${g.figma?.restPerMinute??Ai}/min)`}});if(y.scrapeError){w.fail(`Scrape failed: ${y.scrapeError}`),s.info(S.dim(` Check the URL is a public ${c} page, and that Chromium is installed (${S.cyan("npx playwright install chromium")}).`)),process.exitCode=1;return}if(y.rateLimit){w.fail(y.rateLimit.message),s.info(S.dim(" The limit follows the plan that owns the file: 20 calls/month on Starter or with a View/Collab seat, 10-20/min with a Dev/Full seat on a paid plan.")),s.info(S.dim(` Not falling back to Figma MCP (its budget is the same or smaller). Re-run after the reset, pass ${S.cyan("--mcp")} to spend an MCP call instead, or export the frame as PNG/SVG (no quota).`)),y.rateLimit.upgradeLink&&s.info(S.dim(` Plan details: ${y.rateLimit.upgradeLink}`)),process.exitCode=1;return}if(w.succeed(`Design source ${S.dim(y.summary)}`),y.restError&&s.warn(`Figma REST fetch failed, using MCP fallback: ${y.restError}`),y.design?.mode==="scrape"&&!i.dryRun)try{let M=JSON.parse(y.design.spec),$e=(M.title??"").toLowerCase(),Be=y.design.spec.toLowerCase(),br=/isn'?t shared|doesn'?t exist|page not found|\b404\b/;(br.test($e)||br.test(Be)||/\bsign[ -]?in\b|\blog[ -]?in\b/.test($e)||(M.nodeCount??0)<8)&&(s.warn(`The scraped page looks like a login / error shell${M.title?` ("${M.title}")`:""} \u2014 the design may be gated or the URL wrong.`),s.info(S.dim(` Use ${S.cyan("--auth")} to log in once (or ${S.cyan("--auth-refresh")} to re-login), and confirm the URL opens the design when you're signed in.`)))}catch{}let b=no("Reading design tokens & building prompt...").start(),T=await Ec({provider:a,figma:m,designRef:p,blockName:u,projectRoot:n,withUeModel:i.ueModel!==!1,contentSource:i.source??"document",cfHint:i.cfHint,screenshot:i.screenshot===!0,design:y.design}),D=await Xt(T,n),O=le(X.join(n,"styles","styles.css"));if(b.succeed(O?`Loaded design tokens ${S.dim("styles/styles.css")}`:`Built prompt ${S.dim("no project tokens found")}`),s.info(S.dim(` prompt \u2192 ${D}`)),i.dryRun){if(s.info(""),s.info(S.yellow("Dry run mode \u2014 prompt generated but agent not invoked.")),s.info(`Prompt file: ${S.cyan(D)}`),s.info(`Block name: ${S.cyan(u)}`),s.info(`Prompt version: ${tn}`),s.info(""),s.info("Preview:"),B.emit({type:"prompt",file:D,block:u}),B.enabled)return;s.info(S.dim("\u2500".repeat(60))),console.log(T);return}let ne=i.agent||g.agent;if(i.agent==="none"){s.info("Agent skipped (--agent none). Use the prompt file manually:"),s.info(` ${S.cyan(D)}`);return}let Ue=no("Detecting AI agent...").start(),F=await Gn(ne);if(!F){Ue.fail("No AI agent found (claude, cursor, codex, or a local Ollama / oMLX server)."),s.info(`Install Claude Code: ${S.cyan("npm install -g @anthropic-ai/claude-code")}`),s.info(`Or run a local model: ${S.cyan("ollama serve")} / ${S.cyan("omlx start")}, then ${S.cyan("--agent ollama")} or ${S.cyan("--agent omlx")}.`),s.info(`Or use the prompt file manually: ${S.cyan(D)}`),process.exitCode=1;return}let xe=ye(F.type);Ue.succeed(`Agent ready ${S.cyan(F.type)} ${S.dim(xe?`${i.model??F.model} \xB7 ${F.path}`:F.path)}`);let hr=y.design?.mode==="mcp"||!y.design&&a==="figma";if(xe&&hr){s.error("A local model can't read a Figma design through MCP."),s.info(S.dim(` Set a Figma token (${S.cyan("FIGMA_TOKEN")}) so eds fetches it over REST, export the frame as PNG/SVG, or scrape a Framer / Stitch page. Prompt saved: ${D}`)),process.exitCode=1;return}if(hr&&a==="figma"&&!F.hasFigmaMcp&&(s.warn(`Figma MCP may not be configured for ${F.type}.`),s.info(`Run ${S.cyan("eds figma setup")} to configure it, or set a Figma token for REST.`)),!i.yes){let{confirm:M}=await Promise.resolve().then(()=>(K(),q));if(!await M({message:`Run ${F.type} with the generated prompt?`,default:!0})){s.info(`Prompt saved to: ${S.cyan(D)}`);return}}let Tl=y.design?.mode==="spec"?"embedded design (no MCP)":y.design?.mode==="scrape"?`scraped ${c} page (no MCP)`:y.design?.mode==="file"?`reading ${d}`:y.design?.mode==="mcp"?`via ${c} MCP (1 call, cached)`:`via ${c} MCP`;s.info(` ${S.dim("\u2192")} Handing off to ${S.cyan(F.type)} ${S.dim(Tl)}`),y.design?.mode==="mcp"&&s.info(S.dim(" get_design_context \xD71 \u2192 cache"));let Al=i.source==="cf"||i.source==="mixed",Pt=xe?i.model??F.model:i.model??g.model??(Al&&F.type==="claude"?"sonnet":void 0);Pt&&!xe&&!i.model&&!g.model&&s.info(S.dim(` Model: ${Pt} (Content Fragment source)`));let wr={blockName:u,designFile:y.design?.mode==="file"?d:void 0,contextTokens:g.local?.contextTokens,apiKey:g.local?.apiKey};if(i.draft){await Jc({projectRoot:n,blockName:u,run:()=>ut(F,D,n,Pt,wr),verify:M=>Hi(M,u,i.ueModel!==!1,i.source??"document"),writeMeta:M=>Bi(M,{widths:i.widths,provider:a,designRef:p,figma:m,agentType:F.type}),source:{provider:a,designRef:p,figma:m,agent:F.type,model:Pt}});return}if(!await ut(F,D,n,Pt,wr)){process.exitCode=1;return}let fn=X.join(n,"blocks",u);if(!(le(X.join(fn,`${u}.js`))||le(X.join(fn,`${u}.css`)))){s.warn(`No block files were written to blocks/${u}/ \u2014 nothing to preview.`),y.design?.mode==="mcp"&&!F.hasFigmaMcp?(s.info(S.dim(` The agent couldn't read the design: no ${c} MCP is configured for ${F.type}.`)),s.info(S.dim(` Run ${S.cyan("eds figma setup")}, or set a Figma token (FIGMA_TOKEN) to use REST, then re-run.`))):y.design?.mode==="mcp"?(s.info(S.dim(" The agent couldn't read the design, so it generated nothing. Common cause: the")),s.info(S.dim(` ${c} MCP tool-call limit (e.g. Figma Starter plan). See the log above.`)),s.info(S.dim(" Wait for the limit to reset or upgrade the plan, then re-run the same command."))):s.info(S.dim(" The agent generated nothing \u2014 see the log above for why.")),process.exitCode=1;return}let Rl=await Hi(fn,u,i.ueModel!==!1,i.source??"document");if(await Bi(fn,{widths:i.widths,provider:a,designRef:p,figma:m,agentType:F.type}),!Rl){s.warn(`Block "${u}" generated with issues \u2014 review the output above before publishing.`),process.exitCode=1;return}if(s.success(`Block "${u}" generation complete.`),!i.yes){let{confirm:M}=await Promise.resolve().then(()=>(K(),q));if(await M({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:Be}=await Promise.resolve().then(()=>(Ht(),Bt));await Be(u,{})}}if(!i.yes)await Gu({blockName:u,projectRoot:n,agent:F,model:ye(F.type)?i.model??F.model:i.model??g.model,contextTokens:g.local?.contextTokens,apiKey:g.local?.apiKey,provider:a,figma:m,designRef:p});else if(i.serve){let{previewBlock:M}=await Promise.resolve().then(()=>(Oe(),wt));await M(u,{})}else s.info(` ${S.dim("\u2192")} Next: ${S.cyan(`eds block preview ${u}`)}`)}async function Jc(e){let{projectRoot:t,blockName:n}=e,o=X.join(t,"blocks",n),i=await Qa(t,n,e.from),r,a;try{let l=await e.run(),d=le(X.join(o,`${n}.js`))||le(X.join(o,`${n}.css`));if(!l||!d)return s.warn(`No draft was produced for "${n}" \u2014 see the log above.`),process.exitCode=1,null;a=await e.verify(o),await e.writeMeta(o),r=await Za(t,n,{source:e.source,feedback:e.feedback,ok:a})}finally{await i()}a||(process.exitCode=1);let c=Fe(t,n,r);return B.emit({type:"draft",name:n,version:r,ok:a,dir:X.relative(t,c),files:(await Fu(c)).sort(),...e.feedback?{feedback:e.feedback}:{}}),s.success(`Draft "${n}" v${r} ready${a?"":" (with issues \u2014 see above)"}. blocks/${n}/ is unchanged.`),s.info(` ${S.dim("\u2192")} Review: ${S.cyan(`eds draft preview ${n}`)}`),s.info(` ${S.dim("\u2192")} Change: ${S.cyan(`eds draft refine ${n} "<what to change>"`)}`),s.info(` ${S.dim("\u2192")} Accept: ${S.cyan(`eds draft accept ${n} --commit`)}`),r}async function Bi(e,t){if(le(e)){let n=X.join(e,".eds-meta.json"),o;if(le(n))try{o=JSON.parse(await Me(n,"utf-8")).breakpoints}catch{}let i=rc(t.widths,o),r={provider:t.provider,designRef:t.designRef,figmaFileKey:t.figma?.fileKey??null,figmaNodeId:t.figma?.nodeId??null,lastSyncedAt:new Date().toISOString(),promptVersion:tn,agentUsed:t.agentType,...i.length?{breakpoints:i}:{}};await Lu(n,`${JSON.stringify(r,null,2)}
|
|
960
|
+
`)),e.open!==!1&&await Bc(r.url),await nn(async()=>{l.close(),await r.close()})}var Eu,Cu,Tu,Au,Ne,Oe=v(()=>{"use strict";f();Se();N();Nc();Oc();V();Zn();H();Eu=new Set(["header","footer"]),Cu=[375,768,1280],Tu={".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".html":"text/html; charset=utf-8",".svg":"image/svg+xml"},Au=e=>Tu[te.extname(e).toLowerCase()]??"text/plain";Ne="/__eds_frame/"});var oo={};U(oo,{blockFromDesign:()=>Hu,detectProvider:()=>Wc,generateDraft:()=>zc,verifyGeneratedBlock:()=>Hi,writeBlockMeta:()=>Bi});import{existsSync as le}from"fs";import{readFile as Me,readdir as Fu,writeFile as Lu}from"fs/promises";import X from"path";import{fileURLToPath as Nu}from"url";import S from"chalk";import no from"ora";function Ou(){let e=X.dirname(Nu(import.meta.url));return[X.resolve(e,"../../samples/hero.svg"),X.resolve(e,"../../../samples/hero.svg")].find(n=>le(n))??null}async function Mu(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 _u(e){let{input:t,select:n,confirm:o}=await Promise.resolve().then(()=>(K(),q)),i=await n({message:"1/7 Design source",choices:[{name:"Figma (REST / MCP / local)",value:"figma"},{name:"Framer (scraped, headless Chromium)",value:"framer"},{name:"Google Stitch (scraped, headless Chromium)",value:"stitch"},{name:"Any web page (a live site or HTML mock-up, scraped)",value:"web"}],default:"figma"}),r=await t({message:"2/7 Component name",validate:b=>He.test(b.trim())||"Use kebab-case, e.g. hero-banner"}),a=e??await t({message:`3/7 ${gt[i]} link`,validate:b=>{if(!b.trim())return"Paste the design link";if(i!=="figma")return/^https?:\/\//i.test(b.trim())||"Paste a public http(s) URL to the page";try{return Xn(b.trim()),!0}catch(T){return T.message}}}),c=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;(c==="cf"||c==="mixed")&&(l=(await t({message:" CF model / GraphQL persisted-query name (optional)"})).trim()||void 0);let d=await o({message:"5/7 Generate the Universal Editor model?",default:!0}),m=await o({message:"6/7 Add a screenshot MCP call for a pixel check? (off = one fewer MCP call)",default:!1}),p=await Wn(),u=await n({message:"7/7 Run with",choices:[...p.map(b=>({name:b.model?`${b.type} \xB7 ${b.model} (local)`:`${b.type}${i==="figma"&&!b.hasFigmaMcp?" (Figma MCP not detected)":""}`,value:`agent:${b.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=gt[i].toLowerCase();s.info(j("Summary"));let h=I(["component",g,"content","ue model","screenshot","run"]);s.info(P("component",r,h));let $=i==="figma"?(()=>{let b=Xn(a.trim());return b.nodeId?`node ${b.nodeId}`:b.fileKey})():a.trim();if(s.info(P(g,$,h)),s.info(P("content",c+(l?` (${l})`:""),h)),s.info(P("ue model",d?"yes":"no",h)),s.info(P("screenshot",m?"yes":"no (token-lean)",h)),s.info(P("run",u.replace("agent:",""),h)),s.info(""),!await o({message:"Generate this block?",default:!0}))return null;let y={figmaUrl:a.trim(),name:r,provider:i,source:c,cfHint:l,ueModel:d,screenshot:m};return u==="dry-run"?y.dryRun=!0:u==="none"?y.agent="none":(y.agent=u.replace("agent:",""),y.yes=!0),y}function Ui(e){return e&&e.replace(/[-_\s]+/g,"-").replace(/[^a-z0-9-]/gi,"").toLowerCase().replace(/^-+|-+$/g,"")||"design-block"}function Iu(e){try{let t=new URL(e);return t.pathname.split("/").filter(Boolean).pop()||t.hostname.split(".")[0]}catch{return""}}function Wc(e){if(e)try{let t=new URL(e),n=t.hostname.toLowerCase();if(n.includes("figma.com"))return"figma";if(n.includes("framer"))return"framer";if(n.includes("stitch"))return"stitch";if(t.protocol==="http:"||t.protocol==="https:")return"web"}catch{}}function Bu(e){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(e))return null;let t=X.isAbsolute(e)?e:X.resolve(process.cwd(),e);return!le(t)||!Uu.has(X.extname(t).toLowerCase())?null:t}async function Hu(e,t){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found). Run this from your project root."),process.exitCode=1;return}await s.logoOnceAnimated("Design \u2192 EDS block");let o=e,i=t;if(!o&&i.sample){let M=Ou();if(!M){s.error("Bundled sample design not found (samples/hero.svg)."),process.exitCode=1;return}o=M,i={name:"hero",provider:"figma",...i},s.info(` ${Y.pass} Sample design ${S.dim("aem-eds-kit example hero")} ${S.dim("(bundled \xB7 no token \xB7 no MCP)")}`)}if(B.enabled&&(i={...i,yes:!0},!o)){s.error("--json needs a design (a URL or a local file) or --sample."),process.exitCode=1;return}if(!o){let M=await _u(o);if(!M){s.info("Cancelled.");return}o=M.figmaUrl,i={...i,...M}}let r=i.provider;if(r&&!(r in gt)){s.error(`Unknown --provider "${r}". Use: figma, framer, stitch or web.`),process.exitCode=1;return}if(i.source&&!Gc.includes(i.source)){s.error(`Unknown --source "${i.source}". Use: ${Gc.join(", ")}.`),process.exitCode=1;return}let a=r??Wc(o)??"figma",c=gt[a],l=Bu(o),d=l?l.startsWith(n+X.sep)?X.relative(n,l):l:void 0,m=null,p=d??o;if(l)s.info(` ${Y.pass} Local design file ${S.dim(d)} ${S.dim("(no Figma MCP)")}`);else if(a==="figma"){let M=no("Parsing Figma URL...").start();try{m=Xn(o),M.succeed(`Parsed Figma URL ${S.dim(m.nodeId?`node ${m.nodeId}`:`file ${m.fileKey}`)}`)}catch($e){M.fail($e.message),process.exitCode=1;return}}else s.info(` ${Y.pass} ${c} design ${S.dim(p)}`);let u=i.name||(l?Ui(X.basename(l,X.extname(l))):m?Ui(m.fileName):o?Ui(Iu(o)):"");if(!He.test(u)){s.error(`Invalid block name "${u}". Use --name with a kebab-case name (e.g., --name hero-banner).`),process.exitCode=1;return}!i.name&&m?.nodeId&&(s.warn(`Block name "${u}" came from the Figma file name, not the selected frame.`),s.info(S.dim(` Pass ${S.cyan("--name <kebab-case>")} for a cleaner block name.`)));let g=await ce(n),h=g.figma?.token??process.env.FIGMA_TOKEN??process.env.FIGMA_PAT,$;if(Ni(a)&&!l&&!i.dryRun&&(i.auth||i.authRefresh))if($=Mi(a),i.authRefresh||!Tc(a)){let M=(()=>{try{return new URL(o).origin}catch{return o}})();s.info(` ${S.dim("\u2192")} Opening ${S.cyan(c)} \u2014 click ${S.cyan("Sign In")} and log in, then come back here.`);let{input:$e}=await Promise.resolve().then(()=>(K(),q));try{await Ac($),await dc({loginUrl:M,statePath:$,projectRoot:n,waitForUser:async()=>{await $e({message:"Press Enter once you're signed in (you don't need to open the design)"})}}),await Rc($),s.info(` ${Y.pass} Session saved ${S.dim($)}`)}catch(Be){s.error(`Could not capture the ${c} session: ${Be instanceof Error?Be.message:String(Be)}`),process.exitCode=1;return}}else s.info(` ${Y.pass} Using saved ${c} session ${S.dim($)} ${S.dim("(--auth-refresh to re-login)")}`);let w=no("Resolving design source...").start(),y=await $c({figma:m,localFile:d,token:h,projectRoot:n,preferMcp:i.mcp,refresh:i.refresh,provider:a,designUrl:l?void 0:o,storageStatePath:$,dryRun:i.dryRun,restPerMinute:g.figma?.restPerMinute,onRestWait:M=>{w.text=`Resolving design source... waiting ${Math.ceil(M/1e3)} s for a Figma REST slot (${g.figma?.restPerMinute??Ai}/min)`}});if(y.scrapeError){w.fail(`Scrape failed: ${y.scrapeError}`),s.info(S.dim(` Check the URL is a public ${c} page, and that Chromium is installed (${S.cyan("npx playwright install chromium")}).`)),process.exitCode=1;return}if(y.rateLimit){w.fail(y.rateLimit.message),s.info(S.dim(" The limit follows the plan that owns the file: 20 calls/month on Starter or with a View/Collab seat, 10-20/min with a Dev/Full seat on a paid plan.")),s.info(S.dim(` Not falling back to Figma MCP (its budget is the same or smaller). Re-run after the reset, pass ${S.cyan("--mcp")} to spend an MCP call instead, or export the frame as PNG/SVG (no quota).`)),y.rateLimit.upgradeLink&&s.info(S.dim(` Plan details: ${y.rateLimit.upgradeLink}`)),process.exitCode=1;return}if(w.succeed(`Design source ${S.dim(y.summary)}`),y.restError&&s.warn(`Figma REST fetch failed, using MCP fallback: ${y.restError}`),y.design?.mode==="scrape"&&!i.dryRun)try{let M=JSON.parse(y.design.spec),$e=(M.title??"").toLowerCase(),Be=y.design.spec.toLowerCase(),br=/isn'?t shared|doesn'?t exist|page not found|\b404\b/;(br.test($e)||br.test(Be)||/\bsign[ -]?in\b|\blog[ -]?in\b/.test($e)||(M.nodeCount??0)<8)&&(s.warn(`The scraped page looks like a login / error shell${M.title?` ("${M.title}")`:""} \u2014 the design may be gated or the URL wrong.`),s.info(S.dim(` Use ${S.cyan("--auth")} to log in once (or ${S.cyan("--auth-refresh")} to re-login), and confirm the URL opens the design when you're signed in.`)))}catch{}let b=no("Reading design tokens & building prompt...").start(),T=await Ec({provider:a,figma:m,designRef:p,blockName:u,projectRoot:n,withUeModel:i.ueModel!==!1,contentSource:i.source??"document",cfHint:i.cfHint,screenshot:i.screenshot===!0,design:y.design}),D=await Xt(T,n),O=le(X.join(n,"styles","styles.css"));if(b.succeed(O?`Loaded design tokens ${S.dim("styles/styles.css")}`:`Built prompt ${S.dim("no project tokens found")}`),s.info(S.dim(` prompt \u2192 ${D}`)),i.dryRun){if(s.info(""),s.info(S.yellow("Dry run mode \u2014 prompt generated but agent not invoked.")),s.info(`Prompt file: ${S.cyan(D)}`),s.info(`Block name: ${S.cyan(u)}`),s.info(`Prompt version: ${tn}`),s.info(""),s.info("Preview:"),B.emit({type:"prompt",file:D,block:u}),B.enabled)return;s.info(S.dim("\u2500".repeat(60))),console.log(T);return}let ne=i.agent||g.agent;if(i.agent==="none"){s.info("Agent skipped (--agent none). Use the prompt file manually:"),s.info(` ${S.cyan(D)}`);return}let Ue=no("Detecting AI agent...").start(),F=await Gn(ne);if(!F){Ue.fail("No AI agent found (claude, cursor, codex, or a local Ollama / oMLX server)."),s.info(`Install Claude Code: ${S.cyan("npm install -g @anthropic-ai/claude-code")}`),s.info(`Or run a local model: ${S.cyan("ollama serve")} / ${S.cyan("omlx start")}, then ${S.cyan("--agent ollama")} or ${S.cyan("--agent omlx")}.`),s.info(`Or use the prompt file manually: ${S.cyan(D)}`),process.exitCode=1;return}let xe=ye(F.type);Ue.succeed(`Agent ready ${S.cyan(F.type)} ${S.dim(xe?`${i.model??F.model} \xB7 ${F.path}`:F.path)}`);let hr=y.design?.mode==="mcp"||!y.design&&a==="figma";if(xe&&hr){s.error("A local model can't read a Figma design through MCP."),s.info(S.dim(` Set a Figma token (${S.cyan("FIGMA_TOKEN")}) so eds fetches it over REST, export the frame as PNG/SVG, or scrape a Framer / Stitch page. Prompt saved: ${D}`)),process.exitCode=1;return}if(hr&&a==="figma"&&!F.hasFigmaMcp&&(s.warn(`Figma MCP may not be configured for ${F.type}.`),s.info(`Run ${S.cyan("eds figma setup")} to configure it, or set a Figma token for REST.`)),!i.yes){let{confirm:M}=await Promise.resolve().then(()=>(K(),q));if(!await M({message:`Run ${F.type} with the generated prompt?`,default:!0})){s.info(`Prompt saved to: ${S.cyan(D)}`);return}}let Tl=y.design?.mode==="spec"?"embedded design (no MCP)":y.design?.mode==="scrape"?`scraped ${c} page (no MCP)`:y.design?.mode==="file"?`reading ${d}`:y.design?.mode==="mcp"?`via ${c} MCP (1 call, cached)`:`via ${c} MCP`;s.info(` ${S.dim("\u2192")} Handing off to ${S.cyan(F.type)} ${S.dim(Tl)}`),y.design?.mode==="mcp"&&s.info(S.dim(" get_design_context \xD71 \u2192 cache"));let Al=i.source==="cf"||i.source==="mixed",Pt=xe?i.model??F.model:i.model??g.model??(Al&&F.type==="claude"?"sonnet":void 0);Pt&&!xe&&!i.model&&!g.model&&s.info(S.dim(` Model: ${Pt} (Content Fragment source)`));let wr={blockName:u,designFile:y.design?.mode==="file"?d:void 0,contextTokens:g.local?.contextTokens,apiKey:g.local?.apiKey};if(i.draft){await zc({projectRoot:n,blockName:u,run:()=>ut(F,D,n,Pt,wr),verify:M=>Hi(M,u,i.ueModel!==!1,i.source??"document"),writeMeta:M=>Bi(M,{widths:i.widths,provider:a,designRef:p,figma:m,agentType:F.type}),source:{provider:a,designRef:p,figma:m,agent:F.type,model:Pt}});return}if(!await ut(F,D,n,Pt,wr)){process.exitCode=1;return}let fn=X.join(n,"blocks",u);if(!(le(X.join(fn,`${u}.js`))||le(X.join(fn,`${u}.css`)))){s.warn(`No block files were written to blocks/${u}/ \u2014 nothing to preview.`),y.design?.mode==="mcp"&&!F.hasFigmaMcp?(s.info(S.dim(` The agent couldn't read the design: no ${c} MCP is configured for ${F.type}.`)),s.info(S.dim(` Run ${S.cyan("eds figma setup")}, or set a Figma token (FIGMA_TOKEN) to use REST, then re-run.`))):y.design?.mode==="mcp"?(s.info(S.dim(" The agent couldn't read the design, so it generated nothing. Common cause: the")),s.info(S.dim(` ${c} MCP tool-call limit (e.g. Figma Starter plan). See the log above.`)),s.info(S.dim(" Wait for the limit to reset or upgrade the plan, then re-run the same command."))):s.info(S.dim(" The agent generated nothing \u2014 see the log above for why.")),process.exitCode=1;return}let Rl=await Hi(fn,u,i.ueModel!==!1,i.source??"document");if(await Bi(fn,{widths:i.widths,provider:a,designRef:p,figma:m,agentType:F.type}),!Rl){s.warn(`Block "${u}" generated with issues \u2014 review the output above before publishing.`),process.exitCode=1;return}if(s.success(`Block "${u}" generation complete.`),!i.yes){let{confirm:M}=await Promise.resolve().then(()=>(K(),q));if(await M({message:"Instrument this block for analytics (dataLayer)?",default:!1})){let{trackBlock:Be}=await Promise.resolve().then(()=>(Ht(),Bt));await Be(u,{})}}if(!i.yes)await Gu({blockName:u,projectRoot:n,agent:F,model:ye(F.type)?i.model??F.model:i.model??g.model,contextTokens:g.local?.contextTokens,apiKey:g.local?.apiKey,provider:a,figma:m,designRef:p});else if(i.serve){let{previewBlock:M}=await Promise.resolve().then(()=>(Oe(),wt));await M(u,{})}else s.info(` ${S.dim("\u2192")} Next: ${S.cyan(`eds block preview ${u}`)}`)}async function zc(e){let{projectRoot:t,blockName:n}=e,o=X.join(t,"blocks",n),i=await Qa(t,n,e.from),r,a;try{let l=await e.run(),d=le(X.join(o,`${n}.js`))||le(X.join(o,`${n}.css`));if(!l||!d)return s.warn(`No draft was produced for "${n}" \u2014 see the log above.`),process.exitCode=1,null;a=await e.verify(o),await e.writeMeta(o),r=await Za(t,n,{source:e.source,feedback:e.feedback,ok:a})}finally{await i()}a||(process.exitCode=1);let c=Fe(t,n,r);return B.emit({type:"draft",name:n,version:r,ok:a,dir:X.relative(t,c),files:(await Fu(c)).sort(),...e.feedback?{feedback:e.feedback}:{}}),s.success(`Draft "${n}" v${r} ready${a?"":" (with issues \u2014 see above)"}. blocks/${n}/ is unchanged.`),s.info(` ${S.dim("\u2192")} Review: ${S.cyan(`eds draft preview ${n}`)}`),s.info(` ${S.dim("\u2192")} Change: ${S.cyan(`eds draft refine ${n} "<what to change>"`)}`),s.info(` ${S.dim("\u2192")} Accept: ${S.cyan(`eds draft accept ${n} --commit`)}`),r}async function Bi(e,t){if(le(e)){let n=X.join(e,".eds-meta.json"),o;if(le(n))try{o=JSON.parse(await Me(n,"utf-8")).breakpoints}catch{}let i=rc(t.widths,o),r={provider:t.provider,designRef:t.designRef,figmaFileKey:t.figma?.fileKey??null,figmaNodeId:t.figma?.nodeId??null,lastSyncedAt:new Date().toISOString(),promptVersion:tn,agentUsed:t.agentType,...i.length?{breakpoints:i}:{}};await Lu(n,`${JSON.stringify(r,null,2)}
|
|
949
961
|
`),i.length&&s.info(S.dim(` Preview breakpoints: ${i.map(a=>a.width).join(" \xB7 ")}`))}}async function Gu(e){let{select:t,input:n}=await Promise.resolve().then(()=>(K(),q)),{startPreview:o}=await Promise.resolve().then(()=>(Oe(),wt)),i=null;for(s.info("");;){let r=await t({message:"Block ready \u2014 what next?",choices:[{name:"Refine \u2014 describe a change",value:"refine"},{name:i?`Preview open at ${i.url} (reloads on change)`:"Open live preview",value:"preview",disabled:i?"running":!1},{name:"Finish",value:"done"}],default:"refine"});if(r==="done")break;if(r==="preview"){await Mu()?s.info(S.dim(" A preview server is already running at http://127.0.0.1:8777.")):i=await o(e.blockName,{});continue}let a=(await n({message:"Describe the change:"})).trim();if(!a)continue;let c=Yn({blockName:e.blockName,feedback:a,provider:e.provider,figma:e.figma,designRef:e.designRef}),l=await Xt(c,e.projectRoot);s.info(` ${S.dim("\u2192")} Applying your change with ${S.cyan(e.agent.type)}\u2026`),await ut(e.agent,l,e.projectRoot,e.model,{blockName:e.blockName,refine:!0,contextTokens:e.contextTokens,apiKey:e.apiKey})}if(i){let r=i;s.info(S.dim(` Preview still live at ${r.url}. ${on()}
|
|
950
|
-
`)),await nn(r.close)}}async function Hi(e,t,n,o="document"){let i=[],r=X.join(e,`${t}.js`),a=X.join(e,`${t}.css`),c=le(r),l=le(a);if(i.push({status:c?"pass":"fail",name:`${t}.js`,message:c?"created":"missing \u2014 agent did not write the JS file"}),i.push({status:l?"pass":"fail",name:`${t}.css`,message:l?"created":"missing \u2014 agent did not write the CSS file"}),c){let m=await Me(r,"utf-8");i.push({status:/export\s+default/.test(m)?"pass":"fail",name:"decorate export",message:/export\s+default/.test(m)?"found":"no default export \u2014 block won't load"}),m.includes("console.log")&&i.push({status:"warn",name:"no console.log",message:"found console.log \u2014 remove before production"})}if(l){let m=await Me(a,"utf-8");i.push({status:m.includes(`.${t}`)?"pass":"warn",name:"scoped CSS",message:m.includes(`.${t}`)?`scoped to .${t}`:`no .${t} selector \u2014 styles may leak`})}if(n){let m=le(X.join(e,`_${t}.json`)),p=X.join(e,"..","..","component-models.json"),u=!1;if(!m&&le(p))try{u=(await Me(p,"utf-8")).includes(`"${t}"`)}catch{}let g=m||u;if(i.push({status:g?"pass":"warn",name:"Universal Editor model",message:g?m?`_${t}.json created`:"added to component-models.json":`missing \u2014 no _${t}.json (run with default UE generation, or --no-ue-model to skip)`}),m&&c)try{let h=await Me(X.join(e,`_${t}.json`),"utf-8"),$=await Me(r,"utf-8"),w=/"resourceType"\s*:\s*"[^"]*\/item"/.test(h)||/"filter"\s*:/.test(h)||/"multi"\s*:\s*true/.test(h),y=/\.children/.test($)||/\bfor\s*\(/.test($)||/\.forEach\s*\(/.test($);w&&i.push({status:y?"pass":"warn",name:"multifield wired",message:y?"decorate() iterates items":"repeatable model but decorate() never iterates block.children \u2014 only one item will render"})}catch{}}if((o==="cf"||o==="mixed")&&c){let m=await Me(r,"utf-8"),p=X.join(e,`_${t}.json`),g=(le(p)?await Me(p,"utf-8"):"").includes("aem-content-fragment"),h=/\bfetch\s*\(/.test(m);i.push({status:g&&h?"pass":"warn",name:"content fragment",message:g&&h?"CF field in the model, fetched in decorate()":[!g&&"no aem-content-fragment field in the model",!h&&"decorate() never fetches the fragment"].filter(Boolean).join("; ")})}s.info(j("Verification"));let d=I(i.map(m=>m.name));for(let m of i)s.info(R(m.status,m.name,m.message,d));return s.info(""),!i.some(m=>m.status==="fail")}var Gc,Uu,io=v(()=>{"use strict";f();
|
|
951
|
-
`).pop()}`),s.info(Qe.dim(` The files are in blocks/${e}/; commit them yourself.`)),process.exitCode=1}}async function Vu(e){let t=sn();t&&(await nc(t,e)?(B.emit({type:"discarded",name:e}),s.success(`Discarded draft "${e}". blocks/ is unchanged.`)):(s.error(`No draft "${e}".`),process.exitCode=1))}var Wi,yt=v(()=>{"use strict";f();
|
|
952
|
-
npm i -D playwright pixelmatch pngjs && npx playwright install chromium`});var sl={};U(sl,{visualTest:()=>ef});import{existsSync as nl}from"fs";import{mkdir as qi,readFile as ol,writeFile as ln}from"fs/promises";import ke from"path";import Ki from"chalk";async function ef(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}if(t.design){await tf(n,e,t);return}let o=e?[e]:await Ye(n);if(!o.length){s.warn("No previewable blocks to test.");return}let i=Number.parseInt(t.port??"8788",10),r=await ht(n,t.widths,Number.isFinite(i)?i:8788),a=Number.parseFloat(t.threshold??"0.01"),c=ke.join(n,"tmp","eds-cli","visual-diff");s.logoOnce(A("Visual test"));let l=0,d=0,m=0,p=0;try{for(let u of o){let g=await ve(n,u,t.widths);if(g){s.info(j(u));for(let h of g.breakpoints){let $=await
|
|
962
|
+
`)),await nn(r.close)}}async function Hi(e,t,n,o="document"){let i=[],r=X.join(e,`${t}.js`),a=X.join(e,`${t}.css`),c=le(r),l=le(a);if(i.push({status:c?"pass":"fail",name:`${t}.js`,message:c?"created":"missing \u2014 agent did not write the JS file"}),i.push({status:l?"pass":"fail",name:`${t}.css`,message:l?"created":"missing \u2014 agent did not write the CSS file"}),c){let m=await Me(r,"utf-8");i.push({status:/export\s+default/.test(m)?"pass":"fail",name:"decorate export",message:/export\s+default/.test(m)?"found":"no default export \u2014 block won't load"}),m.includes("console.log")&&i.push({status:"warn",name:"no console.log",message:"found console.log \u2014 remove before production"})}if(l){let m=await Me(a,"utf-8");i.push({status:m.includes(`.${t}`)?"pass":"warn",name:"scoped CSS",message:m.includes(`.${t}`)?`scoped to .${t}`:`no .${t} selector \u2014 styles may leak`})}if(n){let m=le(X.join(e,`_${t}.json`)),p=X.join(e,"..","..","component-models.json"),u=!1;if(!m&&le(p))try{u=(await Me(p,"utf-8")).includes(`"${t}"`)}catch{}let g=m||u;if(i.push({status:g?"pass":"warn",name:"Universal Editor model",message:g?m?`_${t}.json created`:"added to component-models.json":`missing \u2014 no _${t}.json (run with default UE generation, or --no-ue-model to skip)`}),m&&c)try{let h=await Me(X.join(e,`_${t}.json`),"utf-8"),$=await Me(r,"utf-8"),w=/"resourceType"\s*:\s*"[^"]*\/item"/.test(h)||/"filter"\s*:/.test(h)||/"multi"\s*:\s*true/.test(h),y=/\.children/.test($)||/\bfor\s*\(/.test($)||/\.forEach\s*\(/.test($);w&&i.push({status:y?"pass":"warn",name:"multifield wired",message:y?"decorate() iterates items":"repeatable model but decorate() never iterates block.children \u2014 only one item will render"})}catch{}}if((o==="cf"||o==="mixed")&&c){let m=await Me(r,"utf-8"),p=X.join(e,`_${t}.json`),g=(le(p)?await Me(p,"utf-8"):"").includes("aem-content-fragment"),h=/\bfetch\s*\(/.test(m);i.push({status:g&&h?"pass":"warn",name:"content fragment",message:g&&h?"CF field in the model, fetched in decorate()":[!g&&"no aem-content-fragment field in the model",!h&&"decorate() never fetches the fragment"].filter(Boolean).join("; ")})}s.info(j("Verification"));let d=I(i.map(m=>m.name));for(let m of i)s.info(R(m.status,m.name,m.message,d));return s.info(""),!i.some(m=>m.status==="fail")}var Gc,Uu,io=v(()=>{"use strict";f();zn();$i();Vt();fe();Ci();Se();sc();Sc();jc();Vn();Oi();N();V();nt();Dc();Ti();Zn();H();Gc=["document","ue","cf","mixed"],Uu=new Set([".svg",".png",".jpg",".jpeg",".webp"])});var bt={};U(bt,{draftAccept:()=>Ku,draftDiscard:()=>Vu,draftList:()=>zu,draftPreview:()=>Ju,draftRefine:()=>qu});import{existsSync as Wu}from"fs";import Jc from"path";import Qe from"chalk";function sn(){let e=E();return e||(s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1),e??null}async function Gi(e,t){let n=await ft(e,t);return n||(s.error(`No draft "${t}". Create one with: eds block from-design <design> --name ${t} --draft`),process.exitCode=1),n}async function zu(){let e=sn();if(!e)return;let t=await Ya(e);if(B.emit({type:"drafts",drafts:t}),s.info(j("Drafts",`${t.length} in tmp/eds-cli/drafts/`)),!t.length){s.info(Qe.dim(" None. Start one with: eds block from-design <design> --name <block> --draft"));return}let n=I(t.map(o=>o.name));for(let o of t){let i=o.versions.at(-1),r=o.status==="accepted"?`accepted v${o.accepted?.version}`:`${o.versions.length} version${o.versions.length===1?"":"s"}, latest v${i?.version}${i?.ok===!1?" (issues)":""}`;s.info(P(o.name,`${r}${i?.feedback?` \xB7 "${i.feedback}"`:""}`,n))}}async function Ju(e,t){let n=sn();if(!n)return;let o=await Gi(n,e);if(!o)return;let i=Wi(t.version)??o.versions.at(-1)?.version;if(!i||!Wu(Fe(n,e,i))){s.error(`Draft "${e}" has no version ${t.version??""}.`.trim()),process.exitCode=1;return}s.info(Qe.dim(` Draft "${e}" v${i} (not in blocks/ until accepted)`));let{previewBlock:r}=await Promise.resolve().then(()=>(Oe(),wt));await r(e,{...t,blockDir:Fe(n,e,i),version:i})}async function qu(e,t,n){let o=sn();if(!o)return;let i=await Gi(o,e);if(!i)return;if(!t?.trim()){s.error('Say what to change: eds draft refine <name> "<what to change>"'),process.exitCode=1;return}let r=Wi(n.version)??i.versions.at(-1)?.version;if(!r||!i.versions.some(h=>h.version===r)){s.error(`Draft "${e}" has no version ${n.version??""}.`.trim()),process.exitCode=1;return}let a=await ce(o),c=await Gn(n.agent||i.source.agent||a.agent);if(!c){s.error("No AI agent found (claude, cursor, codex, or a local Ollama / oMLX server)."),process.exitCode=1;return}let l=ye(c.type)?n.model??c.model:n.model??i.source.model??a.model,d=Yn({blockName:e,feedback:t.trim(),provider:i.source.provider,figma:i.source.figma??null,designRef:i.source.designRef}),m=await Xt(d,o);s.info(` ${Qe.dim("\u2192")} Round on v${r} with ${Qe.cyan(c.type)}: ${Qe.dim(t.trim())}`);let{generateDraft:p,verifyGeneratedBlock:u,writeBlockMeta:g}=await Promise.resolve().then(()=>(io(),oo));await p({projectRoot:o,blockName:e,from:r,feedback:t.trim(),source:{...i.source,agent:c.type,model:l},run:()=>ut(c,m,o,l,{blockName:e,refine:!0,contextTokens:a.local?.contextTokens,apiKey:a.local?.apiKey}),verify:h=>u(h,e,!0,"document"),writeMeta:h=>g(h,{provider:i.source.provider,designRef:i.source.designRef,figma:i.source.figma??null,agentType:c.type})})}async function Ku(e,t){let n=sn();if(!n||!await Gi(n,e))return;let o;try{o=await ec(n,e,Wi(t.version))}catch(i){s.error(i.message),process.exitCode=1;return}if(s.success(`Accepted "${e}" v${o.version} \u2192 blocks/${e}/`),!t.commit&&!t.branch){B.emit({type:"accepted",name:e,version:o.version}),s.info(Qe.dim(" Not committed. Commit it yourself, or re-run with --commit [--branch <name>]."));return}try{let{execa:i}=await import("execa"),r=c=>i("git",c,{cwd:n});if(t.branch){let c=await r(["rev-parse","--verify","--quiet",`refs/heads/${t.branch}`]).then(()=>!0,()=>!1);await r(c?["switch",t.branch]:["switch","-c",t.branch])}await r(["add","--",Jc.join("blocks",e)]),await r(["commit","-m",oc(o.draft,o.version),"--",Jc.join("blocks",e)]);let a=(await r(["rev-parse","--short","HEAD"])).stdout.trim();await tc(n,e,a),B.emit({type:"accepted",name:e,version:o.version,commit:a,...t.branch?{branch:t.branch}:{}}),s.success(`Committed ${a}${t.branch?` on ${t.branch}`:""}.`)}catch(i){let r=i;s.error(`Commit failed: ${(r.stderr||r.message).trim().split(`
|
|
963
|
+
`).pop()}`),s.info(Qe.dim(` The files are in blocks/${e}/; commit them yourself.`)),process.exitCode=1}}async function Vu(e){let t=sn();t&&(await nc(t,e)?(B.emit({type:"discarded",name:e}),s.success(`Discarded draft "${e}". blocks/ is unchanged.`)):(s.error(`No draft "${e}".`),process.exitCode=1))}var Wi,yt=v(()=>{"use strict";f();zn();$i();Vt();fe();Ci();Se();Oi();N();V();H();Wi=e=>e?Number.parseInt(e.replace(/^v/i,""),10):void 0});var qc={};U(qc,{listBlocks:()=>Qu});import{existsSync as an}from"fs";import{readFile as Xu,readdir as Yu}from"fs/promises";import vt from"path";import kt from"chalk";async function Qu(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=vt.join(t,"blocks");if(!an(n)){s.info("No blocks/ directory found.");return}let o=await Yu(n,{withFileTypes:!0}),i=[];for(let a of o){if(!a.isDirectory())continue;let c=a.name,l=vt.join(n,c),d={name:c,hasJs:an(vt.join(l,`${c}.js`)),hasCss:an(vt.join(l,`${c}.css`)),hasUeModel:an(vt.join(l,`_${c}.json`))},m=vt.join(l,".eds-meta.json");if(an(m))try{let p=JSON.parse(await Xu(m,"utf-8"));d.figmaSource={fileKey:p.figmaFileKey,nodeId:p.figmaNodeId,lastSyncedAt:p.lastSyncedAt}}catch{}i.push(d)}if(e.json){console.log(JSON.stringify(i,null,2));return}if(i.length===0){s.info("No blocks found.");return}s.info(j("Blocks",`${i.length} in project`));let r=I(i.map(a=>a.name));for(let a of i){let c=[a.hasJs?_.ok("js"):kt.dim.strikethrough("js"),a.hasCss?_.ok("css"):kt.dim.strikethrough("css")];a.hasUeModel&&c.push(_.blue("ue-model")),a.figmaSource&&c.push(`${Y.figma} ${_.dotPurple("figma")}`);let l=Et(kt.bold(a.name),r);if(s.info(` ${l} ${kt.dim("[")}${c.join(" ")}${kt.dim("]")}`),a.figmaSource){let d=new Date(a.figmaSource.lastSyncedAt).toLocaleDateString();s.info(` ${" ".repeat(r)} ${Y.arrow} ${kt.dim(`figma:${a.figmaSource.fileKey} \xB7 synced ${d}`)}`)}}s.info("")}var Kc=v(()=>{"use strict";f();N();V();H()});import Vc from"path";function zi(e,t){return Vc.join(e,"blocks",t,"__snapshots__")}function Yc(e,t,n){return Vc.join(zi(e,t),`${t}-${n}.png`)}function cn(e){return`${(e*100).toFixed(2)}%`}async function Ji(e,t,n,o=900){let i;try{({chromium:i}=await import("playwright"))}catch{throw new Error(Xc)}let r=await i.launch();try{let a=await r.newPage({viewport:{width:t,height:o}});await a.goto(e,{waitUntil:"networkidle"}),await a.waitForTimeout(300);let c=n?a.locator(n).first():null;return c&&await c.count()?await c.screenshot():await a.screenshot({fullPage:!0})}finally{await r.close()}}async function Qc(){try{let e="pngjs",t="pixelmatch",{PNG:n}=await import(e),o=(await import(t)).default;return{PNG:n,pixelmatch:o}}catch{throw new Error(Xc)}}async function Zc(e,t){let{PNG:n,pixelmatch:o}=await Qc(),i=n.sync.read(e),r=n.sync.read(t);if(i.width!==r.width||i.height!==r.height)return{diffPixels:-1,totalPixels:0,ratio:1,sizeMismatch:!0,width:i.width,height:i.height,otherWidth:r.width,otherHeight:r.height};let{width:a,height:c}=i,l=new n({width:a,height:c}),d=o(i.data,r.data,l.data,a,c,{threshold:.1}),m=a*c;return{diffPixels:d,totalPixels:m,ratio:m?d/m:0,width:a,height:c,diffPng:n.sync.write(l)}}async function el(e,t){let{PNG:n,pixelmatch:o}=await Qc(),i=n.sync.read(e),r=n.sync.read(t),a=Math.min(i.width,r.width),c=Math.min(i.height,r.height),l=new n({width:a,height:c}),d=new n({width:a,height:c});n.bitblt(i,l,0,0,a,c,0,0),n.bitblt(r,d,0,0,a,c,0,0);let m=new n({width:a,height:c}),p=o(l.data,d.data,m.data,a,c,{threshold:.1}),u=a*c;return{diffPixels:p,totalPixels:u,ratio:u?p/u:0,width:a,height:c,diffPng:n.sync.write(m)}}var Xc,tl=v(()=>{"use strict";f();Xc=`Visual testing needs extra tools. Install them with:
|
|
964
|
+
npm i -D playwright pixelmatch pngjs && npx playwright install chromium`});var sl={};U(sl,{visualTest:()=>ef});import{existsSync as nl}from"fs";import{mkdir as qi,readFile as ol,writeFile as ln}from"fs/promises";import ke from"path";import Ki from"chalk";async function ef(e,t={}){let n=E();if(!n){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}if(t.design){await tf(n,e,t);return}let o=e?[e]:await Ye(n);if(!o.length){s.warn("No previewable blocks to test.");return}let i=Number.parseInt(t.port??"8788",10),r=await ht(n,t.widths,Number.isFinite(i)?i:8788),a=Number.parseFloat(t.threshold??"0.01"),c=ke.join(n,"tmp","eds-cli","visual-diff");s.logoOnce(A("Visual test"));let l=0,d=0,m=0,p=0;try{for(let u of o){let g=await ve(n,u,t.widths);if(g){s.info(j(u));for(let h of g.breakpoints){let $=await Ji(il(r.url,u),h.width,rl(u)),w=Yc(n,u,h.width),y=nl(w);if(t.update||!y){await qi(zi(n,u),{recursive:!0}),await ln(w,$),y?(p++,s.info(R("pass",`${h.width}px`,"baseline updated"))):(m++,s.info(R("pass",`${h.width}px`,"baseline created")));continue}let b=await Zc(await ol(w),$);if(b.sizeMismatch){d++;let T=b.height===Zu&&(b.otherHeight??0)<b.height;s.info(R("fail",`${h.width}px`,T?`baseline is an older full-page shot (${b.width}\xD7${b.height}) \u2014 re-run with --update`:`size changed ${b.width}\xD7${b.height} \u2192 ${b.otherWidth}\xD7${b.otherHeight}`));continue}if(b.ratio>a){d++,await qi(c,{recursive:!0});let T=ke.join(c,`${u}-${h.width}.diff.png`);b.diffPng&&await ln(T,b.diffPng),s.info(R("fail",`${h.width}px`,`${cn(b.ratio)} changed \u2192 ${ke.relative(n,T)}`))}else l++,s.info(R("pass",`${h.width}px`,b.ratio>0?`${cn(b.ratio)} (within ${cn(a)})`:"identical"))}}}}catch(u){s.error(u instanceof Error?u.message:String(u)),process.exitCode=1;return}finally{await r.close()}s.info(""),s.info(`${Ki.green(`${l} passed`)} \xB7 ${Ki.yellow(`${d} changed`)} \xB7 ${m} new \xB7 ${p} updated`),d>0&&(s.warn(`${d} visual change(s). Review the diff PNGs in tmp/eds-cli/visual-diff/, then re-run with --update to accept.`),process.exitCode=1)}async function tf(e,t,n){if(!t){s.error("Design diff needs a block name: eds block test <name> --design"),process.exitCode=1;return}let o=await ve(e,t,n.widths);if(!o){s.error(`Block "${t}" has no css/js to render.`),process.exitCode=1;return}let i,r,a=ke.join(e,"blocks",t,".eds-meta.json");if(nl(a))try{let g=JSON.parse(await ol(a,"utf-8"));i=g.figmaFileKey??void 0,r=g.figmaNodeId??void 0}catch{}if(!i||!r){s.error(`"${t}" has no Figma source in .eds-meta.json \u2014 can't fetch the design image.`),process.exitCode=1;return}let c=await ce(e),l=c.figma?.token??process.env.FIGMA_TOKEN??process.env.FIGMA_PAT;if(!l){s.error("Design diff needs a Figma token (FIGMA_TOKEN or figma.token) to render the node."),process.exitCode=1;return}let d=o.breakpoints.filter(g=>g.figma),m=(d.length?d:o.breakpoints).reduce((g,h)=>h.width>g.width?h:g,o.breakpoints[0]).width,p=Number.parseInt(n.port??"8788",10),u=await ht(e,n.widths,Number.isFinite(p)?p:8788);s.logoOnce(A("Design \u2194 render")),s.info(j(t,`${m}px`));try{let g=await Ji(il(u.url,t),m,rl(t));s.info(R("pass","render","block screenshot captured"));let h=await bc({fileKey:i,nodeId:r,token:l,scale:1,pace:()=>Kn({logPath:qn(e),perMinute:c.figma?.restPerMinute,onWait:y=>s.info(R("warn","design",`waiting ${Math.ceil(y/1e3)} s for a Figma REST slot`))})});s.info(R("pass","design","Figma image fetched (REST)"));let $=await el(h,g),w=ke.join(e,"tmp","eds-cli","visual-diff");await qi(w,{recursive:!0}),await ln(ke.join(w,`${t}-design.png`),h),await ln(ke.join(w,`${t}-render.png`),g),$.diffPng&&await ln(ke.join(w,`${t}-design-diff.png`),$.diffPng),s.info(R("warn","diff",`~${cn($.ratio)} different over ${$.width}\xD7${$.height} (approximate)`)),s.info(""),s.info(Ki.dim(` Saved design / render / diff to ${ke.relative(e,w)}/${t}-*.png \u2014 compare side by side.`))}catch(g){s.error(g instanceof Error?g.message:String(g)),process.exitCode=1}finally{await u.close()}}var il,rl,Zu,al=v(()=>{"use strict";f();fe();Vn();Li();N();tl();V();H();Oe();il=(e,t)=>`${e}${Ne.slice(1)}${t}`,rl=e=>`.${e}-wrapper > .${e}`,Zu=900});async function cl(e,t,n){let o;try{({chromium:o}=await import("playwright"))}catch{throw new Error(nf)}let i=await o.launch();try{let r=await i.newPage({viewport:{width:t,height:900}});await r.goto(e,{waitUntil:"networkidle"}),await r.waitForTimeout(200);let a=await r.evaluate(of);return n&&a.push(...await r.evaluate(`(${rf})(${JSON.stringify(n)})`)),a}finally{await i.close()}}var nf,of,rf,ll=v(()=>{"use strict";f();nf=`Content checks need Playwright. Install it with:
|
|
953
965
|
npm i -D playwright && npx playwright install chromium`,of=`(() => {
|
|
954
966
|
const out = [];
|
|
955
967
|
const root = document.querySelector('[class$="block"]') || document.body;
|
|
@@ -1112,15 +1124,15 @@ document.head.appendChild(s);`}]});var Yi={};U(Yi,{integrate:()=>df});import{exi
|
|
|
1112
1124
|
// ${r.name} (eds integrate)
|
|
1113
1125
|
${r.code(a)}
|
|
1114
1126
|
`:ul(r.name,r.code(a)),d=so.join(t,"scripts","delayed.js");await gl(so.dirname(d),{recursive:!0});let m=af(d)?await cf(d,"utf-8"):lf;await hl(d,`${m.replace(/\s*$/,"")}
|
|
1115
|
-
${l}`),s.info(j("Added"));for(let p of c)s.info(P(r.name,`wrote ${p}`));s.info(P(r.name,"wired into scripts/delayed.js")),s.info(""),s.info(Xi.dim(" Loads after LCP (delayed phase) - zero impact on your Core Web Vitals.")),(r.id==="gtm"||r.id==="ga4")&&s.info(Xi.dim(" Tip: gate analytics behind user consent (add the Cookiebot integration).")),r.id==="chat"&&s.info(Xi.dim(" The widget loads only when the visitor clicks the button (facade pattern).")),s.info(""),s.info(
|
|
1127
|
+
${l}`),s.info(j("Added"));for(let p of c)s.info(P(r.name,`wrote ${p}`));s.info(P(r.name,"wired into scripts/delayed.js")),s.info(""),s.info(Xi.dim(" Loads after LCP (delayed phase) - zero impact on your Core Web Vitals.")),(r.id==="gtm"||r.id==="ga4")&&s.info(Xi.dim(" Tip: gate analytics behind user consent (add the Cookiebot integration).")),r.id==="chat"&&s.info(Xi.dim(" The widget loads only when the visitor clicks the button (facade pattern).")),s.info(""),s.info(z(["Integration added"]))}var lf,Qi=v(()=>{"use strict";f();fl();N();V();H();lf=`// delayed.js - third-party / non-critical scripts.
|
|
1116
1128
|
// Loaded in the EDS delayed phase (after LCP), so nothing here blocks the page.
|
|
1117
1129
|
`});var Zi={};U(Zi,{figmaSetup:()=>ff});import{existsSync as mf}from"fs";import{mkdir as pf,writeFile as uf}from"fs/promises";import pe from"chalk";async function ff(){let{select:e,confirm:t}=await Promise.resolve().then(()=>(K(),q));s.logoOnce(A()),s.info(j("Figma MCP Setup Wizard")),s.info("Detecting installed AI agents...");let n=await Wn(),o;if(n.length===0?(s.warn("No AI agents found (claude, cursor, codex)."),s.info(`Install Claude Code: ${pe.cyan("npm install -g @anthropic-ai/claude-code")}`),o="none"):(s.success(`Found: ${n.map(r=>pe.cyan(r.type)).join(", ")}`),o=await e({message:"Which agent do you want to use with eds-cli?",choices:[...n.map(r=>({name:`${r.type}${r.hasFigmaMcp?pe.green(" (Figma MCP detected)"):""}`,value:r.type})),{name:"None (manual mode)",value:"none"}]})),o!=="none"){let r=n.find(a=>a.type===o);if(r&&!r.hasFigmaMcp){switch(s.warn(`Figma MCP is not configured for ${o}.
|
|
1118
1130
|
`),s.info(`Install it with one of these methods:
|
|
1119
1131
|
`),o){case"claude":s.info(` ${pe.cyan("claude mcp add --transport sse figma-sse https://mcp.figma.com/sse")}`),s.info(" or for Figma Desktop app:"),s.info(` ${pe.cyan("claude mcp add --transport http figma-desktop http://127.0.0.1:3845/mcp")}`);break;case"cursor":s.info(` Add to ${pe.cyan("~/.cursor/mcp.json")}:`),s.info(pe.dim(JSON.stringify({mcpServers:{figma:{url:"https://mcp.figma.com/sse"}}},null,2)));break;case"codex":s.info(" See Figma MCP docs: https://help.figma.com/hc/en-us/articles/32132100833559");break}s.info("")}else r?.hasFigmaMcp&&s.success(`Figma MCP is already configured for ${o}!`)}if(s.info(pe.dim(`
|
|
1120
1132
|
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 r=Da();mf(r)||await pf(r,{recursive:!0});let a={};o!=="none"&&(a.agent=o),await uf(fi(),`${JSON.stringify(a,null,2)}
|
|
1121
1133
|
`,{mode:384}),s.success(`Config saved to ${pe.cyan(fi())}`)}s.info(pe.bold(`
|
|
1122
|
-
Setup complete!`)),o!=="none"&&s.info(`Try: ${pe.cyan('eds block from-design "<figma-url>" --dry-run')}`)}var er=v(()=>{"use strict";f();
|
|
1134
|
+
Setup complete!`)),o!=="none"&&s.info(`Try: ${pe.cyan('eds block from-design "<figma-url>" --dry-run')}`)}var er=v(()=>{"use strict";f();zn();fe();N();H()});var tr={};U(tr,{doctor:()=>hf});import{existsSync as dn}from"fs";import{readFile as mn,readdir as gf}from"fs/promises";import Ze from"path";import{parse as wl}from"yaml";async function hf(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=Or(t);e.json||(s.logoOnce(A("Doctor")),s.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 mn(Ze.join(t,"fstab.yaml"),"utf-8");wl(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=Ze.join(t,"blocks"),u=await gf(p,{withFileTypes:!0}),g="",h=Ze.join(t,"component-models.json");if(dn(h))try{g=await mn(h,"utf-8")}catch{}for(let $ of u){if(!$.isDirectory())continue;let w=$.name,y=Ze.join(p,w,`${w}.js`),b=dn(y);o.push({name:`blocks/${w} has JS`,status:b?"pass":"warn",message:b?"Found":`Missing ${w}.js`}),b&&(await mn(y,"utf-8")).includes("console.log")&&o.push({name:`blocks/${w} no console.log`,status:"warn",message:"Found console.log - remove before production"});let T=dn(Ze.join(p,w,`_${w}.json`)),D=g.includes(`"${w}"`);o.push({name:`blocks/${w} UE model`,status:T||D?"pass":"warn",message:T||D?T?`_${w}.json`:"in component-models.json":"no Universal Editor model - authors can't edit this block in UE"});let O=Ze.join(p,w,".eds-meta.json");if(dn(O))try{let ne=JSON.parse(await mn(O,"utf-8")),Ue=new Date(ne.lastSyncedAt),F=Math.floor((Date.now()-Ue.getTime())/(1e3*60*60*24));o.push({name:`blocks/${w} Figma sync`,status:F>30?"warn":"pass",message:F>30?`Last synced ${F} days ago - design may have changed`:`Synced ${F} days ago`})}catch{o.push({name:`blocks/${w} .eds-meta.json`,status:"warn",message:"Invalid metadata file"})}}}let i=Ze.join(t,"helix-query.yaml");if(dn(i))try{let p=await mn(i,"utf-8");wl(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:gi()?"pass":"warn",message:gi()?"Found":'Missing - run "eds figma setup" to configure'});let r=o.filter(p=>p.status==="fail"),a=o.filter(p=>p.status==="warn");if(e.json){let p={pass:o.filter(u=>u.status==="pass").length,warn:a.length,fail:r.length};console.log(JSON.stringify({projectRoot:t,results:o,summary:p},null,2)),r.length>0&&(process.exitCode=1);return}let c=I(o.map(p=>p.name));for(let p of o)s.info(R(p.status,p.name,p.message,c));let l=o.filter(p=>p.status==="fail"),d=o.filter(p=>p.status==="warn"),m=o.filter(p=>p.status==="pass");s.info(""),s.info(z([je({pass:m.length,warn:d.length,fail:l.length})])),l.length>0&&(process.exitCode=1)}var nr=v(()=>{"use strict";f();fe();N();V();H()});var ir={};U(ir,{auditLoading:()=>bf});import{existsSync as _e}from"fs";import{readFile as xt,readdir as wf,stat as bl}from"fs/promises";import Ie from"path";import or from"chalk";async function bf(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}e.json||(s.logoOnce(A("Loading Audit")),s.info(j("Loading Order Audit",t)));let n=[];if(await yf(t,n),await vf(t,n),await kf(t,n),await xf(t,n),await $f(t,n),await Sf(t,n),e.json){let o={pass:n.filter(i=>i.status==="pass").length,warn:n.filter(i=>i.status==="warn").length,fail:n.filter(i=>i.status==="fail").length,info:n.filter(i=>i.status==="info").length};console.log(JSON.stringify({projectRoot:t,results:n,summary:o},null,2)),o.fail>0&&(process.exitCode=1);return}Pf(n)}async function yf(e,t){let n=Ie.join(e,"head.html");if(!_e(n)){t.push({rule:"head.html exists",status:"warn",message:"Missing head.html"});return}let o=await xt(n,"utf-8"),i=o.split(`
|
|
1123
1135
|
`);for(let l=0;l<i.length;l++){let d=i[l];/<script\b/i.test(d)&&!/type\s*=\s*["']module["']/i.test(d)&&!/<\/script>/.test(d)&&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 a=(o.match(/<link[^>]+rel=["']stylesheet["'][^>]*>/gi)||[]).filter(l=>!l.includes("styles/styles.css")&&!l.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 c=/(?:src|href)=["'](https?:\/\/(?!(?:localhost|127\.0\.0\.1))[^"']+)["']/gi;for(let l of o.matchAll(c)){let d=l[1];d.includes("fonts.googleapis.com")||t.push({rule:"No third-party resources in head.html",status:"warn",message:`Third-party resource: ${d} \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 vf(e,t){let n=Ie.join(e,"scripts","scripts.js");if(!_e(n)){t.push({rule:"scripts/scripts.js exists",status:"warn",message:"Missing scripts.js \u2014 cannot audit loading phases"});return}let o=await xt(n,"utf-8"),i=o.split(`
|
|
1124
1136
|
`),r=/function\s+loadEager|loadEager\s*=/i.test(o),a=/function\s+loadLazy|loadLazy\s*=/i.test(o),c=/function\s+loadDelayed|loadDelayed\s*=/i.test(o);t.push({rule:"loadEager phase exists",status:r?"pass":"fail",message:r?"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:c?"pass":"warn",message:c?"Found":"Missing loadDelayed \u2014 third-party scripts may block LCP",file:"scripts/scripts.js"});let l=o.match(/setTimeout\s*\([^,]+,\s*(\d+)\s*\)/);if(c&&l){let d=Number.parseInt(l[1],10);d<3e3?t.push({rule:"Delayed phase waits >= 3s",status:"warn",message:`delayed.js loads after ${d}ms \u2014 should be >= 3000ms for LCP safety`,file:"scripts/scripts.js"}):t.push({rule:"Delayed phase waits >= 3s",status:"pass",message:`${d}ms delay before loading delayed.js`,file:"scripts/scripts.js"})}if(r){let d=o.match(/loadEager[\s\S]*?(?=function\s|const\s+load|$)/)?.[0]||"";/loadSections\s*\(/.test(d)&&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 d=0;d<i.length;d++){let m=i[d];/import\s.*from\s+['"]https?:\/\//i.test(m)&&t.push({rule:"No third-party imports at top level",status:"warn",message:`Third-party import at line ${d+1} \u2014 move to delayed.js if not critical`,file:"scripts/scripts.js",line:d+1})}if(r){let d=jf(o,"loadEager");d&&/loadHeader|loadFooter/.test(d)&&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 kf(e,t){let n=Ie.join(e,"styles","styles.css");if(!_e(n))return;let i=(await bl(n)).size/1024;t.push({rule:"styles.css size within LCP budget",status:i>40?"warn":"pass",message:`${i.toFixed(1)} KB${i>40?" \u2014 large CSS competes with 100KB LCP budget":""}`,file:"styles/styles.css"});let r=await xt(n,"utf-8");/@import\s/.test(r)&&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 xf(e,t){let n=Ie.join(e,"scripts","delayed.js");if(!_e(n)){t.push({rule:"scripts/delayed.js exists",status:"info",message:"No delayed.js \u2014 third-party scripts should go here"});return}(await xt(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 $f(e,t){let n=Ie.join(e,"blocks");if(!_e(n))return;let o=await wf(n,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let r=i.name,a=Ie.join(n,r,`${r}.js`);if(!_e(a))continue;let c=await xt(a,"utf-8"),l=c.split(`
|
|
1125
|
-
`),d=["jquery","lodash","moment","rxjs","d3","three","gsap","anime","chart.js","swiper"];for(let u=0;u<l.length;u++){let g=l[u].toLowerCase();for(let h of d)g.includes("from")&&g.includes(h)&&/import\s/.test(g)&&t.push({rule:"No heavy imports in blocks",status:"warn",message:`Imports "${h}" \u2014 heavy library delays section loading`,file:`blocks/${r}/${r}.js`,line:u+1})}/document\.write/i.test(c)&&t.push({rule:"No document.write in blocks",status:"fail",message:"document.write blocks parsing and can break the page",file:`blocks/${r}/${r}.js`});let p=(await bl(a)).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/${r}/${r}.js`})}for(let i of o){if(!i.isDirectory())continue;let r=i.name,a=Ie.join(n,r,`${r}.css`);if(!_e(a))continue;let c=await xt(a,"utf-8"),l=/^([a-z][a-z0-9-]*)\s*\{/gm;for(let d of c.matchAll(l)){let m=d[1];["body","html","main"].includes(m)||t.push({rule:"Block CSS is scoped",status:"warn",message:`Bare element selector "${m}" \u2014 may leak styles and cause CLS. Use .${r} prefix`,file:`blocks/${r}/${r}.css`})}}}async function Sf(e,t){let n=Ie.join(e,"scripts","aem.js");if(!_e(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 jf(e,t){let o=new RegExp(`(?:async\\s+)?function\\s+${t}\\s*\\([^)]*\\)\\s*\\{`).exec(e);if(!o)return null;let i=1,r=o.index+o[0].length,a=r;for(;r<e.length&&i>0;)e[r]==="{"?i++:e[r]==="}"&&i--,r++;return e.slice(a,r-1)}function Pf(e){let t=new Map;for(let o of e){let i=o.file||"general",r=t.get(i)??[];r.push(o),t.set(i,r)}for(let[o,i]of t){s.info(` ${Y.bullet} ${or.underline(o)}`);for(let r of i){let a=r.line?or.dim(`:${r.line}`):"";s.info(` ${gn(r.status)} ${r.rule}${a}`),r.status!=="pass"&&s.info(or.dim(` ${r.message}`))}s.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};s.info(
|
|
1126
|
-
`);for(let r=0;r<i.length;r++){let a=i[r],c=!1;for(let l of Tf)l.ext.includes(n)&&(l.id==="innerhtml-static"&&c||l.re.test(a)&&(l.extra&&!l.extra(a)||(l.id==="innerhtml-dynamic"&&(c=!0),o.push({severity:l.severity,rule:l.id,message:l.message,file:t,line:r+1,snippet:a.trim().slice(0,100)}))))}return o}async function Lf(e){if(!ao(et.join(e,"package.json")))return{status:"skipped",note:"no package.json"};if(!(ao(et.join(e,"package-lock.json"))||ao(et.join(e,"npm-shrinkwrap.json")))&&!ao(et.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}),r=JSON.parse(o)?.metadata?.vulnerabilities??{},a={critical:r.critical??0,high:r.high??0,moderate:r.moderate??0,low:r.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 Nf(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=[];for await(let l of vl(t)){let d=et.extname(l).slice(1).toLowerCase();if(!Df.has(d))continue;let m=et.relative(t,l);if(m.endsWith("aem.js")||m.endsWith("lib-franklin.js"))continue;let p=await Ef(l,"utf-8");n.push(...Ff(p,m,d))}let o=await Lf(t),i=l=>n.filter(d=>d.severity===l),r={critical:i("critical").length,high:i("high").length,moderate:i("moderate").length,low:i("low").length},a=r.critical>0||r.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:r}},null,2)),a&&(process.exitCode=1);return}if(s.logoOnce(A("Security Audit")),s.info(j("Dependencies","npm audit")),o.status==="skipped")s.info(R("info","npm audit",o.note??"skipped"));else if(o.status==="ok")s.info(R("pass","npm audit","no known vulnerabilities"));else{let l=o.counts??{critical:0,high:0,moderate:0,low:0};s.info(R(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(s.info(j("Exploit scan","XSS \xB7 secrets \xB7 injection \xB7 tabnabbing")),n.length===0)s.info(R("pass","code","no risky patterns found"));else{let l=[...n].sort((d,m)=>yl.indexOf(d.severity)-yl.indexOf(m.severity));for(let d of l){let m=Af[d.severity],p=sr.dim(`${d.file}:${d.line}`);s.info(` ${gn(m.status)} ${sr.bold(m.label)} ${d.message} ${p}`),s.info(sr.dim(` ${d.snippet}`))}}let c=je({fail:r.critical+r.high+(o.counts?.critical??0)+(o.counts?.high??0),warn:r.moderate+(o.counts?.moderate??0),info:r.low+(o.counts?.low??0)});s.info(""),s.info(J([c||`${Y.pass} no vulnerabilities or risky patterns found`])),a&&(process.exitCode=1)}var Tf,yl,Af,Rf,Df,cr=v(()=>{"use strict";f();N();V();H();Tf=[{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"]}],yl=["critical","high","moderate","low"],Af={critical:{status:"fail",label:"CRIT"},high:{status:"fail",label:"HIGH"},moderate:{status:"warn",label:"MOD "},low:{status:"info",label:"LOW "}},Rf=new Set(["node_modules",".git","dist","build",".vscode","coverage"]),Df=new Set(["js","mjs","html","json","pem","txt"])});async function kl(e,t,n){let o=t.ref||"main",i=n.startsWith("/")?n:`/${n}`,r=`${Of}/${e}/${t.org}/${t.site}/${o}${i}`;s.debug(`POST ${r}`);let a=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"}}),c=await a.json().catch(()=>({})),l=c;return a.ok?{ok:!0,status:a.status,path:i,previewUrl:l.preview?.url,liveUrl:l.live?.url}:{ok:!1,status:a.status,path:i,message:c.message||`HTTP ${a.status}`}}async function lr(e,t){return kl("preview",e,t)}async function dr(e,t){return kl("live",e,t)}async function xl(e,t){return Promise.all(t.map(n=>lr(e,n)))}async function $l(e,t){return Promise.all(t.map(n=>dr(e,n)))}var Of,mr=v(()=>{"use strict";f();N();Of="https://admin.hlx.page"});var pr={};U(pr,{preview:()=>_f,resolveAdminConfig:()=>co});import Sl from"chalk";import Mf from"ora";async function _f(e,t){let n=E(),o=await ce(n),i=co(o,t);if(!i)return;let r=Mf(`Previewing ${e.length} path(s)...`).start(),a=e.length===1?[await lr(i,e[0])]:await xl(i,e);r.stop();let c=!1;for(let l of a)l.ok?s.success(`${l.path} \u2192 ${Sl.cyan(l.previewUrl||"preview updated")}`):(s.error(`${l.path} \u2014 ${l.message}`),c=!0);c&&(process.exitCode=1)}function co(e,t){let n=t.org||e.admin?.org,o=t.site||e.admin?.site,i=t.ref||e.admin?.ref||"main";if(!n||!o){s.error("Missing --org and --site. Set them via flags or in .edsrc.json:"),s.info(Sl.dim(' { "admin": { "org": "my-org", "site": "my-site" } }')),process.exitCode=1;return}return{org:n,site:o,ref:i}}var lo=v(()=>{"use strict";f();mr();fe();N();V()});var ur={};U(ur,{publish:()=>Bf});import If from"chalk";import Uf from"ora";async function Bf(e,t){let n=E(),o=await ce(n),i=co(o,t);if(!i)return;let r=Uf(`Publishing ${e.length} path(s)...`).start(),a=e.length===1?[await dr(i,e[0])]:await $l(i,e);r.stop();let c=!1;for(let l of a)l.ok?s.success(`${l.path} \u2192 ${If.cyan(l.liveUrl||"published")}`):(s.error(`${l.path} \u2014 ${l.message}`),c=!0);c&&(process.exitCode=1)}var fr=v(()=>{"use strict";f();mr();fe();N();V();lo()});var mo={};U(mo,{adminWizard:()=>Hf});async function Hf(e){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Admin API \u2014 preview / publish"));let{select:n,input:o,confirm:i}=await Promise.resolve().then(()=>(K(),q)),a=(await ce(t)).admin??{},c=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:a.org})).trim(),d=(await o({message:"Repository / site",default:a.site})).trim(),m=(await o({message:"Git ref",default:a.ref||"main"})).trim(),u=(await o({message:"Paths (space- or comma-separated)",default:"/"})).split(/[\s,]+/).filter(Boolean);if(!l||!d||u.length===0){s.error("org, site and at least one path are required."),process.exitCode=1;return}s.info(j("Summary"));let g=I(["operation","org","site","ref","paths"]);if(s.info(P("operation",c,g)),s.info(P("org",l,g)),s.info(P("site",d,g)),s.info(P("ref",m,g)),s.info(P("paths",u.join(", "),g)),s.info(""),c==="publish"&&!await i({message:`Publish ${u.length} path(s) to LIVE?`,default:!1})){s.info("Cancelled.");return}let h={org:l,site:d,ref:m};if(c==="preview"){let{preview:$}=await Promise.resolve().then(()=>(lo(),pr));await $(u,h)}else{let{publish:$}=await Promise.resolve().then(()=>(fr(),ur));await $(u,h)}}var po=v(()=>{"use strict";f();fe();N();V();H()});var jl={};U(jl,{mainMenu:()=>Kf});import{existsSync as Gf}from"fs";import{readdir as Wf}from"fs/promises";import Jf from"path";import zf from"chalk";async function gr(e){let t=Jf.join(e,"blocks");return Gf(t)?(await Wf(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name):[]}async function Kf(){let{select:e,isEscape:t,isExit:n}=await Promise.resolve().then(()=>(K(),q));Qn.menu=!0,await s.logoOnceAnimated("");let o;for(;;){s.info(zf.dim(" Esc quits here \xB7 goes back to this menu from any step"));let i;try{i=await e({message:"Choose an action",choices:qf,default:o})}catch(r){if(t(r)||n(r))return;throw r}if(i==="exit")return;o=i;try{await Vf(i)}catch(r){if(n(r))return;t(r)||s.error(r instanceof Error?r.message:String(r))}process.exitCode=void 0,s.info("")}}async function Vf(e){let{select:t,input:n}=await Promise.resolve().then(()=>(K(),q));switch(e){case"new":{let{newProject:o}=await Promise.resolve().then(()=>(Lo(),Fo));await o(void 0,{});return}case"init":{let{initProject:o}=await Promise.resolve().then(()=>(Lt(),Ft));await o({});return}case"template":{let o=await n({message:"Template name",validate:r=>!!r.trim()||"Required"}),{templateNew:i}=await Promise.resolve().then(()=>(Ho(),Bo));await i(o.trim(),{});return}case"sandbox":{let o=await n({message:"Sandbox repo name",validate:r=>/^[a-z0-9][a-z0-9._-]*$/i.test(r.trim())||"Use a valid repo name"}),{sandboxNew:i}=await Promise.resolve().then(()=>(ze(),Je));await i(o.trim(),{});return}case"from-design":{let{blockFromDesign:o}=await Promise.resolve().then(()=>(io(),oo));await o(void 0,{});return}case"migrate":{let{migrateComponent:o}=await Promise.resolve().then(()=>(Xo(),Vo));await o(void 0,{});return}case"scaffold":{let{scaffoldInteractive:o}=await Promise.resolve().then(()=>(ue(),we));await o();return}case"create":{let o=await n({message:"Block name",validate:r=>He.test(r.trim())||"Use kebab-case, e.g. hero-banner"}),{createBlock:i}=await Promise.resolve().then(()=>(mi(),di));await i(o.trim(),{});return}case"integrate":{let{integrate:o}=await Promise.resolve().then(()=>(Qi(),Yi));await o(void 0);return}case"preview-block":{let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found).");return}let i=await gr(o);if(i.length===0){s.warn("No blocks found in blocks/.");return}let r=await t({message:"Which block?",choices:i.map(c=>({name:c,value:c}))}),{previewBlock:a}=await Promise.resolve().then(()=>(Oe(),wt));await a(r,{});return}case"model":{let{modelAdd:o}=await Promise.resolve().then(()=>(ri(),ii));await o(void 0,[],{});return}case"track":{let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found).");return}let i=await gr(o);if(i.length===0){s.warn("No blocks found in blocks/.");return}let r=await t({message:"Which block to instrument?",choices:i.map(c=>({name:c,value:c}))}),{trackBlock:a}=await Promise.resolve().then(()=>(Ht(),Bt));await a(r,{});return}case"schema":{let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found).");return}let i=await gr(o);if(i.length===0){s.warn("No blocks found in blocks/.");return}let r=await t({message:"Which block?",choices:i.map(c=>({name:c,value:c}))}),{schemaBlock:a}=await Promise.resolve().then(()=>(ai(),si));await a(r,{});return}case"ue":{if(await t({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:i}=await Promise.resolve().then(()=>(zt(),Jt));await i()}else{let i=await n({message:"Page path",default:"/"}),{ueOpen:r}=await Promise.resolve().then(()=>(zt(),Jt));await r(i.trim()||"/",{})}return}case"admin":{let{adminWizard:o}=await Promise.resolve().then(()=>(po(),mo));await o();return}case"audit":{let o=await t({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:i}=await Promise.resolve().then(()=>(nr(),tr));await i({})}else if(o==="loading"){let{auditLoading:i}=await Promise.resolve().then(()=>(rr(),ir));await i({})}else{let{auditSecurity:i}=await Promise.resolve().then(()=>(cr(),ar));await i({})}return}case"figma-setup":{let{figmaSetup:o}=await Promise.resolve().then(()=>(er(),Zi));await o();return}}}var qf,Pl=v(()=>{"use strict";f();N();V();nt();Zn();qf=[{name:"New project",value:"new",description:"Clone the latest EDS boilerplate"},{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, Framer or Google Stitch"},{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"},{name:"Exit",value:"exit",description:"Quit eds (or press Esc)"}]});f();import Xf from"chalk";import{Command as Yf}from"commander";var uo={name:"aem-eds-kit",version:"0.4.60",description:"CLI for AEM Edge Delivery Services: blocks from Figma, Framer or Google Stitch designs, AEM component migration (AEMaaCS and 6.5), Universal Editor models and QA",type:"module",engines:{node:">=20"},bin:{eds:"dist/bin/eds.js"},files:["dist","samples","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","aem-edge-delivery","universal-editor","aemaacs","aem-migration","framer","google-stitch","design-to-code","claude-code"],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",pixelmatch:"^6.0.0",playwright:"^1.64.0",pngjs:"^7.0.0"}};Se();N();H();var G=new Yf;G.name("eds").description("CLI for AEM Edge Delivery Services: blocks from Figma, Framer or Stitch designs, AEM migration, Universal Editor models and QA").version(uo.version).option("--verbose","Enable verbose output").option("--quiet","Suppress non-error output").option("--json","Machine-readable output (block from-design and draft: JSON-lines events on stdout)").option("--no-color","Disable color output").showHelpAfterError("(add --help for usage)").hook("preAction",e=>{let t=e.opts();t.verbose&&s.setLevel("debug"),t.quiet&&s.setQuiet(!0),t.color===!1&&(Xf.level=0)});async function $t(e,t){G.opts().json&&(B.enable(),B.emit({type:"start",command:e,cli:uo.version}));try{await t()}catch(n){s.error(n instanceof Error?n.message:String(n)),process.exitCode=1}finally{let n=Number(process.exitCode??0);B.emit({type:"result",ok:n===0,exitCode:n})}}G.addHelpText("beforeAll",()=>A());G.command("new [dir]").description("Clone the latest EDS boilerplate into a local folder (no GitHub auth)").option("--boilerplate <repo>","da | ue | commerce, owner/repo on GitHub, or any git URL (default adobe/aem-boilerplate)").option("--ue","Use the crosswalk / Universal Editor boilerplate").option("--ref <ref>","Branch or tag to clone").option("--keep-history","Keep the boilerplate's git history (remote renamed to upstream)").option("--remote <url>","Set origin to your own repo").option("--install","Run npm install after cloning").option("--yes","Skip the guided prompts").action(async(e,t)=>{let{newProject:n}=await Promise.resolve().then(()=>(Lo(),Fo));await n(e,t)});var pn=G.command("sandbox").description("Disposable EDS sandbox repos on GitHub");pn.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(()=>(ze(),Je));await n(e,t)});pn.command("login").description("Authorize GitHub (OAuth device flow or a token) - no gh needed").action(async()=>{let{sandboxLogin:e}=await Promise.resolve().then(()=>(ze(),Je));await e()});pn.command("logout").description("Remove the stored GitHub token").action(async()=>{let{sandboxLogout:e}=await Promise.resolve().then(()=>(ze(),Je));await e()});pn.command("list").description("List your EDS sandboxes (repos tagged eds-sandbox)").action(async()=>{let{sandboxList:e}=await Promise.resolve().then(()=>(ze(),Je));await e()});pn.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(()=>(ze(),Je));await n(e,t)});var Qf=G.command("template").description("Generate page templates / initial content");Qf.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(()=>(Ho(),Bo));await n(e,t)});G.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(()=>(Lt(),Ft));await t(e)});var Zf=G.command("migrate").description("Migrate from classic AEM to EDS");Zf.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("--super-root <dirs>","jcr_root folder(s), comma-separated, holding a proxy component's super type (e.g. a Core Components checkout)").option("--yes","Skip confirmation prompts").action(async(e,t)=>{let{migrateComponent:n}=await Promise.resolve().then(()=>(Xo(),Vo));await n(e,t)});var eg=G.command("model").description("Compose Universal Editor models");eg.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(()=>(ri(),ii));await o(e,t,n)});var tg=G.command("schema").description("Structured data (JSON-LD) for blocks");tg.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(()=>(ai(),si));await n(e,t)});var ng=G.command("track").description("Instrument blocks for analytics");ng.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(()=>(Ht(),Bt));await n(e,t)});var El=G.command("ue").description("Universal Editor - readiness check + editor deep link");El.command("check").description("Check whether blocks are Universal-Editor-ready (offline)").action(async()=>{let{ueCheck:e}=await Promise.resolve().then(()=>(zt(),Jt));await e()});El.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(()=>(zt(),Jt));await n(e,t)});var St=G.command("block").description("Manage EDS blocks");St.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(()=>(mi(),di));await n(e,t)});St.command("from-design [design]").description("Generate an EDS block from a design: a Figma URL, a Framer/Stitch or any web page (scraped with headless Chromium), 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("--provider <type>","Design source: figma | framer | stitch | web (else detected from the URL)").option("--agent <type>","Force agent type: claude | cursor | codex | ollama | omlx | local (any OpenAI-compatible server) | none").option("--model <name>","Model to run (Claude alias/id, or a local model, e.g. qwen2.5-coder:14b)").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("--auth","Scrape with a logged-in session (Framer/Stitch) \u2014 login captured once, then reused").option("--auth-refresh","Force a fresh scrape login even if a session is saved").option("--sample","Use the bundled sample design (the example file's hero) \u2014 no URL, no token, no MCP").option("--serve","Auto-start the live preview after generating (non-interactive runs only)").option("--draft","Generate a draft (tmp/eds-cli/drafts/<name>/vN) for review; blocks/ changes only on eds draft accept").option("--yes","Skip confirmation prompts").action(async(e,t)=>{await $t("block from-design",async()=>{let{blockFromDesign:n}=await Promise.resolve().then(()=>(io(),oo));await n(e,t)})});var un=G.command("draft").description("Review drafts from `block from-design --draft`: preview, refine, accept or discard");un.command("list").description("List drafts and their versions").action(async()=>{await $t("draft list",async()=>{let{draftList:e}=await Promise.resolve().then(()=>(yt(),bt));await e()})});un.command("preview <name> [version]").description("Preview a draft version in the browser (default: the latest), e.g. hero 2").option("--port <port>","Port to serve on (default 8777)").option("--widths <list>","Breakpoint widths").option("--no-open","Don't open the browser").action(async(e,t,n)=>{await $t("draft preview",async()=>{let{draftPreview:o}=await Promise.resolve().then(()=>(yt(),bt));await o(e,{...n,version:t})})});un.command("refine <name> <feedback>").description("One more agent round on the draft; the result is the next version").option("--from <n>","Start from this version (default: the latest)").option("--agent <type>","Agent (default: the one that made the draft)").option("--model <name>","Model (default: the one that made the draft)").action(async(e,t,n)=>{await $t("draft refine",async()=>{let{draftRefine:o}=await Promise.resolve().then(()=>(yt(),bt)),{from:i,...r}=n;await o(e,t,{...r,version:i})})});un.command("accept <name> [version]").description("Copy a draft version (default: the latest) into blocks/<name>/, optionally commit it").option("--commit","Commit blocks/<name>/ with the review rounds in the message").option("--branch <name>","Commit on this branch (created if missing; implies --commit)").action(async(e,t,n)=>{await $t("draft accept",async()=>{let{draftAccept:o}=await Promise.resolve().then(()=>(yt(),bt));await o(e,{...n,version:t})})});un.command("discard <name>").description("Drop a draft and its versions; blocks/ is untouched").action(async e=>{await $t("draft discard",async()=>{let{draftDiscard:t}=await Promise.resolve().then(()=>(yt(),bt));await t(e)})});St.command("list").description("List all blocks in the project").action(async e=>{let{listBlocks:t}=await Promise.resolve().then(()=>(Kc(),qc));await t({...e,json:G.opts().json})});St.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(()=>(Oe(),wt));e?await n.previewBlock(e,t):await n.galleryPreview(t)});St.command("test [name]").description("Visual-regression test a block (or all blocks) against committed baselines").option("--update","(Re)write the baseline screenshots instead of comparing").option("--threshold <ratio>","Max changed-pixel ratio before failing (default 0.01 = 1%)").option("--design","Compare the rendered block against its Figma design image (needs a token)").option("--widths <list>","Comma-separated breakpoint widths (e.g. 375,768,1280)").option("--port <port>","Port for the internal preview server (default: 8788)").action(async(e,t)=>{let{visualTest:n}=await Promise.resolve().then(()=>(al(),sl));await n(e,t)});St.command("check [name]").description("Content, link and a11y check on a block's rendered DOM (or all blocks)").option("--strict","Fail on warnings too, not just errors").option("--widths <list>","Comma-separated breakpoint widths (uses the widest)").option("--port <port>","Port for the internal preview server (default: 8789)").action(async(e,t)=>{let{blockCheck:n}=await Promise.resolve().then(()=>(ml(),dl));await n(e,t)});var jt=G.command("scaffold").description("Scaffold standard UE components and blocks").action(async()=>{let{scaffoldInteractive:e}=await Promise.resolve().then(()=>(ue(),we));await e()});jt.command("ue").description("Scaffold default-content UE components + a field-reference block (all 17 fields)").action(async()=>{let{scaffoldUe:e}=await Promise.resolve().then(()=>(ue(),we));await e()});jt.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(()=>(ue(),we));await t(e)});jt.command("ci").description("Scaffold a GitHub Actions workflow (doctor + audits + project lint/build)").action(async()=>{let{scaffoldCi:e}=await Promise.resolve().then(()=>(ue(),we));await e()});jt.command("helpers [names...]").description("Scaffold scripts/utils.js with chosen EDS helpers (interactive picker)").action(async e=>{let{scaffoldHelpers:t}=await Promise.resolve().then(()=>(ue(),we));await t(e)});jt.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(()=>(ue(),we));await t(e)});jt.command("xwalk").description("Write xwalk.json enabling Universal Editor multi-field support").action(async()=>{let{scaffoldXwalk:e}=await Promise.resolve().then(()=>(ue(),we));await e()});G.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(()=>(Qi(),Yi));await t(e)});var og=G.command("figma").description("Figma MCP integration");og.command("setup").description("Configure Figma MCP for your AI agent").action(async()=>{let{figmaSetup:e}=await Promise.resolve().then(()=>(er(),Zi));await e()});G.command("doctor").description("Audit your EDS project for common issues").action(async()=>{let{doctor:e}=await Promise.resolve().then(()=>(nr(),tr));await e({json:G.opts().json})});var Cl=G.command("audit").description("Run project audits");Cl.command("loading").description("Check loading order (eager/lazy/delayed phases, LCP budget)").action(async()=>{let{auditLoading:e}=await Promise.resolve().then(()=>(rr(),ir));await e({json:G.opts().json})});Cl.command("security").description("Scan for vulnerabilities (npm audit) and exploit patterns (XSS, secrets, tabnabbing)").action(async()=>{let{auditSecurity:e}=await Promise.resolve().then(()=>(cr(),ar));await e({json:G.opts().json})});G.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(()=>(po(),mo));await o("preview");return}let{preview:n}=await Promise.resolve().then(()=>(lo(),pr));await n(e,t)});G.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(()=>(po(),mo));await o("publish");return}let{publish:n}=await Promise.resolve().then(()=>(fr(),ur));await n(e,t)});(async()=>{try{if(process.argv.slice(2).length===0)if(process.stdout.isTTY){let{mainMenu:e}=await Promise.resolve().then(()=>(Pl(),jl));await e()}else G.outputHelp();else await G.parseAsync()}catch(e){s.error(e instanceof Error?e.message:String(e)),process.exitCode=1}})();
|
|
1137
|
+
`),d=["jquery","lodash","moment","rxjs","d3","three","gsap","anime","chart.js","swiper"];for(let u=0;u<l.length;u++){let g=l[u].toLowerCase();for(let h of d)g.includes("from")&&g.includes(h)&&/import\s/.test(g)&&t.push({rule:"No heavy imports in blocks",status:"warn",message:`Imports "${h}" \u2014 heavy library delays section loading`,file:`blocks/${r}/${r}.js`,line:u+1})}/document\.write/i.test(c)&&t.push({rule:"No document.write in blocks",status:"fail",message:"document.write blocks parsing and can break the page",file:`blocks/${r}/${r}.js`});let p=(await bl(a)).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/${r}/${r}.js`})}for(let i of o){if(!i.isDirectory())continue;let r=i.name,a=Ie.join(n,r,`${r}.css`);if(!_e(a))continue;let c=await xt(a,"utf-8"),l=/^([a-z][a-z0-9-]*)\s*\{/gm;for(let d of c.matchAll(l)){let m=d[1];["body","html","main"].includes(m)||t.push({rule:"Block CSS is scoped",status:"warn",message:`Bare element selector "${m}" \u2014 may leak styles and cause CLS. Use .${r} prefix`,file:`blocks/${r}/${r}.css`})}}}async function Sf(e,t){let n=Ie.join(e,"scripts","aem.js");if(!_e(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 jf(e,t){let o=new RegExp(`(?:async\\s+)?function\\s+${t}\\s*\\([^)]*\\)\\s*\\{`).exec(e);if(!o)return null;let i=1,r=o.index+o[0].length,a=r;for(;r<e.length&&i>0;)e[r]==="{"?i++:e[r]==="}"&&i--,r++;return e.slice(a,r-1)}function Pf(e){let t=new Map;for(let o of e){let i=o.file||"general",r=t.get(i)??[];r.push(o),t.set(i,r)}for(let[o,i]of t){s.info(` ${Y.bullet} ${or.underline(o)}`);for(let r of i){let a=r.line?or.dim(`:${r.line}`):"";s.info(` ${gn(r.status)} ${r.rule}${a}`),r.status!=="pass"&&s.info(or.dim(` ${r.message}`))}s.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};s.info(z([je(n)])),n.fail>0&&(process.exitCode=1)}var rr=v(()=>{"use strict";f();N();V();H()});var ar={};U(ar,{auditSecurity:()=>Nf});import{existsSync as ao}from"fs";import{readFile as Ef,readdir as Cf}from"fs/promises";import et from"path";import sr from"chalk";async function*vl(e){let t=await Cf(e,{withFileTypes:!0});for(let n of t){let o=et.join(e,n.name);if(n.isDirectory()){if(Rf.has(n.name))continue;yield*vl(o)}else n.isFile()&&(yield o)}}function Ff(e,t,n){let o=[],i=e.split(`
|
|
1138
|
+
`);for(let r=0;r<i.length;r++){let a=i[r],c=!1;for(let l of Tf)l.ext.includes(n)&&(l.id==="innerhtml-static"&&c||l.re.test(a)&&(l.extra&&!l.extra(a)||(l.id==="innerhtml-dynamic"&&(c=!0),o.push({severity:l.severity,rule:l.id,message:l.message,file:t,line:r+1,snippet:a.trim().slice(0,100)}))))}return o}async function Lf(e){if(!ao(et.join(e,"package.json")))return{status:"skipped",note:"no package.json"};if(!(ao(et.join(e,"package-lock.json"))||ao(et.join(e,"npm-shrinkwrap.json")))&&!ao(et.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}),r=JSON.parse(o)?.metadata?.vulnerabilities??{},a={critical:r.critical??0,high:r.high??0,moderate:r.moderate??0,low:r.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 Nf(e={}){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}let n=[];for await(let l of vl(t)){let d=et.extname(l).slice(1).toLowerCase();if(!Df.has(d))continue;let m=et.relative(t,l);if(m.endsWith("aem.js")||m.endsWith("lib-franklin.js"))continue;let p=await Ef(l,"utf-8");n.push(...Ff(p,m,d))}let o=await Lf(t),i=l=>n.filter(d=>d.severity===l),r={critical:i("critical").length,high:i("high").length,moderate:i("moderate").length,low:i("low").length},a=r.critical>0||r.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:r}},null,2)),a&&(process.exitCode=1);return}if(s.logoOnce(A("Security Audit")),s.info(j("Dependencies","npm audit")),o.status==="skipped")s.info(R("info","npm audit",o.note??"skipped"));else if(o.status==="ok")s.info(R("pass","npm audit","no known vulnerabilities"));else{let l=o.counts??{critical:0,high:0,moderate:0,low:0};s.info(R(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(s.info(j("Exploit scan","XSS \xB7 secrets \xB7 injection \xB7 tabnabbing")),n.length===0)s.info(R("pass","code","no risky patterns found"));else{let l=[...n].sort((d,m)=>yl.indexOf(d.severity)-yl.indexOf(m.severity));for(let d of l){let m=Af[d.severity],p=sr.dim(`${d.file}:${d.line}`);s.info(` ${gn(m.status)} ${sr.bold(m.label)} ${d.message} ${p}`),s.info(sr.dim(` ${d.snippet}`))}}let c=je({fail:r.critical+r.high+(o.counts?.critical??0)+(o.counts?.high??0),warn:r.moderate+(o.counts?.moderate??0),info:r.low+(o.counts?.low??0)});s.info(""),s.info(z([c||`${Y.pass} no vulnerabilities or risky patterns found`])),a&&(process.exitCode=1)}var Tf,yl,Af,Rf,Df,cr=v(()=>{"use strict";f();N();V();H();Tf=[{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"]}],yl=["critical","high","moderate","low"],Af={critical:{status:"fail",label:"CRIT"},high:{status:"fail",label:"HIGH"},moderate:{status:"warn",label:"MOD "},low:{status:"info",label:"LOW "}},Rf=new Set(["node_modules",".git","dist","build",".vscode","coverage"]),Df=new Set(["js","mjs","html","json","pem","txt"])});async function kl(e,t,n){let o=t.ref||"main",i=n.startsWith("/")?n:`/${n}`,r=`${Of}/${e}/${t.org}/${t.site}/${o}${i}`;s.debug(`POST ${r}`);let a=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"}}),c=await a.json().catch(()=>({})),l=c;return a.ok?{ok:!0,status:a.status,path:i,previewUrl:l.preview?.url,liveUrl:l.live?.url}:{ok:!1,status:a.status,path:i,message:c.message||`HTTP ${a.status}`}}async function lr(e,t){return kl("preview",e,t)}async function dr(e,t){return kl("live",e,t)}async function xl(e,t){return Promise.all(t.map(n=>lr(e,n)))}async function $l(e,t){return Promise.all(t.map(n=>dr(e,n)))}var Of,mr=v(()=>{"use strict";f();N();Of="https://admin.hlx.page"});var pr={};U(pr,{preview:()=>_f,resolveAdminConfig:()=>co});import Sl from"chalk";import Mf from"ora";async function _f(e,t){let n=E(),o=await ce(n),i=co(o,t);if(!i)return;let r=Mf(`Previewing ${e.length} path(s)...`).start(),a=e.length===1?[await lr(i,e[0])]:await xl(i,e);r.stop();let c=!1;for(let l of a)l.ok?s.success(`${l.path} \u2192 ${Sl.cyan(l.previewUrl||"preview updated")}`):(s.error(`${l.path} \u2014 ${l.message}`),c=!0);c&&(process.exitCode=1)}function co(e,t){let n=t.org||e.admin?.org,o=t.site||e.admin?.site,i=t.ref||e.admin?.ref||"main";if(!n||!o){s.error("Missing --org and --site. Set them via flags or in .edsrc.json:"),s.info(Sl.dim(' { "admin": { "org": "my-org", "site": "my-site" } }')),process.exitCode=1;return}return{org:n,site:o,ref:i}}var lo=v(()=>{"use strict";f();mr();fe();N();V()});var ur={};U(ur,{publish:()=>Bf});import If from"chalk";import Uf from"ora";async function Bf(e,t){let n=E(),o=await ce(n),i=co(o,t);if(!i)return;let r=Uf(`Publishing ${e.length} path(s)...`).start(),a=e.length===1?[await dr(i,e[0])]:await $l(i,e);r.stop();let c=!1;for(let l of a)l.ok?s.success(`${l.path} \u2192 ${If.cyan(l.liveUrl||"published")}`):(s.error(`${l.path} \u2014 ${l.message}`),c=!0);c&&(process.exitCode=1)}var fr=v(()=>{"use strict";f();mr();fe();N();V();lo()});var mo={};U(mo,{adminWizard:()=>Hf});async function Hf(e){let t=E();if(!t){s.error("Not inside an EDS project (no EDS project markers found)."),process.exitCode=1;return}s.logoOnce(A("Admin API \u2014 preview / publish"));let{select:n,input:o,confirm:i}=await Promise.resolve().then(()=>(K(),q)),a=(await ce(t)).admin??{},c=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:a.org})).trim(),d=(await o({message:"Repository / site",default:a.site})).trim(),m=(await o({message:"Git ref",default:a.ref||"main"})).trim(),u=(await o({message:"Paths (space- or comma-separated)",default:"/"})).split(/[\s,]+/).filter(Boolean);if(!l||!d||u.length===0){s.error("org, site and at least one path are required."),process.exitCode=1;return}s.info(j("Summary"));let g=I(["operation","org","site","ref","paths"]);if(s.info(P("operation",c,g)),s.info(P("org",l,g)),s.info(P("site",d,g)),s.info(P("ref",m,g)),s.info(P("paths",u.join(", "),g)),s.info(""),c==="publish"&&!await i({message:`Publish ${u.length} path(s) to LIVE?`,default:!1})){s.info("Cancelled.");return}let h={org:l,site:d,ref:m};if(c==="preview"){let{preview:$}=await Promise.resolve().then(()=>(lo(),pr));await $(u,h)}else{let{publish:$}=await Promise.resolve().then(()=>(fr(),ur));await $(u,h)}}var po=v(()=>{"use strict";f();fe();N();V();H()});var jl={};U(jl,{mainMenu:()=>Kf});import{existsSync as Gf}from"fs";import{readdir as Wf}from"fs/promises";import zf from"path";import Jf from"chalk";async function gr(e){let t=zf.join(e,"blocks");return Gf(t)?(await Wf(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name):[]}async function Kf(){let{select:e,isEscape:t,isExit:n}=await Promise.resolve().then(()=>(K(),q));Qn.menu=!0,await s.logoOnceAnimated("");let o;for(;;){s.info(Jf.dim(" Esc quits here \xB7 goes back to this menu from any step"));let i;try{i=await e({message:"Choose an action",choices:qf,default:o})}catch(r){if(t(r)||n(r))return;throw r}if(i==="exit")return;o=i;try{await Vf(i)}catch(r){if(n(r))return;t(r)||s.error(r instanceof Error?r.message:String(r))}process.exitCode=void 0,s.info("")}}async function Vf(e){let{select:t,input:n}=await Promise.resolve().then(()=>(K(),q));switch(e){case"new":{let{newProject:o}=await Promise.resolve().then(()=>(Lo(),Fo));await o(void 0,{});return}case"init":{let{initProject:o}=await Promise.resolve().then(()=>(Lt(),Ft));await o({});return}case"template":{let o=await n({message:"Template name",validate:r=>!!r.trim()||"Required"}),{templateNew:i}=await Promise.resolve().then(()=>(Ho(),Bo));await i(o.trim(),{});return}case"sandbox":{let o=await n({message:"Sandbox repo name",validate:r=>/^[a-z0-9][a-z0-9._-]*$/i.test(r.trim())||"Use a valid repo name"}),{sandboxNew:i}=await Promise.resolve().then(()=>(Je(),ze));await i(o.trim(),{});return}case"from-design":{let{blockFromDesign:o}=await Promise.resolve().then(()=>(io(),oo));await o(void 0,{});return}case"migrate":{let{migrateComponent:o}=await Promise.resolve().then(()=>(Xo(),Vo));await o(void 0,{});return}case"scaffold":{let{scaffoldInteractive:o}=await Promise.resolve().then(()=>(ue(),we));await o();return}case"create":{let o=await n({message:"Block name",validate:r=>He.test(r.trim())||"Use kebab-case, e.g. hero-banner"}),{createBlock:i}=await Promise.resolve().then(()=>(mi(),di));await i(o.trim(),{});return}case"integrate":{let{integrate:o}=await Promise.resolve().then(()=>(Qi(),Yi));await o(void 0);return}case"preview-block":{let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found).");return}let i=await gr(o);if(i.length===0){s.warn("No blocks found in blocks/.");return}let r=await t({message:"Which block?",choices:i.map(c=>({name:c,value:c}))}),{previewBlock:a}=await Promise.resolve().then(()=>(Oe(),wt));await a(r,{});return}case"model":{let{modelAdd:o}=await Promise.resolve().then(()=>(ri(),ii));await o(void 0,[],{});return}case"track":{let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found).");return}let i=await gr(o);if(i.length===0){s.warn("No blocks found in blocks/.");return}let r=await t({message:"Which block to instrument?",choices:i.map(c=>({name:c,value:c}))}),{trackBlock:a}=await Promise.resolve().then(()=>(Ht(),Bt));await a(r,{});return}case"schema":{let o=E();if(!o){s.error("Not inside an EDS project (no EDS project markers found).");return}let i=await gr(o);if(i.length===0){s.warn("No blocks found in blocks/.");return}let r=await t({message:"Which block?",choices:i.map(c=>({name:c,value:c}))}),{schemaBlock:a}=await Promise.resolve().then(()=>(ai(),si));await a(r,{});return}case"ue":{if(await t({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:i}=await Promise.resolve().then(()=>(Jt(),zt));await i()}else{let i=await n({message:"Page path",default:"/"}),{ueOpen:r}=await Promise.resolve().then(()=>(Jt(),zt));await r(i.trim()||"/",{})}return}case"admin":{let{adminWizard:o}=await Promise.resolve().then(()=>(po(),mo));await o();return}case"audit":{let o=await t({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:i}=await Promise.resolve().then(()=>(nr(),tr));await i({})}else if(o==="loading"){let{auditLoading:i}=await Promise.resolve().then(()=>(rr(),ir));await i({})}else{let{auditSecurity:i}=await Promise.resolve().then(()=>(cr(),ar));await i({})}return}case"figma-setup":{let{figmaSetup:o}=await Promise.resolve().then(()=>(er(),Zi));await o();return}}}var qf,Pl=v(()=>{"use strict";f();N();V();nt();Zn();qf=[{name:"New project",value:"new",description:"Clone the latest EDS boilerplate"},{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, Framer or Google Stitch"},{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"},{name:"Exit",value:"exit",description:"Quit eds (or press Esc)"}]});f();import Xf from"chalk";import{Command as Yf}from"commander";var uo={name:"aem-eds-kit",version:"0.4.62",description:"CLI for AEM Edge Delivery Services: blocks from Figma, Framer or Google Stitch designs, AEM component migration (AEMaaCS and 6.5), Universal Editor models and QA",type:"module",engines:{node:">=20"},bin:{eds:"dist/bin/eds.js"},files:["dist","samples","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","aem-edge-delivery","universal-editor","aemaacs","aem-migration","framer","google-stitch","design-to-code","claude-code"],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",pixelmatch:"^6.0.0",playwright:"^1.64.0",pngjs:"^7.0.0"}};Se();N();H();var G=new Yf;G.name("eds").description("CLI for AEM Edge Delivery Services: blocks from Figma, Framer or Stitch designs, AEM migration, Universal Editor models and QA").version(uo.version).option("--verbose","Enable verbose output").option("--quiet","Suppress non-error output").option("--json","Machine-readable output (block from-design and draft: JSON-lines events on stdout)").option("--no-color","Disable color output").showHelpAfterError("(add --help for usage)").hook("preAction",e=>{let t=e.opts();t.verbose&&s.setLevel("debug"),t.quiet&&s.setQuiet(!0),t.color===!1&&(Xf.level=0)});async function $t(e,t){G.opts().json&&(B.enable(),B.emit({type:"start",command:e,cli:uo.version}));try{await t()}catch(n){s.error(n instanceof Error?n.message:String(n)),process.exitCode=1}finally{let n=Number(process.exitCode??0);B.emit({type:"result",ok:n===0,exitCode:n})}}G.addHelpText("beforeAll",()=>A());G.command("new [dir]").description("Clone the latest EDS boilerplate into a local folder (no GitHub auth)").option("--boilerplate <repo>","da | ue | commerce, owner/repo on GitHub, or any git URL (default adobe/aem-boilerplate)").option("--ue","Use the crosswalk / Universal Editor boilerplate").option("--ref <ref>","Branch or tag to clone").option("--keep-history","Keep the boilerplate's git history (remote renamed to upstream)").option("--remote <url>","Set origin to your own repo").option("--install","Run npm install after cloning").option("--yes","Skip the guided prompts").action(async(e,t)=>{let{newProject:n}=await Promise.resolve().then(()=>(Lo(),Fo));await n(e,t)});var pn=G.command("sandbox").description("Disposable EDS sandbox repos on GitHub");pn.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(()=>(Je(),ze));await n(e,t)});pn.command("login").description("Authorize GitHub (OAuth device flow or a token) - no gh needed").action(async()=>{let{sandboxLogin:e}=await Promise.resolve().then(()=>(Je(),ze));await e()});pn.command("logout").description("Remove the stored GitHub token").action(async()=>{let{sandboxLogout:e}=await Promise.resolve().then(()=>(Je(),ze));await e()});pn.command("list").description("List your EDS sandboxes (repos tagged eds-sandbox)").action(async()=>{let{sandboxList:e}=await Promise.resolve().then(()=>(Je(),ze));await e()});pn.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(()=>(Je(),ze));await n(e,t)});var Qf=G.command("template").description("Generate page templates / initial content");Qf.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(()=>(Ho(),Bo));await n(e,t)});G.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(()=>(Lt(),Ft));await t(e)});var Zf=G.command("migrate").description("Migrate from classic AEM to EDS");Zf.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("--super-root <dirs>","jcr_root folder(s), comma-separated, holding a proxy component's super type (e.g. a Core Components checkout)").option("--yes","Skip confirmation prompts").action(async(e,t)=>{let{migrateComponent:n}=await Promise.resolve().then(()=>(Xo(),Vo));await n(e,t)});var eg=G.command("model").description("Compose Universal Editor models");eg.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(()=>(ri(),ii));await o(e,t,n)});var tg=G.command("schema").description("Structured data (JSON-LD) for blocks");tg.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(()=>(ai(),si));await n(e,t)});var ng=G.command("track").description("Instrument blocks for analytics");ng.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(()=>(Ht(),Bt));await n(e,t)});var El=G.command("ue").description("Universal Editor - readiness check + editor deep link");El.command("check").description("Check whether blocks are Universal-Editor-ready (offline)").action(async()=>{let{ueCheck:e}=await Promise.resolve().then(()=>(Jt(),zt));await e()});El.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(()=>(Jt(),zt));await n(e,t)});var St=G.command("block").description("Manage EDS blocks");St.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(()=>(mi(),di));await n(e,t)});St.command("from-design [design]").description("Generate an EDS block from a design: a Figma URL, a Framer/Stitch or any web page (scraped with headless Chromium), 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("--provider <type>","Design source: figma | framer | stitch | web (else detected from the URL)").option("--agent <type>","Force agent type: claude | cursor | codex | ollama | omlx | local (any OpenAI-compatible server) | none").option("--model <name>","Model to run (Claude alias/id, or a local model, e.g. qwen2.5-coder:14b)").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("--auth","Scrape with a logged-in session (Framer/Stitch) \u2014 login captured once, then reused").option("--auth-refresh","Force a fresh scrape login even if a session is saved").option("--sample","Use the bundled sample design (the example file's hero) \u2014 no URL, no token, no MCP").option("--serve","Auto-start the live preview after generating (non-interactive runs only)").option("--draft","Generate a draft (tmp/eds-cli/drafts/<name>/vN) for review; blocks/ changes only on eds draft accept").option("--yes","Skip confirmation prompts").action(async(e,t)=>{await $t("block from-design",async()=>{let{blockFromDesign:n}=await Promise.resolve().then(()=>(io(),oo));await n(e,t)})});var un=G.command("draft").description("Review drafts from `block from-design --draft`: preview, refine, accept or discard");un.command("list").description("List drafts and their versions").action(async()=>{await $t("draft list",async()=>{let{draftList:e}=await Promise.resolve().then(()=>(yt(),bt));await e()})});un.command("preview <name> [version]").description("Preview a draft version in the browser (default: the latest), e.g. hero 2").option("--port <port>","Port to serve on (default 8777)").option("--widths <list>","Breakpoint widths").option("--no-open","Don't open the browser").action(async(e,t,n)=>{await $t("draft preview",async()=>{let{draftPreview:o}=await Promise.resolve().then(()=>(yt(),bt));await o(e,{...n,version:t})})});un.command("refine <name> <feedback>").description("One more agent round on the draft; the result is the next version").option("--from <n>","Start from this version (default: the latest)").option("--agent <type>","Agent (default: the one that made the draft)").option("--model <name>","Model (default: the one that made the draft)").action(async(e,t,n)=>{await $t("draft refine",async()=>{let{draftRefine:o}=await Promise.resolve().then(()=>(yt(),bt)),{from:i,...r}=n;await o(e,t,{...r,version:i})})});un.command("accept <name> [version]").description("Copy a draft version (default: the latest) into blocks/<name>/, optionally commit it").option("--commit","Commit blocks/<name>/ with the review rounds in the message").option("--branch <name>","Commit on this branch (created if missing; implies --commit)").action(async(e,t,n)=>{await $t("draft accept",async()=>{let{draftAccept:o}=await Promise.resolve().then(()=>(yt(),bt));await o(e,{...n,version:t})})});un.command("discard <name>").description("Drop a draft and its versions; blocks/ is untouched").action(async e=>{await $t("draft discard",async()=>{let{draftDiscard:t}=await Promise.resolve().then(()=>(yt(),bt));await t(e)})});St.command("list").description("List all blocks in the project").action(async e=>{let{listBlocks:t}=await Promise.resolve().then(()=>(Kc(),qc));await t({...e,json:G.opts().json})});St.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(()=>(Oe(),wt));e?await n.previewBlock(e,t):await n.galleryPreview(t)});St.command("test [name]").description("Visual-regression test a block (or all blocks) against committed baselines").option("--update","(Re)write the baseline screenshots instead of comparing").option("--threshold <ratio>","Max changed-pixel ratio before failing (default 0.01 = 1%)").option("--design","Compare the rendered block against its Figma design image (needs a token)").option("--widths <list>","Comma-separated breakpoint widths (e.g. 375,768,1280)").option("--port <port>","Port for the internal preview server (default: 8788)").action(async(e,t)=>{let{visualTest:n}=await Promise.resolve().then(()=>(al(),sl));await n(e,t)});St.command("check [name]").description("Content, link and a11y check on a block's rendered DOM (or all blocks)").option("--strict","Fail on warnings too, not just errors").option("--widths <list>","Comma-separated breakpoint widths (uses the widest)").option("--port <port>","Port for the internal preview server (default: 8789)").action(async(e,t)=>{let{blockCheck:n}=await Promise.resolve().then(()=>(ml(),dl));await n(e,t)});var jt=G.command("scaffold").description("Scaffold standard UE components and blocks").action(async()=>{let{scaffoldInteractive:e}=await Promise.resolve().then(()=>(ue(),we));await e()});jt.command("ue").description("Scaffold default-content UE components + a field-reference block (all 17 fields)").action(async()=>{let{scaffoldUe:e}=await Promise.resolve().then(()=>(ue(),we));await e()});jt.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(()=>(ue(),we));await t(e)});jt.command("ci").description("Scaffold a GitHub Actions workflow (doctor + audits + project lint/build)").action(async()=>{let{scaffoldCi:e}=await Promise.resolve().then(()=>(ue(),we));await e()});jt.command("helpers [names...]").description("Scaffold scripts/utils.js with chosen EDS helpers (interactive picker)").action(async e=>{let{scaffoldHelpers:t}=await Promise.resolve().then(()=>(ue(),we));await t(e)});jt.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(()=>(ue(),we));await t(e)});jt.command("xwalk").description("Write xwalk.json enabling Universal Editor multi-field support").action(async()=>{let{scaffoldXwalk:e}=await Promise.resolve().then(()=>(ue(),we));await e()});G.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(()=>(Qi(),Yi));await t(e)});var og=G.command("figma").description("Figma MCP integration");og.command("setup").description("Configure Figma MCP for your AI agent").action(async()=>{let{figmaSetup:e}=await Promise.resolve().then(()=>(er(),Zi));await e()});G.command("doctor").description("Audit your EDS project for common issues").action(async()=>{let{doctor:e}=await Promise.resolve().then(()=>(nr(),tr));await e({json:G.opts().json})});var Cl=G.command("audit").description("Run project audits");Cl.command("loading").description("Check loading order (eager/lazy/delayed phases, LCP budget)").action(async()=>{let{auditLoading:e}=await Promise.resolve().then(()=>(rr(),ir));await e({json:G.opts().json})});Cl.command("security").description("Scan for vulnerabilities (npm audit) and exploit patterns (XSS, secrets, tabnabbing)").action(async()=>{let{auditSecurity:e}=await Promise.resolve().then(()=>(cr(),ar));await e({json:G.opts().json})});G.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(()=>(po(),mo));await o("preview");return}let{preview:n}=await Promise.resolve().then(()=>(lo(),pr));await n(e,t)});G.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(()=>(po(),mo));await o("publish");return}let{publish:n}=await Promise.resolve().then(()=>(fr(),ur));await n(e,t)});(async()=>{try{if(process.argv.slice(2).length===0)if(process.stdout.isTTY){let{mainMenu:e}=await Promise.resolve().then(()=>(Pl(),jl));await e()}else G.outputHelp();else await G.parseAsync(process.argv,{from:"node"})}catch(e){s.error(e instanceof Error?e.message:String(e)),process.exitCode=1}})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aem-eds-kit",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.62",
|
|
4
4
|
"description": "CLI for AEM Edge Delivery Services: blocks from Figma, Framer or Google Stitch designs, AEM component migration (AEMaaCS and 6.5), Universal Editor models and QA",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|