Setting the file. One moment.
Export Page · Wix Harmony Editor · wix/skills · Skills Docs
ContentsBack to the top of the page scripts/copy/export-page.mjs
scripts/copy/ export-page.mjs
JavaScript · 53 lines · 5 KB
12 import fs from 'node:fs' ;
13
14 const args = process.argv. slice ( 2 );
15 const opt = ( n , d ) => { const i = args. indexOf ( `--${ n }` ); return i >= 0 ? args[i + 1 ] : d; };
16 const [ pageId , sectionId , out ] = args. filter (( a , i ) => ! a. startsWith ( '--' ) && ! (i > 0 && args[i - 1 ]. startsWith ( '--' )));
17 if ( ! pageId || ! sectionId || ! out) { console. error ( 'usage: export-page.mjs <pageId> <sectionId> <out.json> [--batch 10]' ); process. exit ( 2 ); }
18 const batch = Number ( opt ( 'batch' , 10 ));
19 const b = await chromium. connectOverCDP ( `http://127.0.0.1:${ process . env . PW_PORT || 9333 }` );
20 const p = b. contexts (). flatMap (( c ) => c. pages ()). find (( x ) => x. url (). includes ( 'editor.wix.com/edit/' ));
21 if ( ! p) { console. error ( 'No Harmony editor page is open.' ); process. exit ( 3 ); }
22 await hideScrollbars (p); // canvas widths must not depend on the OS scrollbar setting
23 const run = async ( code ) => { const r = await p. evaluate ( async ( code ) => { const a = await repluggableAppDebug.host. getAPI ({ name: 'RunEditorLLMCodeToolAPI' , public: true , layer: 'DATA_SERVICE' }); return a. execute ({ code }, { biParams: {} }); }, code); const c = JSON . parse (r.items[ 0 ].content); if ( ! c.success) throw new Error (c.summary); return c.result; };
24 const J = JSON .stringify;
25 const prelude = `const A = editorLLMApis;
26 const slim = (els) => els.map((e) => ({ path: e.elementPath, el: e.element, props: Object.fromEntries(Object.entries(e.properties).filter(([k, v]) => v && v.raw != null && v.raw !== '').map(([k, v]) => [k, v.raw])) })).filter((e) => Object.keys(e.props).length);
27 const one = async (id, type, label, box, sizing) => { const it = { id, label, type, desktop: box, sizing };
28 try { it.styles = slim((await A.appearance.getStyles({ componentId: id })).elements); } catch (e) {}
29 try { const v = await A.content.get({ componentId: id }); it.content = v.values ?? v.value; } catch (e) {}
30 if (/RichText/.test(type)) { try { it.html = (await A.richText.getText({ componentId: id })).text; } catch (e) {} }
31 try { const pin = await A.layout.getPinToScreen({ componentId: id }); if (pin && pin.pinned) it.pin = pin; } catch (e) {}
32 return it; };
33 await A.pages.navigate({ pageId: ${ J ( pageId ) } }); await A.breakpoints.toggle({ device: 'desktop' });` ;
34
35 const head = await run ( `${ prelude }
36 const d = await A.layout.getComposition({ componentId: ${ J ( sectionId ) } });
37 const bg = await A.appearance.getContainerBackground({ componentId: ${ J ( sectionId ) } });
38 await A.breakpoints.toggle({ device: 'mobile' }); const m = await A.layout.getComposition({ componentId: ${ J ( sectionId ) } }); await A.breakpoints.toggle({ device: 'desktop' });
39 const pinned = []; for (const t of ['wixEditorElements.Button']) { const f = await A.components.find({ type: t, pageId: ${ J ( pageId ) }, limit: 200 }); for (const c of f.components) { const g = await A.components.get({ componentId: c.id }); if (g.parentId === ${ J ( pageId ) }) pinned.push(c.id); } }
40 return { ids: d.children.map((k) => k.componentId), section: { id: ${ J ( sectionId ) }, box: d.box, mobileBox: m.box, mobileHidden: m.notVisible || [], background: bg.background && bg.background.fields.map((f) => ({ key: f.key, value: f.value })) }, mobile: Object.fromEntries(m.children.map((k) => [k.componentId, k.box])), pinned };` );
41 const components = [];
42 for ( let i = 0 ; i < head.ids. length ; i += batch) {
43 const part = await run ( `${ prelude }
44 const d = await A.layout.getComposition({ componentId: ${ J ( sectionId ) } }); const want = new Set(${ J ( head . ids . slice ( i , i + batch )) }); const out = [];
45 for (const c of d.children) if (want.has(c.componentId)) out.push(await one(c.componentId, c.type, c.label, c.box, c.sizing));
46 return out;` );
47 components. push ( ... part);
48 }
49 for ( const id of head.pinned) components. push ( await run ( `${ prelude } const m = await A.layout.measure({ componentId: ${ J ( id ) } }); const g = await A.components.get({ componentId: ${ J ( id ) } }); const it = await one(${ J ( id ) }, g.type, g.label, m.onPage, null); it.parent = 'page'; return it;` ));
50 for ( const c of components) c.mobile = head.mobile[c.id] || null ;
51 fs. writeFileSync (out, JSON . stringify ({ exportedAt: new Date (). toISOString (), pageId, total: components. length , section: head.section, components }, null , 1 ));
52 console. log ( JSON . stringify ({ out, components: components. length , pinned: head.pinned. length }));
53 await b. close ();