`; return html.replace(/<\/body>/i,script+''); } function onPreviewMessage(e){if(!e.data||e.data.type!=='select')return;state.selected=e.data;drawInspector();} function drawInspector(){ const el=state.selected;const box=document.getElementById('inspector');if(!el){box.className='inspector-empty';box.innerHTML='Select an element

Click anything in the preview to edit its content and appearance.';return;} box.className='';box.innerHTML=`
Selected: ${escapeHtml(el.tag)}
`; const send=()=>{const p=document.getElementById('preview').contentWindow;const style={fontSize:iFont.value,fontWeight:iWeight.value,color:iColor.value,background:iBg.value,padding:iPad.value,margin:iMargin.value,width:iWidth.value,height:iHeight.value,borderRadius:iRadius.value};p.postMessage({type:'edit',text:document.getElementById('iText').value,style},'*');}; ['iText','iFont','iWeight','iColor','iBg','iPad','iMargin','iWidth','iHeight','iRadius'].forEach(id=>document.getElementById(id).addEventListener('input',send)); document.getElementById('delete').onclick=()=>document.getElementById('preview').contentWindow.postMessage({type:'edit',text:'',style:{display:'none'}},'*'); document.getElementById('duplicate').onclick=()=>document.getElementById('preview').contentWindow.postMessage({type:'edit',text:el.text+'',style:{}},'*'); } function refreshSections(){ const list=document.getElementById('sections'); if(!list)return; const parser=new DOMParser();const d=parser.parseFromString(state.html,'text/html');const els=[...d.body.children].slice(0,30); list.innerHTML=els.map((x,i)=>``).join('')||'
No top-level sections detected.
'; } function addElement(){ const p=document.getElementById('preview').contentWindow; p.postMessage({type:'edit',text:'New section',style:{display:'block',padding:'24px',background:'#f4f4f4',color:'#111'}},'*'); } async function runExport(){ const modal=document.getElementById('modal'), progress=document.getElementById('progress'), finish=document.getElementById('finish'); modal.classList.add('open'); finish.classList.add('hidden'); const stages=['Saving latest changes','Synchronizing preview and source','Checking project structure','Validating HTML','Checking asset references','Preparing Cloudflare Pages files','Creating ZIP']; progress.innerHTML=''; for(let i=0;i'+stages[i];progress.appendChild(row);await new Promise(r=>setTimeout(r,180));row.classList.add('done'); } const html=state.html||'

SiteWright export

'; const readme=`# SiteWright export\n\nThis export is a static Cloudflare Pages site.\n\n## Deploy\n1. Extract the ZIP.\n2. Upload the extracted folder to Cloudflare Pages Direct Upload, or connect the folder to a Git repository.\n3. For a static upload, no build command is required.\n4. Make sure index.html is at the project root.\n\n## Notes\n- The imported page source is exported as index.html.\n- External assets remain external unless they were already embedded in the imported HTML.\n- This package contains no server, Worker, Functions runtime, or origin dependency.\n`; const zip=await makeZip({'index.html':html,'README.md':readme,'404.html':html}); const blob=new Blob([zip],{type:'application/zip'}); const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='sitewright-cloudflare-pages-export.zip';a.click();setTimeout(()=>URL.revokeObjectURL(a.href),2000); finish.classList.remove('hidden'); finish.textContent='ZIP downloaded'; finish.disabled=true; } // Minimal ZIP writer for small text exports; uses stored (uncompressed) entries for maximum compatibility. async function makeZip(files){ const enc=new TextEncoder(), chunks=[], central=[]; let offset=0; const crcTable=(()=>{let t=[];for(let n=0;n<256;n++){let c=n;for(let k=0;k<8;k++)c=(c&1)?0xedb88320^(c>>>1):c>>>1;t[n]=c>>>0;}return t})(); const crc32=b=>{let c=0xffffffff;for(const x of b)c=crcTable[(c^x)&255]^(c>>>8);return (c^0xffffffff)>>>0}; const u16=n=>new Uint8Array([n&255,(n>>>8)&255]),u32=n=>new Uint8Array([n&255,(n>>>8)&255,(n>>>16)&255,(n>>>24)&255]); for(const [name,text] of Object.entries(files)){const nb=enc.encode(name),db=enc.encode(text),crc=crc32(db);const local=concat([u32(0x04034b50),u16(20),u16(0),u16(0),u16(0),u16(0),u32(crc),u32(db.length),u32(db.length),u16(nb.length),u16(0),nb,db]);chunks.push(local);central.push({nb,crc,len:db.length,offset});offset+=local.length;} const cd=central.map(x=>concat([u32(0x02014b50),u16(20),u16(20),u16(0),u16(0),u16(0),u16(0),u32(x.crc),u32(x.len),u32(x.len),u16(x.nb.length),u16(0),u16(0),u16(0),u16(0),u32(0),u32(x.offset),x.nb])); const cdb=concat(cd),localAll=concat(chunks);const end=concat([u32(0x06054b50),u16(0),u16(0),u16(cd.length),u16(cd.length),u32(cdb.length),u32(localAll.length),u16(0)]);return concat([localAll,cdb,end]); } function concat(arr){const len=arr.reduce((n,a)=>n+a.length,0),out=new Uint8Array(len);let p=0;for(const a of arr){out.set(a,p);p+=a.length;}return out;} landing(); })();