@smart-cloud/publisher-exporter 1.0.6 → 1.0.8
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/README.md +2 -2
- package/dist/crawl.js +4 -4
- package/dist/deploy.js +4 -5
- package/dist/rewrite-worker.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
It is designed to run outside WordPress. The WordPress plugin only manages runtime config, queue state, and logs.
|
|
6
6
|
|
|
7
|
-
Package page: https://www.npmjs.com/package/@smart-cloud/publisher-exporter
|
|
8
|
-
|
|
9
7
|
## Install
|
|
10
8
|
|
|
11
9
|
Global install:
|
|
@@ -28,6 +26,8 @@ export PLAYWRIGHT_BROWSERS_PATH=/var/lib/playwright-browsers
|
|
|
28
26
|
publisher-exporter install-browsers
|
|
29
27
|
```
|
|
30
28
|
|
|
29
|
+
If `PLAYWRIGHT_BROWSERS_PATH` points to a shared system directory, create that directory first and make it writable by the same OS user that will run `publisher-exporter install-browsers`. A one-time elevated setup step to create or re-own the directory is fine. The later cron job does not need elevated privileges to use an already installed shared browser cache, but it does need read and execute access to that directory tree.
|
|
30
|
+
|
|
31
31
|
## Commands
|
|
32
32
|
|
|
33
33
|
```bash
|
package/dist/crawl.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {chromium}from'playwright';import
|
|
1
|
+
import {chromium}from'playwright';import y from'fs/promises';import f from'path';import {gunzipSync}from'zlib';import wt from'crypto';import yt from'fast-glob';import {availableParallelism}from'os';import {Worker}from'worker_threads';var lt=".deploy-plan.json",ct="deploy-plan.json";function dt(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?f.resolve(e):""}function be(e){let t=String(e||"").replace(/\\/g,"/").replace(/^\/+/,"").trim();return !t||t==="."||t.startsWith("../")||t===".."?null:t}function se(e){return [...new Set(e.map(be).filter(t=>t!==null))]}function pt(e,t){return {schemaVersion:1,generatedAt:String(t.generatedAt||new Date().toISOString()),outputDir:f.resolve(e.outputDir),runMode:t.runMode,crawlMode:t.crawlMode,fullSyncRequired:!!t.fullSyncRequired,changedFiles:se(t.changedFiles||[]),deletedFiles:se(t.deletedFiles||[]),rewriteTargets:se(t.rewriteTargets||[])}}function gt(e){let t=f.join(f.resolve(e.outputDir),lt),r=dt();return r?[f.join(r,ct),t]:[t]}function _(e,t){let r=f.resolve(e),s=f.resolve(t),n=f.relative(r,s).replace(/\\/g,"/");return be(n)}async function Re(e,t){let r=pt(e,t);for(let s of gt(e))await y.mkdir(f.dirname(s),{recursive:true}),await y.writeFile(s,JSON.stringify(r,null,2),"utf8");}function xe(e){let t=e.trim();return t==="."?".":t.replace(/\/$/,"")}function ne(e){return !e||typeof e!="object"?{}:Object.fromEntries(Object.entries(e).map(([t,r])=>[t.trim(),String(r??"")]).filter(([t])=>t.length>0))}function mt(e){if(!e||typeof e!="object")return {};let t={};for(let[r,s]of Object.entries(e)){let n=r.trim();if(!n||!s||typeof s!="object")continue;let i=s,u={};if(typeof i.targetOrigin=="string"){let a=xe(i.targetOrigin);a&&(u.targetOrigin=a);}let o=ne(i.extraReplacements);if(Object.keys(o).length>0&&(u.extraReplacements=o),i.s3&&typeof i.s3=="object"){let a={},l=i.s3;typeof l.bucket=="string"&&(a.bucket=l.bucket.trim()),typeof l.prefix=="string"&&(a.prefix=l.prefix.trim()),typeof l.region=="string"&&(a.region=l.region.trim()),typeof l.htmlCacheControl=="string"&&(a.htmlCacheControl=l.htmlCacheControl.trim()),typeof l.assetCacheControl=="string"&&(a.assetCacheControl=l.assetCacheControl.trim()),Object.keys(a).length>0&&(u.s3=a);}if(i.cloudFront&&typeof i.cloudFront=="object"){let a={},l=i.cloudFront;typeof l.distributionId=="string"&&(a.distributionId=l.distributionId.trim()),Array.isArray(l.invalidationPaths)&&(a.invalidationPaths=l.invalidationPaths.map(c=>String(c??"").trim()).filter(c=>c.length>0)),Object.keys(a).length>0&&(u.cloudFront=a);}t[n]=u;}return t}function ie(e,t){let s=String(e||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!s)return t;let n=s.split("/").map(i=>i.trim()).filter(i=>i.length>0&&i!=="."&&i!=="..");return n.length>0?n.join("/"):t}function ft(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?f.resolve(e):""}function Ce(e,t,r){let s=String(t||"").trim();return s&&f.isAbsolute(s)?f.resolve(s):f.resolve(e,ie(s,r))}async function oe(){let e=process.env.PUBLISHER_CONFIG||"publisher.config.json",t=await y.readFile(e,"utf8"),r=JSON.parse(t);r.sourceOrigin=r.sourceOrigin.replace(/\/$/,""),r.targetOrigin=xe(r.targetOrigin),r.ignoreHttpsErrors??=false,r.outputDir=String(r.outputDir||"export").trim()||"export",r.urlRewriteMode||=r.targetOrigin==="."?"relative":"absolute",r.noJavaScriptRenderPathPrefixes||=[],r.seedPaths||=[],r.sitemapPaths||=["/sitemap_index.xml","/sitemap.xml"],r.allowedAssetHosts||=[],r.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],r.blockedPathPrefixes||=[],r.blockedSearchFragments||=[],r.concurrency||=1,r.maxPages||=0,r.extraReplacements=ne(r.extraReplacements),r.postCrawlCopyMap=ne(r.postCrawlCopyMap),r.logDir=String(r.logDir||"logs").trim()||"logs",r.verbose??=false,r.logLevel||=r.verbose?"debug":"info",r.s3SyncMode||="sdk-upload-delete",r.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},r.readiness.timeoutMs??=1500,r.readiness.fallbackWaitMs??=1500,r.viewport||={width:1440,height:1200},r.navigationTimeoutMs||=3e4,r.scheduler||={enabled:false,timezone:"UTC",rules:[]},r.scheduler.enabled??=false,r.scheduler.timezone||="UTC",r.scheduler.rules||=[],r.deploymentProfiles=mt(r.deploymentProfiles),r.assetDownloadConcurrency=Number(r.assetDownloadConcurrency)>0?Number(r.assetDownloadConcurrency):r.concurrency,r.rewriteConcurrency=Number(r.rewriteConcurrency)>0?Number(r.rewriteConcurrency):r.assetDownloadConcurrency,r.defaultDeploymentProfile=String(r.defaultDeploymentProfile??"").trim(),r.defaultDeploymentProfile&&!r.deploymentProfiles[r.defaultDeploymentProfile]&&(r.defaultDeploymentProfile="");let s=ft(),n=s?f.resolve(s,".."):"";return n?(r.outputDir=Ce(n,r.outputDir,"export"),r.logDir=Ce(n,r.logDir,"logs")):(f.isAbsolute(r.outputDir)||(r.outputDir=ie(r.outputDir,"export")),f.isAbsolute(r.logDir)||(r.logDir=ie(r.logDir,"logs"))),r}function ke(e,t=10){return wt.createHash("sha1").update(e).digest("hex").slice(0,t)}async function ae(e){await y.mkdir(f.dirname(e),{recursive:true});}function $(e){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(f.extname(e).toLowerCase())}function E(e){return e.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function j(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function W(e){return e.replace(/\//g,"\\/")}function Ae(e){return e.replace(/\//g,"\\\\/")}function H(e,t,r){if(!t)return;e[t]=r;let s=W(t),n=W(r);e[s]=n;let i=Ae(t),u=Ae(r);e[i]=u;let o=j(t),a=j(r);e[o]=a;let l=j(s),c=j(n);e[l]=c;let m=j(i),d=j(u);e[m]=d;}function ue(e,t){let r=t.startsWith("/")?t:`/${t}`,s=(e||"").replace(/\/$/,"");return !s||s==="."||s==="/"?r:`${s}${r}`}function Me(e,t){try{return new URL(e,t==="."?"https://relative.invalid":t).pathname}catch{return e.startsWith("/")?e:`/${e.replace(/^\.\//,"")}`}}function Te(e,t,r){if(!t)return r;let s=f.dirname(f.resolve(t)),n=f.resolve(e,r.replace(/^\/+/,"")),i=f.relative(s,n).replace(/\\/g,"/");return i?(i.startsWith(".")||(i=`./${i}`),i):"."}var bt=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],Rt=new Set([".html",".htm"]),Ee="WPSuite.io Static Publisher",Ct=Ee.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function xt(e,t,r){if(e.wpsuite?.subscriber===true||!r)return false;let s=f.extname(r).toLowerCase();return Rt.has(s)?/<head\b|<html\b|<!doctype html/i.test(t):false}function At(e){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${Ct}\\2)[^>]*\\/?>`,"i").test(e))return e;let t=`<meta name="generator" content="${Ee}" />`;if(e.match(/(\r?\n)([ \t]*)<\/head>/i))return e.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${t}$1$2</head>`);let s=e.includes(`\r
|
|
2
2
|
`)?`\r
|
|
3
3
|
`:`
|
|
4
|
-
`;return e.replace(/<head\b[^>]*>/i,n=>`${n}${s} ${t}`)}function
|
|
5
|
-
`,"utf8");}function
|
|
6
|
-
`,"utf8");});}enqueueJsonLine(t,r){this.enqueueTask(()=>pt(t,r));}updateCurrentEvent(t,r,s){let n=mt(t,r,s);this.enqueueTask(async()=>{await P.mkdir(this.logDir,{recursive:true}),await P.writeFile(this.currentEventPath,JSON.stringify(n,null,2),"utf8");});}push(t,r,s){let n=JSON.stringify({time:new Date().toISOString(),level:t,message:r,...s||{}});this.enqueueLine(n),this.updateCurrentEvent(t,r,s),t==="error"?console.error(r,s||""):t==="warn"?console.warn(r,s||""):(T[this.level]>=T.debug||["summary","page","sitemap","asset","timing"].includes(t))&&console.log(r);}info(t,r){this.push("info",t,r);}progress(t,r){dt("crawl.log.jsonl",t,r),this.updateCurrentEvent("progress",t,r);}checkpoint(t,r){this.updateCurrentEvent("checkpoint",t,r);}page(t,r){this.push("page",t,r);}sitemap(t,r){this.push("sitemap",t,r);}asset(t,r){this.push("asset",t,r);}warn(t,r){this.push("warn",t,r);}error(t,r){this.enqueueJsonLine(this.errorsPath,{message:t,...r||{}}),this.push("error",t,r);}summary(t,r){this.push("summary",t,r);}mark(t){this.marks.set(t,Date.now());}endMark(t,r){let s=this.marks.get(t);if(!s)return;let n=Date.now()-s,i={name:t,ms:n,seconds:Number((n/1e3).toFixed(2)),...r||{}};this.enqueueJsonLine(this.timingsPath,i),this.push("timing",`Timing ${t}: ${i.seconds}s`,i);}reject(t,r,s,n){let i={kind:t,url:r,reason:s,source:n};this.enqueueJsonLine(this.rejectedPath,i),T[this.level]>=T.debug&&this.push("reject",`Rejected ${t} ${r}: ${s}`,i);}ignore(t,r,s,n){let i={kind:t,url:r,reason:s,source:n};this.enqueueJsonLine(this.ignoredPath,i),T[this.level]>=T.debug&&this.push("ignore",`Ignored ${t} ${r}: ${s}`,i);}skip(t,r,s,n){let i={kind:t,url:r,status:s,source:n};this.enqueueJsonLine(this.skippedPath,i),this.push("warn",`Skipped ${t} ${r}: HTTP ${s}`,i);}async flush(){let t=Date.now()-this.startedAt,r={name:"total",ms:t,seconds:Number((t/1e3).toFixed(2))};if(this.enqueueJsonLine(this.timingsPath,r),await this.writeQueue,this.writeError)throw this.writeError}};var ft=["text/css","javascript","image/","font/","application/font","application/json","application/xml","text/xml","application/rss+xml","application/atom+xml","application/xslt+xml","text/xsl","image/svg+xml","application/octet-stream"],wt=new Set([".css",".js",".mjs",".json",".map",".xml",".xsl",".rss",".atom",".txt",".enc",".jws",".png",".jpg",".jpeg",".gif",".webp",".avif",".svg",".ico",".woff",".woff2",".ttf",".otf",".eot",".pdf",".mp4",".webm"]),Pt=new Set(["",".html",".htm"]),yt=new Set([".css",".xml",".xsl",".svg",".json",".html",".htm",".txt",".enc",".jws"]),St=["/wp-content/","/wp-includes/","/wp-admin/","/static/","/assets/","/build/","/_next/"];function vt(e){let t=[],r="full",s="full",n=false,i=false;for(let o=0;o<e.length;o++){let a=e[o];if(a==="--retry-timeouts")r="retry-timeouts",n=true;else if(a==="--resume")n=true;else if(a==="--resume-rewrite")n=true,i=true;else if(a==="--crawl-mode"){let u=e[++o];if(!u)throw new Error("--crawl-mode requires a value");s=u==="incremental"?"incremental":"full",n||=s==="incremental";}else if(a.startsWith("--crawl-mode="))s=a.slice(13)==="incremental"?"incremental":"full",n||=s==="incremental";else if(a==="--incremental")s="incremental",n=true;else if(a==="--url"){let u=e[++o];if(!u)throw new Error("--url requires a value");r="single-url",n=true,t.push(u);}else if(a.startsWith("--url="))r="single-url",n=true,t.push(a.slice(6));else if(a==="--urls"){let u=e[++o];if(!u)throw new Error("--urls requires a file path");r="single-url",n=true,t.push(`@${u}`);}}return {mode:r,crawlMode:s,urls:t,preserveOutput:n,resumeRewrite:i}}function te(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?f.resolve(e):""}function bt(){let e=te();return e?f.resolve(e,".."):""}function Rt(){let e=process.env.STATIC_PUBLISHER_WP_ROOT||process.env.WPSUITE_STATIC_PUBLISHER_WP_ROOT||"";return e.trim()?f.resolve(e):""}function xt(e){let t=e.trim(),r=[{alias:"@storage-root",root:bt(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@runtime",root:te(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@wp-root",root:Rt(),requiredEnv:"STATIC_PUBLISHER_WP_ROOT or WPSUITE_STATIC_PUBLISHER_WP_ROOT"}];for(let s of r){if(t!==s.alias&&!t.startsWith(`${s.alias}/`))continue;if(!s.root)return {resolvedPath:null,alias:s.alias,requiredEnv:s.requiredEnv};let n=t.slice(s.alias.length).replace(/^\/+/,"");return {resolvedPath:n?f.resolve(s.root,n):s.root,alias:s.alias}}return {resolvedPath:f.resolve(t)}}function Fe(e){let t=te();return t?f.join(t,"crawl-manifest.json"):f.join(e.outputDir,".crawl-manifest.json")}async function Ct(e){try{let t=await P.readFile(Fe(e),"utf8"),r=JSON.parse(t);if(r&&typeof r=="object"&&r.schemaVersion===1&&r.pages&&typeof r.pages=="object")return r}catch{}return {schemaVersion:1,updatedAt:"",pages:{}}}function Se(e){return JSON.parse(JSON.stringify(e))}async function kt(e,t){let r=Fe(e);await P.mkdir(f.dirname(r),{recursive:true}),await P.writeFile(r,JSON.stringify(t,null,2),"utf8");}function N(e){if(!e)return null;let t=e.trim();return t||null}async function Lt(e,t,r,s){let n=[...new Set(r.map(a=>a.trim()).filter(Boolean))],i=String(e.wpsuite?.siteKey||"").trim();if(n.length===0||!i)return new Map;let o=new URL("/wp-json/smartcloud-static-publisher/v1/change-tokens",e.sourceOrigin).toString();try{let a=await t.post(o,{timeout:3e4,failOnStatusCode:!1,headers:{"content-type":"application/json","x-site-key":i},data:JSON.stringify({urls:n})});if(!a.ok())return s.warn(`Change token lookup failed with HTTP ${a.status()}`,{endpoint:o,status:a.status()}),new Map;let u=await a.json().catch(()=>null);if(!u||!Array.isArray(u.items))return new Map;let l=new Map;for(let c of u.items)!c||typeof c.url!="string"||l.set(c.url,c);return l}catch(a){return s.warn("Change token lookup failed; falling back to sitemap metadata",{endpoint:o,error:String(a)}),new Map}}async function ve(e,t,r,s,n){if(!r.enabled)return null;if(r.changeTokenCache.has(s))return r.changeTokenCache.get(s)??null;let o=(await Lt(e,t,[s],n)).get(s)??null;return r.changeTokenCache.set(s,o),o}async function At(e,t,r,s,n,i){if(!s.enabled)return {action:"render",changeToken:null};let o=s.manifest.pages[n];if(!o)return {action:"render",changeToken:await ve(e,t,s,n,i)};let a=await ve(e,t,s,n,i);if(a?.supported&&a.token)return o.changeToken===a.token?{action:"reuse",changeToken:a}:{action:"render",changeToken:a};let u=N(r.sitemapLastmodByPage[n]);return u&&o.sitemapLastmod&&o.sitemapLastmod===u?{action:"reuse",changeToken:a}:{action:"render",changeToken:a}}async function Et(e,t,r,s){let n=be(r.previousManifest),i=0;for(let[p,d]of Object.entries(r.manifest.pages))if(!r.seenPages.has(p)){try{await P.unlink(d.outputPath);}catch(g){(g.code||"")!=="ENOENT"&&s.warn(`Failed to remove stale incremental page output for ${p}`,{url:p,outputPath:d.outputPath,error:String(g)});}delete r.manifest.pages[p],i++;}let o=be(r.manifest),a=new Set,u=new Set;for(let p of o){for(let g of Re(e,p))a.add(g);let d=q(e,t.assetMap,p);d&&u.add(d);}let l=0,c=0;for(let p of n){if(o.has(p))continue;let d=new Set,g=q(e,t.assetMap,p);if(g)d.add(g);else {let h=ne(e,p);d.add(h.originalFilePath),h.hashedFilePath&&d.add(h.hashedFilePath);}for(let h of d)if(!u.has(h))try{await P.unlink(h),l++;}catch(m){(m.code||"")!=="ENOENT"&&s.warn(`Failed to remove stale incremental asset output for ${p}`,{url:p,outputPath:h,error:String(m)});}for(let h of Re(e,p))a.has(h)||Object.prototype.hasOwnProperty.call(t.assetMap,h)&&(delete t.assetMap[h],c++);}(i>0||l>0||c>0)&&s.info(`Incremental cleanup removed ${i} stale pages, ${l} stale assets, ${c} stale asset mappings`,{removedPages:i,removedAssets:l,removedAssetMappings:c,phase:"incremental-cleanup"});}function be(e){let t=new Set;for(let r of Object.values(e.pages))for(let s of r.discoveredAssets||[]){let n=s.trim();n&&t.add(n);}return t}function Re(e,t){let r=new Set([t]);try{let s=new URL(t),i=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{i.push(new URL(e.targetOrigin).origin);}catch{}for(let o of i)try{r.add(new URL(o).origin+s.pathname+s.search);}catch{}r.add(s.pathname+s.search),r.add(s.pathname);}catch{}return [...r]}function Mt(e,t){let r=e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/"?e.targetOrigin:"https://relative.invalid/";try{let s=new URL(t,r);return f.join(e.outputDir,decodeURIComponent(s.pathname))}catch{return null}}function q(e,t,r){let s=t[r];return s?Mt(e,s):ne(e,r).originalFilePath}function Tt(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?f.join(f.resolve(e),"queue-runner-heartbeat.json"):""}async function xe(e){let t=Tt();if(t)try{let r=await P.readFile(t,"utf8"),s=JSON.parse(r);if(!s||typeof s!="object")return;await P.writeFile(t,JSON.stringify({...s,checkedAt:new Date().toISOString(),status:"running",currentStep:"rewrite",message:e},null,2),"utf8");}catch{}}function It(e,t){let r=new Set;for(let s of t.donePages)r.add(f.resolve(se(e,s)));for(let s of t.doneAssets){let n=q(e,t.assetMap,s);!n||!O(n)||r.add(f.resolve(n));}return [...r]}var W="re:",Q=new Map;function $t(e){if(!e.startsWith(W))return null;let t=Q.get(e);if(t!==void 0)return t||null;let r=e.slice(W.length).trim();if(!r)return Q.set(e,false),null;try{let s=new RegExp(r);return Q.set(e,s),s}catch{return console.warn(`[crawl] Ignoring invalid path matcher regex: ${e}`),Q.set(e,false),null}}function re(e,t){let r=$t(t);return r?r.test(e):t.startsWith(W)?false:e.startsWith(t)}function jt(e,t){return t.find(r=>re(e,r))}function Oe(e,t){let r=jt(t.pathname,e.blockedPathPrefixes);if(r)return r.startsWith(W)?`blocked path regex: ${r}`:`blocked path prefix: ${r}`;let s=e.blockedSearchFragments.find(n=>t.search.includes(n));return s?`blocked search fragment: ${s}`:null}function Dt(e){let t=new URL(e.sourceOrigin),r=new Set([t.hostname,...e.allowedAssetHosts]);if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{r.add(new URL(e.targetOrigin).hostname);}catch{}for(let s of Object.keys(e.extraReplacements||{}))try{r.add(new URL(s).hostname);}catch{}return r}function Ft(e,t){return Dt(e).has(t.hostname)}function Ot(e){let t=L(e.trim()).replace(/\\\//g,"/").replace(/^['"]|['"]$/g,"").trim();return t=t.replace(/[)]+$/g,"").trim(),t=t.replace(/;.*$/g,"").trim(),t}function Ue(e){let t=L(e).replace(/\\\//g,"/");return /[{}]|\bwindow\.|\blocation\.|\bincludes\(|\?\?null|\+|%7B|%7D|%22|<|>|\s/.test(t)}function H(e){return St.some(t=>e.pathname.startsWith(t))}function S(e,t,r=e.sourceOrigin,s,n="url"){let i=Ot(t);if(!i||i.startsWith("data:")||i.startsWith("blob:")||i.startsWith("mailto:")||i.startsWith("tel:")||i.startsWith("#"))return s?.ignore(n,t,"empty or unsupported scheme",r),null;if(Ue(i))return s?.ignore(n,t,"looks like JavaScript/code fragment",r),null;try{let o=new URL(i,r);if(!["http:","https:"].includes(o.protocol))return s?.ignore(n,t,"unsupported protocol: ",r),null;if(!Ft(e,o))return s?.ignore(n,o.toString(),"host not allowed",r),null;let a=Oe(e,o);if(a)return s?.reject(n,o.toString(),a,r),null;let u=new URL(e.sourceOrigin);return o.protocol=u.protocol,o.host=u.host,o.hash="",o}catch{return s?.reject(n,t,"invalid URL",r),null}}function Qe(e){return wt.has(f.extname(e.pathname).toLowerCase())}function D(e){return H(e)?false:Pt.has(f.extname(e.pathname).toLowerCase())}function J(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function y(e,t){return J(t)||t.pathname==="/robots.txt"||t.pathname==="/llms.txt"||t.pathname.toLowerCase().endsWith(".xsl")?true:Qe(t)?e.assetPathPrefixes.length===0?true:e.assetPathPrefixes.some(r=>re(t.pathname,r)):false}function se(e,t){let r=new URL(t),s=decodeURIComponent(r.pathname);return s.endsWith("/")?s+="index.html":f.extname(s)||(s+="/index.html"),f.join(e.outputDir,s)}function ne(e,t){let r=new URL(t),s=decodeURIComponent(r.pathname);s.endsWith("/")&&(s+="index.html");let n=!!r.search,i=s,o=f.join(e.outputDir,i),a=K(e.targetOrigin,i),u=`${a}${r.search}`;if(!n)return {originalPathname:i,originalFilePath:o,originalPublicUrl:a,originalPublicUrlWithSearch:u,preferQueryHashed:n};let l=f.extname(s),p=`${l?s.slice(0,-l.length):s}.${ce(r.search)}${l||".bin"}`;return {originalPathname:i,originalFilePath:o,originalPublicUrl:a,originalPublicUrlWithSearch:u,preferQueryHashed:n,hashedPathname:p,hashedFilePath:f.join(e.outputDir,p),hashedPublicUrl:K(e.targetOrigin,p)}}function Ut(e,t,r,s,n){t[r]=s;try{let i=new URL(r),a=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{a.push(new URL(e.targetOrigin).origin);}catch{}for(let u of a)try{let l=new URL(u);t[l.origin+i.pathname+i.search]=s;}catch{}try{let u=(()=>{let l=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin);return `${l.pathname}${l.search}`})();t[i.pathname+i.search]=u;}catch{}try{let u=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=u;}catch{}try{let u=new URL(n,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=u;}catch{}}catch{}}async function Z(e){try{return await P.readFile(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function Ne(e){try{return await P.stat(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}function Qt(e){let t=String(e["content-length"]||"").trim();if(!t)return null;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>=0?r:null}function qe(e){let t=String(e["last-modified"]||"").trim();if(!t)return null;let r=Date.parse(t);return Number.isFinite(r)?r:null}function Nt(e,t){let r=qe(t),s=Qt(t),n=e.mtime.getTime();return r!==null&&Math.abs(n-r)>=1e3||s!==null&&e.size!==s?false:r!==null||s!==null}async function qt(e,t){if(!t)return;let r=qe(t);if(r===null)return;let s=await Ne(e);if(!s)return;let n=new Date(r);await P.utimes(e,s.atime,n).catch(()=>{});}function Ce(e,t){let r=f.extname(e.pathname).toLowerCase(),s=t["content-type"]||"";return yt.has(r)||ft.some(n=>s.includes(n))&&!s.startsWith("image/")&&!s.includes("font")}function ke(e,t){(e.doneAssets.size%25===0||e.doneAssets.size===1||e.doneAssets.size===e.stats.assetsQueued)&&t.progress(`Asset download progress: downloaded ${e.doneAssets.size}, discovered ${e.stats.assetsQueued}.`,{doneAssets:e.doneAssets.size,assetsQueued:e.stats.assetsQueued,phase:"download-assets"});}async function ee(e,t,r,s,n,i,o){let a=ne(e,r),u=a.originalFilePath,l=a.originalPublicUrlWithSearch;if(a.preferQueryHashed&&a.hashedFilePath&&a.hashedPublicUrl){let p=await Z(a.originalFilePath);p!==null&&!p.equals(s)&&(u=a.hashedFilePath,l=a.hashedPublicUrl);}Ut(e,t,r,l,a.originalPublicUrl);let c=await Z(u);(c===null||!c.equals(s))&&(await V(u),await P.writeFile(u,s)),await qt(u,o),n.stats.assetsSaved++,i&&(n.stats.assetsSaved%50===0||n.stats.assetsSaved===1)&&i.progress(`Asset progress: saved ${n.stats.assetsSaved}, discovered ${n.stats.assetsQueued}, pending ${n.assetQueue.length}.`,{assetsSaved:n.stats.assetsSaved,assetsQueued:n.stats.assetsQueued,assetQueue:n.assetQueue.length,phase:"download-assets"});}function _(e,t,r,s,n){let i=n&&/^https?:\/\//i.test(n)?n:e.sourceOrigin,o=S(e,r,i,s,"page");if(!o)return;if(!D(o)||Qe(o)){if(y(e,o)){s.info(`Seeded/non-page URL queued as asset: ${o.toString()}`,{url:o.toString(),source:n}),k(e,t,o.toString(),s,n);return}s.reject("page",o.toString(),H(o)?"asset/internal path cannot be page":"not page-like",n);return}let a=o.toString();!t.donePages.has(a)&&!t.queuedPages.has(a)&&(t.queuedPages.add(a),t.pageQueue.push(a),t.stats.pagesQueued++,(t.stats.pagesQueued%25===0||t.stats.pagesQueued===1)&&s.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,pageQueue:t.pageQueue.length,phase:"discovery"}));}function k(e,t,r,s,n){let i=n&&/^https?:\/\//i.test(n)?n:e.sourceOrigin,o=S(e,r,i,s,"asset");if(!o)return;if(!y(e,o)){s.reject("asset",o.toString(),"not a safe asset path/prefix",n);return}let a=o.toString();!t.doneAssets.has(a)&&!t.queuedAssets.has(a)&&(t.queuedAssets.add(a),t.assetQueue.push(a),t.stats.assetsQueued++,(t.stats.assetsQueued%100===0||t.stats.assetsQueued===1)&&s.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,assetQueue:t.assetQueue.length,phase:"discovery"}));}function ie(e,t,r,s,n){let i=n&&/^https?:\/\//i.test(n)?n:e.sourceOrigin,o=S(e,r,i,s,"sitemap");if(!o)return;if(!J(o)){s.reject("sitemap",o.toString(),"not sitemap-like",n);return}let a=o.toString();!t.doneSitemaps.has(a)&&!t.queuedSitemaps.has(a)&&(t.queuedSitemaps.add(a),t.sitemapQueue.push(a),t.stats.sitemapsQueued++,(t.stats.sitemapsQueued%10===0||t.stats.sitemapsQueued===1)&&s.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,sitemapQueue:t.sitemapQueue.length,phase:"discovery"}));}function Wt(e){let t=L(e),r=[...t.matchAll(/<url>\s*([\s\S]*?)\s*<\/url>/gi)].map(s=>s[1]);return r.length>0?r.map(s=>{let n=s.match(/<loc>\s*([^<]+?)\s*<\/loc>/i);if(!n?.[1])return null;let i=s.match(/<lastmod>\s*([^<]+?)\s*<\/lastmod>/i);return {loc:n[1].trim(),lastmod:N(i?.[1]??null)}}).filter(s=>!!s):[...t.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)].map(s=>({loc:s[1].trim(),lastmod:null})).filter(s=>s.loc)}function _t(e){return e.split(",").map(t=>t.trim().split(/\s+/)[0]).filter(Boolean)}function Ht(e){let t=[],r=/url\(\s*(?:"([^"]+)"|'([^']+)'|([^)]*?))\s*\)/gi;for(let s of e.matchAll(r)){let n=(s[1]||s[2]||s[3]||"").trim();n&&t.push(n);}return t}function Y(e){return e.trim().replace(/\\/g,"/").replace(/^https?:\/\/[^/]+/i,"").replace(/^\/+/,"")}async function Jt(e,t){await P.mkdir(t,{recursive:true});let r=await P.readdir(e,{withFileTypes:true});for(let s of r){let n=f.join(e,s.name),i=f.join(t,s.name);if(s.isDirectory()){await P.cp(n,i,{recursive:true,force:true});continue}await P.copyFile(n,i);}}async function Bt(e,t){let r=Object.entries(e.postCrawlCopyMap||{}).map(([n,i])=>({sourcePath:n.trim(),prefix:String(i||"").trim()}));if(r.length===0)return;let s=0;t.mark("copy-extra-paths");for(let n of r){let i=n.sourcePath,o=n.prefix;if(!i||!o){t.warn("Skipped post-crawl copy mapping with empty key/value",{sourcePath:i,prefixPath:o});continue}let a=xt(i);if(!a.resolvedPath){t.warn("Skipped post-crawl copy source because alias root is not configured",{sourcePath:i,alias:a.alias||"",requiredEnv:a.requiredEnv||"",prefixPath:o});continue}let u=a.resolvedPath,l=Y(o);if(!l){t.warn("Skipped post-crawl copy mapping with invalid export prefix",{sourcePath:i,prefixPath:o});continue}let c;try{c=await P.stat(u);}catch{t.warn("Skipped post-crawl copy source because it does not exist",{sourcePath:i,sourceAbs:u,prefixPath:o});continue}let p=f.resolve(e.outputDir,l);if(c.isDirectory()){await Jt(u,p),s++,t.progress(`Copied static directory to export: ${u} -> /${l}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${l}`,copiedItems:s});continue}let d=f.basename(u),g=o.endsWith("/")?f.join(p,d):p;await P.mkdir(f.dirname(g),{recursive:true}),await P.copyFile(u,g),s++,t.progress(`Copied static file to export: ${u} -> /${Y(o.endsWith("/")?`${o}${d}`:o)}`,{phase:"copy-extra-paths",sourcePath:u,targetPath:`/${Y(o.endsWith("/")?`${o}${d}`:o)}`,copiedItems:s});}t.endMark("copy-extra-paths",{mappedSources:r.length,copiedItems:s});}function j(e,t,r,s,n){let i=new Set,o=L(r).replace(/\\\//g,"/");for(let l of Ht(o)){let c=S(e,l,t,s,`${n}:css-url`);c&&y(e,c)&&i.add(c.toString());}for(let l of o.matchAll(/@import\s+(?:url\()?\s*['"]?([^'"\s;]+)['"]?\s*\)?/gi)){let c=S(e,l[1],t,s,`${n}:css-import`);c&&y(e,c)&&i.add(c.toString());}for(let l of o.matchAll(/<\?xml-stylesheet[^>]+href=["']([^"']+)["'][^>]*\?>/gi)){let c=S(e,l[1],t,s,`${n}:xml-stylesheet`);c&&y(e,c)&&i.add(c.toString());}let a="(?:css|js|mjs|json|map|xml|xsl|rss|atom|txt|enc|jws|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|pdf|mp4|webm)",u=new RegExp(`(?:https?:)?//[^\\s'"<>\\);]+\\.${a}(?:\\?[^\\s'"<>\\);]*)?|(?<!\\.)/[^\\s'"<>\\);]+\\.${a}(?:\\?[^\\s'"<>\\);]*)?`,"gi");for(let l of o.matchAll(u)){let c=l[0].startsWith("//")?`${new URL(e.sourceOrigin).protocol}${l[0]}`:l[0];if(Ue(c)){s.ignore(`${n}:serialized-url`,c,"looks like JavaScript/code fragment",t);continue}let p=S(e,c,t,s,`${n}:serialized-url`);p&&y(e,p)?i.add(p.toString()):p&&s.ignore("asset",p.toString(),"serialized URL did not pass safe asset path filter",t);}return [...i]}function zt(e,t,r,s){let n=new Set,i=L(r);for(let o of i.matchAll(/href=["']([^"'#\s][^"']*?)["']/gi)){let a=o[1],u=S(e,a,t,s,"page-link");u&&(Oe(e,u)||D(u)&&!H(u)&&!y(e,u)&&n.add(u.toString()));}return [...n]}async function Le(e,t,r,s){for(;r.sitemapQueue.length>0;){let n=r.sitemapQueue.shift();if(r.queuedSitemaps.delete(n),!r.doneSitemaps.has(n)){r.doneSitemaps.add(n),s.sitemap(`Fetching sitemap ${n}`,{url:n});try{let i=await t.get(n,{timeout:6e4});if(!i.ok()){s.skip("sitemap",n,i.status());continue}let o=await i.body(),a=i.url()||n;await ee(e,r.assetMap,a,o,r,s);let u=o.toString("utf8");for(let l of j(e,a,u,s,"sitemap"))k(e,r,l,s,a);for(let l of Wt(u)){let c=S(e,l.loc,a,s,"sitemap-loc");c&&(J(c)?ie(e,r,c.toString(),s,a):y(e,c)?k(e,r,c.toString(),s,a):D(c)?(l.lastmod&&(r.sitemapLastmodByPage[c.toString()]=l.lastmod),_(e,r,c.toString(),s,a)):s.reject("sitemap-loc",c.toString(),"not page/sitemap/asset-like",a));}}catch(i){s.error(`Failed sitemap ${n}`,{url:n,error:String(i)});}}}}async function Gt(e,t,r,s,n){let i=S(e,s,e.sourceOrigin,n,"asset-fetch");if(!i||!y(e,i))return;let o=i.toString();if(!r.doneAssets.has(o)){n.asset(`Fetching asset ${o}`,{url:o});try{let a=q(e,r.assetMap,o),u=a?await Ne(a):null;if(a&&u)try{let g=await t.head(o,{timeout:6e4}),h=g.headers();if(g.ok()&&Nt(u,h)){let m=await Z(a);if(m!==null){let w=g.url()||o;if(await ee(e,r.assetMap,w,m,r,n,h),r.doneAssets.add(o),n.info(`Reused existing asset ${o} based on response headers.`,{url:o,filePath:a,lastModified:h["last-modified"]||"",contentLength:h["content-length"]||"",phase:"download-assets"}),ke(r,n),Ce(i,h)){let v=m.toString("utf8");for(let b of j(e,w,v,n,"asset:cached"))k(e,r,b,n,w);}return}}}catch{}let l=await t.get(o,{timeout:6e4});if(!l.ok()){n.skip("asset",o,l.status());return}let c=await l.body(),p=l.url()||o,d=l.headers();if(await ee(e,r.assetMap,p,c,r,n,d),r.doneAssets.add(o),ke(r,n),Ce(i,d)){let g=c.toString("utf8");for(let h of j(e,p,g,n,`asset:${f.extname(i.pathname).toLowerCase()||d["content-type"]||"unknown"}`))k(e,r,h,n,p);}}catch(a){n.error(`Failed asset ${o}`,{url:o,error:String(a)});}}}async function Vt(e,t,r,s){let n=Math.max(1,Number(e.assetDownloadConcurrency||e.concurrency||1)),i=Array.from({length:n},async()=>{for(;r.assetQueue.length>0;){let o=r.assetQueue.shift();o&&(r.queuedAssets.delete(o),await Gt(e,t,r,o,s));}});await Promise.all(i);}async function Kt(e){await e.evaluate(async()=>{await new Promise(t=>{let r=0,s=700,n=window.setInterval(()=>{window.scrollBy(0,s),r+=s,r>=document.body.scrollHeight+window.innerHeight&&(window.clearInterval(n),window.scrollTo(0,0),t());},120);});});}async function Xt(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForFunction&&await t.waitForFunction(e.readiness.waitForFunction,void 0,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await Kt(t),await t.waitForTimeout(e.readiness.fallbackWaitMs);}async function Yt(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForLoadState("load",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForTimeout(e.readiness.fallbackWaitMs);}function Zt(e,t){return e.noJavaScriptRenderPathPrefixes.some(r=>re(t,r))}async function er(e,t,r,s,n=true){let i=new Set;if(n){let a=await t.evaluate(()=>{let u=new Set,l=["href","src","poster","data-src","data-lazy-src","data-original","data-bg","data-background","data-href"],c=new Set,p=["srcset","data-srcset","data-lazy-srcset"];return document.querySelectorAll("*").forEach(d=>{for(let h of l){let m=d.getAttribute(h);m&&u.add(m);}for(let h of p){let m=d.getAttribute(h);m&&m.split(",").forEach(w=>{let v=w.trim().split(/\s+/)[0];v&&u.add(v);});}let g=d.getAttribute("style");g&&c.add(g);}),{attrs:[...u],styles:[...c]}});for(let u of a.attrs)for(let l of _t(u)){let c=S(e,l,r,s,"dom-attr");c&&y(e,c)&&i.add(c.toString());}for(let u of a.styles)for(let l of j(e,r,u,s,"dom-style"))i.add(l);}let o=await t.content();for(let a of j(e,r,o,s,"page-html"))i.add(a);return [...i]}async function Ae(e,t,r,s,n){let i=se(e,t);await V(i),await P.writeFile(i,r,"utf8"),s.stats.pagesSaved++,n&&(s.stats.pagesSaved%10===0||s.stats.pagesSaved===1)&&n.progress(`Page progress: processed ${s.donePages.size}, rendered ${s.stats.pagesRendered}, saved ${s.stats.pagesSaved}, discovered ${s.stats.pagesQueued}.`,{donePages:s.donePages.size,pagesRendered:s.stats.pagesRendered,pagesSaved:s.stats.pagesSaved,pagesQueued:s.stats.pagesQueued,pageQueue:s.pageQueue.length,phase:"save-pages"});}function Ee(e){return e.donePages.size%5===0||e.donePages.size===1||e.donePages.size===e.stats.pagesQueued}function Me(e,t){t.progress(`Render progress: processed ${e.donePages.size}, rendered ${e.stats.pagesRendered}, saved ${e.stats.pagesSaved}, discovered ${e.stats.pagesQueued}.`,{donePages:e.donePages.size,pagesRendered:e.stats.pagesRendered,pagesSaved:e.stats.pagesSaved,pagesQueued:e.stats.pagesQueued,phase:"render-pages"});}async function tr(e){await e.addInitScript(()=>{Object.defineProperty(window,"__WPSUITE_STATIC_EXPORT__",{value:true,writable:false,configurable:true});let t=r=>{if(r==null||String(r)==="")return true;try{let s=new URL(String(r),window.location.href),n=new URL(window.location.href);return s.hash="",n.hash="",s.href===n.href}catch{return false}};try{let r=window.location.assign.bind(window.location),s=window.location.replace.bind(window.location),n=window.location.reload.bind(window.location);Object.defineProperty(window.location,"assign",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.assign",i??"");return}return r(i)}}),Object.defineProperty(window.location,"replace",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.replace",i??"");return}return s(i)}}),Object.defineProperty(window.location,"reload",{configurable:!0,value:()=>{console.warn("[smartcloud-static-publisher] blocked location.reload");}});}catch{}});}async function rr(e,t,r,s,n,i){let o=await chromium.launch({headless:true}),a=await o.newContext({viewport:e.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",ignoreHTTPSErrors:e.ignoreHttpsErrors}),u=await o.newContext({viewport:e.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",javaScriptEnabled:false,ignoreHTTPSErrors:e.ignoreHttpsErrors});await tr(a);try{for(;t.pageQueue.length>0&&!(e.maxPages>0&&t.donePages.size>=e.maxPages);){let l=t.pageQueue.shift();if(!l)break;if(t.queuedPages.delete(l),t.donePages.has(l))continue;t.donePages.add(l),i.enabled&&i.seenPages.add(l);let c=new URL(l),p=Zt(e,c.pathname);if(!D(c)||y(e,c)||H(c)){if(y(e,c)){r.info(`Worker redirected non-page URL to asset queue: ${l}`,{url:l,source:"worker-guard"}),k(e,t,l,r,"worker-guard");continue}r.reject("page",l,"guard rejected non-page URL before rendering","worker");continue}let d=await At(e,n,t,i,l,r);if(i.enabled&&s!=="single-url"){let m=i.manifest.pages[l];if(d.action==="reuse"&&m){for(let w of m.discoveredAssets)k(e,t,w,r,l);for(let w of m.discoveredPages)_(e,t,w,r,l);m.lastSeenRunId=i.runId,m.sitemapLastmod=N(t.sitemapLastmodByPage[l])??m.sitemapLastmod,d.changeToken?.supported&&(m.changeToken=d.changeToken.token,m.tokenSource=d.changeToken.tokenSource??m.tokenSource),r.info(`Incremental reuse skipped unchanged page ${l}`,{url:l,mode:"incremental",reason:d.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"}),Ee(t)&&Me(t,r);continue}}let g=await(p?u.newPage():a.newPage()),h=!1;await g.route("**/*",async m=>{let w=m.request();if(w.isNavigationRequest()&&w.frame()===g.mainFrame())try{let v=new URL(w.url()),b=new URL(l);if(v.hash="",b.hash="",v.href===b.href){if(h){r.warn(`Blocked same-page navigation/reload for ${l}`,{url:l,requestUrl:w.url()}),await m.abort("aborted");return}h=!0;}}catch{}await m.continue();}),g.on("response",m=>{try{let w=S(e,m.url(),e.sourceOrigin,void 0,"network-response");w&&y(e,w)&&k(e,t,w.toString(),r,l);}catch{}}),r.page(`Rendering ${l}`,{url:l});try{let m=null,w=null;try{if(m=await g.goto(l,{waitUntil:"domcontentloaded",timeout:e.navigationTimeoutMs}),m&&m.ok())try{w=await m.text();}catch{w=null;}}catch(I){r.warn(`Navigation issue for ${l}; saving current DOM if available`,{url:l,error:String(I)});}if(m&&!m.ok()){r.skip("page",l,m.status()),await g.close();continue}p?(r.info(`Rendering without JS execution for ${l}`,{url:l,mode:"no-js"}),await Yt(e,g)):await Xt(e,g),t.stats.pagesRendered++,Ee(t)&&Me(t,r);let v=await er(e,g,l,r,!p);for(let I of v)k(e,t,I,r,l);let b=w??await g.content(),oe=s!=="single-url"?zt(e,l,b,r):[];if(s!=="single-url")for(let I of oe)_(e,t,I,r,l);await Ae(e,l,b,t,r),i.enabled&&(i.manifest.pages[l]={url:l,outputPath:se(e,l),changeToken:d.changeToken?.supported?d.changeToken.token:null,tokenSource:d.changeToken?.supported?d.changeToken.tokenSource??null:null,sitemapLastmod:N(t.sitemapLastmodByPage[l])??null,discoveredPages:oe,discoveredAssets:v,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId});}catch(m){try{let w=await g.content();w&&w.trim()&&(await Ae(e,l,w,t,r),r.warn(`Saved partial DOM for ${l}`,{url:l,error:String(m)}));}catch(w){r.error(`Could not save partial DOM for ${l}`,{url:l,error:String(w)});}r.error(`Failed page ${l}`,{url:l,error:String(m)});}finally{await g.close();}}}finally{await u.close(),await a.close(),await o.close();}}async function sr(e){try{let t=await P.readFile(e),s=(e.endsWith(".gz")?gunzipSync(t):t).toString("utf8").trim();if(!s)return [];try{let n=JSON.parse(s);if(Array.isArray(n))return n;if(n&&typeof n=="object")return [n]}catch{return s.split(/\r?\n/).map(n=>n.trim()).filter(Boolean).map(n=>{try{let i=JSON.parse(n);return i&&typeof i=="object"?i:null}catch{return null}}).filter(n=>n!==null)}return []}catch{return []}}function Te(e){let t=String(e||"").toLowerCase();return t.includes("timeout")||t.includes("timed out")||t.includes("navigation timeout")}function nr(e){let t=String(e?.job?.command||"").trim(),r=String(e?.job?.crawlMode||"full").trim();return t!=="publish"&&t!=="crawl"?false:r!=="incremental"}function ir(e){let t=[e?.archivedAt,e?.job?.endedAt,e?.job?.startedAt];for(let r of t){let s=Date.parse(String(r||""));if(Number.isFinite(s))return s}return 0}async function We(e){try{let t=await P.readFile(e,"utf8"),r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function Ie(e){let t=String(e.originalFileName||"").toLowerCase();return t.endsWith("errors.jsonl")?0:t.endsWith("errors.json")?1:2}function or(e,t){let r=Array.isArray(t?.artifacts)?t.artifacts.filter(s=>String(s?.role||"").trim()==="errors"&&String(s?.storedFileName||"").trim()!=="").sort((s,n)=>Ie(s)-Ie(n)).map(s=>f.join(e,String(s.storedFileName))):[];return [...new Set([...r,f.join(e,"errors.jsonl"),f.join(e,"errors.json"),f.join(e,"errors.jsonl.gz"),f.join(e,"errors.json.gz")])]}async function $e(e){let t=await We(f.join(e,"job.json"));for(let r of or(e,t)){let s=await sr(r);if(s.length>0)return s}return []}async function ar(e){let t=f.join(e.logDir,"archive"),r;try{r=await P.readdir(t);}catch{return ""}let s="",n=0;for(let i of r){let o=f.join(t,i);if(!(await P.stat(o).catch(()=>null))?.isDirectory())continue;let u=await We(f.join(o,"job.json"));if(!nr(u))continue;let l=ir(u);l>=n&&(n=l,s=o);}return s}async function ur(e){let t=await ar(e),r=t!==""?await $e(t):await $e(e.logDir),s=new Set;for(let n of r)if(Te(n.error)||Te(n.message)){let i=n.url;typeof i=="string"&&i&&s.add(i);}return [...s]}async function lr(e){let t=[];for(let r of e)if(r.startsWith("@")){let s=r.slice(1),n=await P.readFile(s,"utf8");t.push(...n.split(/\r?\n/).map(i=>i.trim()).filter(i=>i&&!i.startsWith("#")));}else t.push(r);return t}async function cr(e){try{let t=await P.readFile(f.join(e.outputDir,"asset-map.json"),"utf8");return JSON.parse(t)}catch{return {}}}async function dr(e){let t=["crawl.log.jsonl","current-crawl-event.json","rejected.jsonl","ignored.jsonl","skipped-http.jsonl","errors.jsonl","timings.jsonl","rejected.json","ignored.json","skipped-http.json","errors.json","timings.json"];await P.mkdir(e,{recursive:true}),await Promise.all(t.map(async r=>{try{await P.unlink(f.join(e,r));}catch(s){if(s.code!=="ENOENT")throw s}}));}function je(e,t,r,s,n){let i=S(e,r,e.sourceOrigin,s,"manual-url");i&&(J(i)?ie(e,t,i.toString(),s,n):y(e,i)?k(e,t,i.toString(),s,n):D(i)?_(e,t,i.toString(),s,n):s.reject("manual-url",i.toString(),"not page/sitemap/asset-like",n));}async function pr(){let e=await G(),t=vt(process.argv.slice(2));if(t.resumeRewrite&&t.mode!=="full")throw new Error("--resume-rewrite is only supported for full crawl/publish jobs.");let r=[];t.mode==="retry-timeouts"&&(r=await ur(e)),t.mode==="single-url"&&(r=await lr(t.urls));let s=t.crawlMode==="incremental"&&t.mode==="full",n=s?await Ct(e):{schemaVersion:1,updatedAt:"",pages:{}},i={enabled:s,manifest:Se(n),previousManifest:Se(n),runId:`${Date.now()}`,seenPages:new Set,changeTokenCache:new Map};await dr(e.logDir);let o={pageQueue:[],queuedPages:new Set,donePages:new Set,assetQueue:[],queuedAssets:new Set,doneAssets:new Set,sitemapQueue:[],queuedSitemaps:new Set,doneSitemaps:new Set,sitemapLastmodByPage:{},assetMap:t.preserveOutput?await cr(e):{},stats:{pagesQueued:0,pagesRendered:0,assetsQueued:0,sitemapsQueued:0,assetsSaved:0,pagesSaved:0}};t.preserveOutput||await P.rm(e.outputDir,{recursive:true,force:true}),await P.mkdir(e.outputDir,{recursive:true});let a=new $(e.logDir,e.logLevel);if(t.resumeRewrite)a.info("Resuming final rewrite from existing output.",{phase:"rewrite-text",mode:t.mode,crawlMode:t.crawlMode});else {let d=await chromium.launch({headless:true}),g=await d.newContext({ignoreHTTPSErrors:e.ignoreHttpsErrors}),h=g.request;try{if(a.mark("discovery"),t.mode==="full"?(e.sitemapPaths.forEach(w=>ie(e,o,w,a)),await Le(e,h,o,a),e.seedPaths.forEach(w=>je(e,o,w,a,"seed-path"))):(r.forEach(w=>je(e,o,w,a,"cli")),await Le(e,h,o,a)),a.endMark("discovery",{pages:o.pageQueue.length,assets:o.assetQueue.length,sitemaps:o.sitemapQueue.length}),a.summary(`Queued ${o.pageQueue.length} pages, ${o.assetQueue.length} assets, ${o.sitemapQueue.length} sitemaps.`,{mode:t.mode,crawlMode:t.crawlMode,queuedPages:o.pageQueue.length,queuedAssets:o.assetQueue.length,queuedSitemaps:o.sitemapQueue.length}),t.mode==="retry-timeouts"&&o.pageQueue.length===0&&o.assetQueue.length===0&&o.sitemapQueue.length===0){a.summary("No timed-out URLs were queued. Skipping retry crawl.",{mode:t.mode,crawlMode:t.crawlMode,queuedPages:0,queuedAssets:0,queuedSitemaps:0}),await a.flush();return}a.mark("render-pages");let m=Array.from({length:Math.max(1,e.concurrency)},()=>rr(e,o,a,t.mode,h,i));await Promise.all(m),a.endMark("render-pages",{pages:o.donePages.size}),a.mark("download-assets"),await Vt(e,h,o,a),a.endMark("download-assets",{assets:o.doneAssets.size}),i.enabled&&e.maxPages===0&&await Et(e,o,i,a),t.mode==="full"&&await Bt(e,a);}finally{await g.close(),await d.close();}}i.enabled&&!t.resumeRewrite&&(i.manifest.updatedAt=new Date().toISOString(),await kt(e,i.manifest)),await P.writeFile(f.join(e.outputDir,"asset-map.json"),JSON.stringify(o.assetMap,null,2),"utf8");let u=t.mode==="single-url"?It(e,o):void 0;a.mark("rewrite-text");let l=t.mode==="single-url"?`Rewriting text files touched by URL crawl: 0/${u?.length??0}`:"Rewriting text files...";a.progress(l,{phase:"rewrite-text",index:0,totalFiles:u?.length,changedTextFiles:0}),await xe(l);let c=Date.now(),p=await fe(e,o.assetMap,{files:u,onProgress:async({index:d,totalFiles:g,changedTextFiles:h,file:m})=>{a.checkpoint(`Rewriting text file ${d}/${g}`,{phase:"rewrite-text",index:d,totalFiles:g,changedTextFiles:h,file:m});let w=Date.now();if(!(d===1||d===g||w-c>=5e3))return;c=w;let b=`Rewriting text files: ${d}/${g}`;a.progress(b,{phase:"rewrite-text",index:d,totalFiles:g,changedTextFiles:h,file:m}),await xe(b);}});a.endMark("rewrite-text",{changedTextFiles:p}),a.summary(t.resumeRewrite?`Done. Resumed final rewrite over existing output and changed ${p} text files.`:`Done. Rendered ${o.stats.pagesRendered} pages, processed ${o.doneSitemaps.size} sitemaps, downloaded ${o.doneAssets.size} assets.`,{mode:t.mode,crawlMode:t.crawlMode,resumeRewrite:t.resumeRewrite,...o.stats,pagesRendered:o.stats.pagesRendered,donePages:o.donePages.size,doneSitemaps:o.doneSitemaps.size,doneAssets:o.doneAssets.size,changedTextFiles:p}),await a.flush();}pr().catch(async e=>{console.error(e);try{let r=(await G().catch(()=>null))?.logDir??"logs",s=new $(r,"debug");s.error(`Unhandled error: ${e instanceof Error?e.message:String(e)}`,e instanceof Error?{stack:e.stack}:void 0),await s.flush();}catch{}process.exit(1);});
|
|
4
|
+
`;return e.replace(/<head\b[^>]*>/i,n=>`${n}${s} ${t}`)}function kt(e){let t=E(e).trim();return t.startsWith("{")||t.startsWith("[")||t.includes("\\/")||/"@context"|"@type"/.test(t)}function Mt(e,t){let r=[...new Set(t)].filter(i=>i.includes("/")&&!/\\+\//.test(i)).map(i=>[i,W(i)]).filter(([i,u])=>i!==u).sort((i,u)=>u[0].length-i[0].length);if(!r.length)return e;let s=i=>{let u=i;for(let[o,a]of r)u=u.split(o).join(a);return u},n=e.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(i,u,o,a)=>`${u}${s(o)}${a}`);return n=n.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(i,u,o,a,l)=>kt(a)?`${u}${s(a)}${l}`:i),n}function Tt(e,t){if(!t)return null;let r=f.dirname(f.resolve(t)),s=f.resolve(e.outputDir),n=f.relative(r,s).replace(/\\/g,"/");return n?(n.startsWith(".")||(n=`./${n}`),n.endsWith("/")?n:`${n}/`):"./"}function Lt(e,t,r){let s=Tt(t,r);if(!s)return e;let n=e;for(let i of bt){let u=i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=new RegExp(`(?:\\.{1,}/)+${u}`,"g"),a=new RegExp(`(?<!\\.)/${u}`,"g");n=n.replace(o,`${s}${i}`).replace(a,`${s}${i}`);let l=i.replace(/\//g,"\\/"),c=s.replace(/\//g,"\\/"),m=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),d=new RegExp(`(?:\\.{1,}\\\\/)+${m}`,"g"),h=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${m}`,"g"),p=new RegExp(`(?<![\\.\\\\])\\/${m}`,"g");n=n.replace(d,`${c}${l}`).replace(h,`${c}${l}`).replace(p,`${c}${l}`);}return n}function ce(e,t,r){if(e.urlRewriteMode==="absolute")return t;let s=(()=>{try{return new URL(t,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin)}catch{return null}})(),n=s?s.pathname:Me(t,e.targetOrigin),i=s?`${s.search}${s.hash}`:"";return e.urlRewriteMode==="root-relative"?`${n}${i}`:`${Te(e.outputDir,r,n)}${i}`}function le(e,t,r,s,n){H(e,r,ce(t,s,n));}function Et(e,t,r,s,n){if(!r||r===s)return;H(e,r,s);let i=ce(t,r,n),u=ce(t,s,n);H(e,i,u);}function Dt(e,t,r,s,n={}){let i=e,u={};le(u,t,t.sourceOrigin,t.targetOrigin,s);for(let[a,l]of Object.entries(t.extraReplacements))le(u,t,a,l,s);for(let[a,l]of Object.entries(r))le(u,t,a,l,s);for(let[a,l]of Object.entries(n)){let c=r[a];!c||c===l||Et(u,t,l,c,s);}let o=Object.entries(u).sort((a,l)=>l[0].length-a[0].length);for(let[a,l]of o)i=i.split(a).join(l);return t.urlRewriteMode!=="absolute"&&(i=Lt(i,t,s)),i=Mt(i,o.map(([,a])=>a)),xt(t,i,s)&&(i=At(i)),i}async function It(e,t,r,s){let n=f.join(e.outputDir,s),i=f.extname(n).toLowerCase(),u;try{u=await y.readFile(n,"utf8");}catch(l){if(l.code!=="ENOENT")throw l;return {changed:false}}let a=Dt(u,e,t,i===".js"||i===".mjs"?void 0:n,r);return a!==u?(await y.writeFile(n,a,"utf8"),{changed:true}):{changed:false}}async function Ft(e,t){return await new Promise((r,s)=>{let n=a=>{if(o(),a?.error){s(new Error(a.error));return}r({changed:!!a?.changed});},i=a=>{o(),s(a);},u=a=>{o(),a!==0&&s(new Error(`Rewrite worker exited with code ${a}.`));},o=()=>{e.off("message",n),e.off("error",i),e.off("exit",u);};e.on("message",n),e.on("error",i),e.on("exit",u),e.postMessage({file:t});})}async function De(e,t,r={}){let n=(r.files?[...new Set(r.files)].map(d=>f.resolve(d)).filter(d=>d.startsWith(f.resolve(e.outputDir))).map(d=>f.relative(e.outputDir,d).replace(/\\/g,"/")).filter(d=>d.length>0):await yt(["**/*"],{cwd:e.outputDir,onlyFiles:true,dot:true})).filter(d=>d!=="asset-map.json"&&$(d)),i=0;if(n.length===0)return 0;let u=Math.max(1,Number(e.rewriteConcurrency||e.assetDownloadConcurrency||1)),o=Math.max(1,Math.min(u,n.length,availableParallelism())),a=0,l=0,c=null;if(o===1){for(let d of n){let h=await It(e,t,r.previousAssetMap??{},d);h.changed&&(i+=1),l+=1,await r.onProgress?.({index:l,totalFiles:n.length,changedTextFiles:i,file:d,changed:h.changed});}return i}let m=Array.from({length:o},async()=>{let d=new Worker(new URL("./rewrite-worker.js",import.meta.url),{workerData:{config:e,assetMap:t,previousAssetMap:r.previousAssetMap??{}}});try{for(;!c;){let h=a;if(h>=n.length)return;a+=1;let p=n[h],P=await Ft(d,p);P.changed&&(i+=1),l+=1,await r.onProgress?.({index:l,totalFiles:n.length,changedTextFiles:i,file:p,changed:P.changed});}}catch(h){throw c=h instanceof Error?h:new Error(String(h)),c}finally{await d.terminate().catch(()=>{});}});return await Promise.all(m),i}var U={error:0,warn:1,info:2,debug:3},Ie=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",J=Ie?f.join(Ie,"current-progress.json"):"",Fe=Promise.resolve();function je(e){return e.includes("crawl")?"crawl":e.includes("deploy")?"deploy":e.includes("invalidate")?"invalidate":e}function jt(e,t){let r={...e},s=new Set(["pagesQueued","pagesRendered","assetsQueued","sitemapsQueued","pagesDiscovered","assetsDiscovered","sitemapsDiscovered","pagesSaved","assetsSaved","donePages","doneAssets","doneSitemaps","changedTextFiles","uploaded","failed","index","totalFiles","pageQueue","assetQueue","sitemapQueue"]);for(let[n,i]of Object.entries(t)){let u=r[n];if(typeof u=="number"&&typeof i=="number"&&s.has(n)){r[n]=Math.max(u,i);continue}r[n]=i;}return r}function Ot(e,t,r){J&&(Fe=Fe.then(async()=>{let s=new Date,n=s.toISOString();await y.mkdir(f.dirname(J),{recursive:true});let i=await y.readFile(J,"utf8").then(P=>JSON.parse(P)).catch(()=>null),u=i&&typeof i.details=="object"&&i.details?i.details:{},o=je(e),a=i?.currentStep||je(i?.source||""),l=i?.startedAt||n,c={...i?.stepDurationsSec??{}},m=i?.stepStartedAt||n;if(a&&a!==o&&i?.stepStartedAt){let P=Math.max(0,Math.round((s.getTime()-new Date(i.stepStartedAt).getTime())/1e3));c[a]=(c[a]??0)+P,m=n;}let d=Math.max(0,Math.round((s.getTime()-new Date(m).getTime())/1e3)),h=Math.max(0,Math.round((s.getTime()-new Date(l).getTime())/1e3)),p={checkedAt:n,source:e,message:t,details:jt(u,r??{}),startedAt:l,currentStep:o,stepStartedAt:m,stepElapsedSec:d,totalElapsedSec:h,stepDurationsSec:c};await y.writeFile(J,JSON.stringify(p,null,2),"utf8");}).catch(()=>{}));}async function $t(e,t){await y.mkdir(f.dirname(e),{recursive:true}),await y.appendFile(e,`${JSON.stringify(t)}
|
|
5
|
+
`,"utf8");}function Ut(e,t){let r=typeof t?.phase=="string"?t.phase.trim():"";return r||(e==="page"?"render-pages":e==="asset"?"download-assets":e==="sitemap"?"discovery":e==="timing"&&typeof t?.name=="string"&&t.name.trim()||"crawl")}function Qt(e,t,r){return {checkedAt:new Date().toISOString(),currentStep:Ut(e,r),level:e,message:t,details:r??{}}}var Q=class{constructor(t,r="info"){this.logDir=t;this.level=typeof r=="boolean"?r?"debug":"info":r,this.ensureLogFileReady();}logDir;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;level;get logPath(){return f.join(this.logDir,"crawl.log.jsonl")}get currentEventPath(){return f.join(this.logDir,"current-crawl-event.json")}get rejectedPath(){return f.join(this.logDir,"rejected.jsonl")}get ignoredPath(){return f.join(this.logDir,"ignored.jsonl")}get skippedPath(){return f.join(this.logDir,"skipped-http.jsonl")}get errorsPath(){return f.join(this.logDir,"errors.jsonl")}get timingsPath(){return f.join(this.logDir,"timings.jsonl")}ensureLogFileReady(){return this.initPromise||(this.initPromise=(async()=>{await y.mkdir(this.logDir,{recursive:true}),await y.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(t){this.writeQueue=this.writeQueue.then(t).catch(r=>{this.writeError=r instanceof Error?r:new Error(String(r));});}enqueueLine(t){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await y.appendFile(this.logPath,`${t}
|
|
6
|
+
`,"utf8");});}enqueueJsonLine(t,r){this.enqueueTask(()=>$t(t,r));}updateCurrentEvent(t,r,s){let n=Qt(t,r,s);this.enqueueTask(async()=>{await y.mkdir(this.logDir,{recursive:true}),await y.writeFile(this.currentEventPath,JSON.stringify(n,null,2),"utf8");});}push(t,r,s){let n=JSON.stringify({time:new Date().toISOString(),level:t,message:r,...s||{}});this.enqueueLine(n),this.updateCurrentEvent(t,r,s),t==="error"?console.error(r,s||""):t==="warn"?console.warn(r,s||""):(U[this.level]>=U.debug||["summary","page","sitemap","asset","timing"].includes(t))&&console.log(r);}info(t,r){this.push("info",t,r);}progress(t,r){Ot("crawl.log.jsonl",t,r),this.updateCurrentEvent("progress",t,r);}checkpoint(t,r){this.updateCurrentEvent("checkpoint",t,r);}page(t,r){this.push("page",t,r);}sitemap(t,r){this.push("sitemap",t,r);}asset(t,r){this.push("asset",t,r);}warn(t,r){this.push("warn",t,r);}error(t,r){this.enqueueJsonLine(this.errorsPath,{message:t,...r||{}}),this.push("error",t,r);}summary(t,r){this.push("summary",t,r);}mark(t){this.marks.set(t,Date.now());}endMark(t,r){let s=this.marks.get(t);if(!s)return;let n=Date.now()-s,i={name:t,ms:n,seconds:Number((n/1e3).toFixed(2)),...r||{}};this.enqueueJsonLine(this.timingsPath,i),this.push("timing",`Timing ${t}: ${i.seconds}s`,i);}reject(t,r,s,n){let i={kind:t,url:r,reason:s,source:n};this.enqueueJsonLine(this.rejectedPath,i),U[this.level]>=U.debug&&this.push("reject",`Rejected ${t} ${r}: ${s}`,i);}ignore(t,r,s,n){let i={kind:t,url:r,reason:s,source:n};this.enqueueJsonLine(this.ignoredPath,i),U[this.level]>=U.debug&&this.push("ignore",`Ignored ${t} ${r}: ${s}`,i);}skip(t,r,s,n){let i={kind:t,url:r,status:s,source:n};this.enqueueJsonLine(this.skippedPath,i),this.push("warn",`Skipped ${t} ${r}: HTTP ${s}`,i);}async flush(){let t=Date.now()-this.startedAt,r={name:"total",ms:t,seconds:Number((t/1e3).toFixed(2))};if(this.enqueueJsonLine(this.timingsPath,r),await this.writeQueue,this.writeError)throw this.writeError}};var qt=["text/css","javascript","image/","font/","application/font","application/json","application/xml","text/xml","application/rss+xml","application/atom+xml","application/xslt+xml","text/xsl","image/svg+xml","application/octet-stream"],_t=new Set([".css",".js",".mjs",".json",".map",".xml",".xsl",".rss",".atom",".txt",".enc",".jws",".png",".jpg",".jpeg",".gif",".webp",".avif",".svg",".ico",".woff",".woff2",".ttf",".otf",".eot",".pdf",".mp4",".webm"]),Wt=new Set(["",".html",".htm"]),Ht=new Set([".css",".xml",".xsl",".svg",".json",".html",".htm",".txt",".enc",".jws"]),Jt=["/wp-content/","/wp-includes/","/wp-admin/","/static/","/assets/","/build/","/_next/"];function zt(e){let t=[],r="full",s="full",n=false,i=false;for(let u=0;u<e.length;u++){let o=e[u];if(o==="--retry-timeouts")r="retry-timeouts",n=true;else if(o==="--resume")n=true;else if(o==="--resume-rewrite")n=true,i=true;else if(o==="--crawl-mode"){let a=e[++u];if(!a)throw new Error("--crawl-mode requires a value");s=a==="incremental"?"incremental":"full",n||=s==="incremental";}else if(o.startsWith("--crawl-mode="))s=o.slice(13)==="incremental"?"incremental":"full",n||=s==="incremental";else if(o==="--incremental")s="incremental",n=true;else if(o==="--url"){let a=e[++u];if(!a)throw new Error("--url requires a value");r="single-url",n=true,t.push(a);}else if(o.startsWith("--url="))r="single-url",n=true,t.push(o.slice(6));else if(o==="--urls"){let a=e[++u];if(!a)throw new Error("--urls requires a file path");r="single-url",n=true,t.push(`@${a}`);}}return {mode:r,crawlMode:s,urls:t,preserveOutput:n,resumeRewrite:i}}function me(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?f.resolve(e):""}function Bt(){let e=me();return e?f.resolve(e,".."):""}function Vt(){let e=process.env.STATIC_PUBLISHER_WP_ROOT||process.env.WPSUITE_STATIC_PUBLISHER_WP_ROOT||"";return e.trim()?f.resolve(e):""}function Gt(e){let t=e.trim(),r=[{alias:"@storage-root",root:Bt(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@runtime",root:me(),requiredEnv:"STATIC_PUBLISHER_RUNTIME_DIR or WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR"},{alias:"@wp-root",root:Vt(),requiredEnv:"STATIC_PUBLISHER_WP_ROOT or WPSUITE_STATIC_PUBLISHER_WP_ROOT"}];for(let s of r){if(t!==s.alias&&!t.startsWith(`${s.alias}/`))continue;if(!s.root)return {resolvedPath:null,alias:s.alias,requiredEnv:s.requiredEnv};let n=t.slice(s.alias.length).replace(/^\/+/,"");return {resolvedPath:n?f.resolve(s.root,n):s.root,alias:s.alias}}return {resolvedPath:f.resolve(t)}}function Ye(e){let t=me();return t?f.join(t,"crawl-manifest.json"):f.join(e.outputDir,".crawl-manifest.json")}function Ze(){return {schemaVersion:2,updatedAt:"",pages:{},assets:{}}}function Kt(){return {rewriteTargets:new Set,changedFiles:new Set,deletedFiles:new Set}}function D(e,t,r){let s=_(t.outputDir,r);s&&(e.changedFiles.add(s),e.deletedFiles.delete(s));}function Oe(e,t,r){let s=_(t.outputDir,r);s&&(e.deletedFiles.add(s),e.changedFiles.delete(s));}function B(e,t){e.rewriteTargets.add(f.resolve(t));}async function Xt(e){try{let t=await y.readFile(Ye(e),"utf8"),r=JSON.parse(t);if(r&&typeof r=="object"&&r.pages&&typeof r.pages=="object"){if(r.schemaVersion===2&&r.assets&&typeof r.assets=="object")return r;if(r.schemaVersion===1)return {schemaVersion:2,updatedAt:String(r.updatedAt||""),pages:r.pages,assets:{}}}}catch{}return Ze()}function $e(e){return JSON.parse(JSON.stringify(e))}async function Yt(e,t){let r=Ye(e);await y.mkdir(f.dirname(r),{recursive:true}),await y.writeFile(r,JSON.stringify(t,null,2),"utf8");}function V(e){if(!e)return null;let t=e.trim();return t||null}function Zt(e,t){let r=new Set,s=new Set([...Object.keys(e),...Object.keys(t)]);for(let n of s){let i=e[n],u=t[n];!i||!u||i===u||r.add(n);}return r}async function er(e,t,r,s){let n=[...new Set(r.map(o=>o.trim()).filter(Boolean))],i=String(e.wpsuite?.siteKey||"").trim();if(n.length===0||!i)return new Map;let u=new URL("/wp-json/smartcloud-static-publisher/v1/change-tokens",e.sourceOrigin).toString();try{let o=await t.post(u,{timeout:3e4,failOnStatusCode:!1,headers:{"content-type":"application/json","x-site-key":i},data:JSON.stringify({urls:n})});if(!o.ok())return s.warn(`Change token lookup failed with HTTP ${o.status()}`,{endpoint:u,status:o.status()}),new Map;let a=await o.json().catch(()=>null);if(!a||!Array.isArray(a.items))return new Map;let l=new Map;for(let c of a.items)!c||typeof c.url!="string"||l.set(c.url,c);return l}catch(o){return s.warn("Change token lookup failed; falling back to sitemap metadata",{endpoint:u,error:String(o)}),new Map}}async function Ue(e,t,r,s,n){if(!r.enabled)return null;if(r.changeTokenCache.has(s))return r.changeTokenCache.get(s)??null;let u=(await er(e,t,[s],n)).get(s)??null;return r.changeTokenCache.set(s,u),u}async function tr(e,t,r,s,n,i){if(!s.enabled)return {action:"render",changeToken:null};let u=s.manifest.pages[n];if(!u)return {action:"render",changeToken:await Ue(e,t,s,n,i)};let o=await Ue(e,t,s,n,i);if(o?.supported&&o.token)return u.changeToken===o.token?{action:"reuse",changeToken:o}:{action:"render",changeToken:o};let a=V(r.sitemapLastmodByPage[n]);return a&&u.sitemapLastmod&&u.sitemapLastmod===a?{action:"reuse",changeToken:o}:{action:"render",changeToken:o}}async function rr(e,t,r,s,n){let i=Qe(r.previousManifest),u=0;for(let[d,h]of Object.entries(r.manifest.pages))if(!r.seenPages.has(d)){Oe(n,e,h.outputPath);try{await y.unlink(h.outputPath);}catch(p){(p.code||"")!=="ENOENT"&&s.warn(`Failed to remove stale incremental page output for ${d}`,{url:d,outputPath:h.outputPath,error:String(p)});}delete r.manifest.pages[d],u++;}let o=Qe(r.manifest,r.runId),a=new Set,l=new Set;for(let d of o){for(let P of G(e,d))a.add(P);let h=r.manifest.assets[d]?.outputPath;h&&l.add(h);let p=K(e,t.assetMap,d);p&&l.add(p);}for(let d of Object.keys(r.manifest.assets))o.has(d)||delete r.manifest.assets[d];let c=0,m=0;for(let d of i){let h=new Set,p=r.previousManifest.assets[d]?.outputPath;p&&h.add(p);let P=K(e,t.assetMap,d);if(!o.has(d)&&P)h.add(P);else if(!o.has(d)){let g=we(e,d);h.add(g.originalFilePath),g.hashedFilePath&&h.add(g.hashedFilePath);}for(let g of h)if(!l.has(g)){Oe(n,e,g);try{await y.unlink(g),c++;}catch(w){(w.code||"")!=="ENOENT"&&s.warn(`Failed to remove stale incremental asset output for ${d}`,{url:d,outputPath:g,error:String(w)});}}for(let g of G(e,d))a.has(g)||Object.prototype.hasOwnProperty.call(t.assetMap,g)&&(delete t.assetMap[g],m++);}(u>0||c>0||m>0)&&s.info(`Incremental cleanup removed ${u} stale pages, ${c} stale assets, ${m} stale asset mappings`,{removedPages:u,removedAssets:c,removedAssetMappings:m,phase:"incremental-cleanup"});}function Qe(e,t){let r=new Set;for(let s of Object.values(e.pages))for(let n of s.discoveredAssets||[]){let i=n.trim();i&&r.add(i);}for(let[s,n]of Object.entries(e.assets||{})){if(t&&n.lastSeenRunId!==t)continue;let i=s.trim();i&&r.add(i);}return r}function Ne(e,t,r){for(let s of t)for(let n of G(e,s))if(r.has(n))return true;return false}function sr(e,t,r,s,n){let i=new Set(r.rewriteTargets),u=Zt(s,n);if(u.size===0)return [...i];for(let o of Object.values(t.manifest.pages))Ne(e,o.discoveredAssets,u)&&i.add(f.resolve(o.outputPath));for(let[o,a]of Object.entries(t.manifest.assets)){a.isText&&Ne(e,a.discoveredAssets,u)&&i.add(f.resolve(a.outputPath));for(let l of G(e,o))if(u.has(l)){D(r,e,a.outputPath),a.isText&&i.add(f.resolve(a.outputPath));break}}return [...i]}function G(e,t){let r=new Set([t]);try{let s=new URL(t),i=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{i.push(new URL(e.targetOrigin).origin);}catch{}for(let u of i)try{r.add(new URL(u).origin+s.pathname+s.search);}catch{}r.add(s.pathname+s.search),r.add(s.pathname);}catch{}return [...r]}function nr(e,t){let r=e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/"?e.targetOrigin:"https://relative.invalid/";try{let s=new URL(t,r);return f.join(e.outputDir,decodeURIComponent(s.pathname))}catch{return null}}function K(e,t,r){let s=t[r];return s?nr(e,s):we(e,r).originalFilePath}function ir(){let e=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return e.trim()?f.join(f.resolve(e),"queue-runner-heartbeat.json"):""}async function qe(e){let t=ir();if(t)try{let r=await y.readFile(t,"utf8"),s=JSON.parse(r);if(!s||typeof s!="object")return;await y.writeFile(t,JSON.stringify({...s,checkedAt:new Date().toISOString(),status:"running",currentStep:"rewrite",message:e},null,2),"utf8");}catch{}}function or(e,t){let r=new Set;for(let s of t.donePages)r.add(f.resolve(Y(e,s)));for(let s of t.doneAssets){let n=K(e,t.assetMap,s);!n||!$(n)||r.add(f.resolve(n));}return [...r]}var X="re:",z=new Map;function ar(e){if(!e.startsWith(X))return null;let t=z.get(e);if(t!==void 0)return t||null;let r=e.slice(X.length).trim();if(!r)return z.set(e,false),null;try{let s=new RegExp(r);return z.set(e,s),s}catch{return console.warn(`[crawl] Ignoring invalid path matcher regex: ${e}`),z.set(e,false),null}}function fe(e,t){let r=ar(t);return r?r.test(e):t.startsWith(X)?false:e.startsWith(t)}function ur(e,t){return t.find(r=>fe(e,r))}function et(e,t){let r=ur(t.pathname,e.blockedPathPrefixes);if(r)return r.startsWith(X)?`blocked path regex: ${r}`:`blocked path prefix: ${r}`;let s=e.blockedSearchFragments.find(n=>t.search.includes(n));return s?`blocked search fragment: ${s}`:null}function lr(e){let t=new URL(e.sourceOrigin),r=new Set([t.hostname,...e.allowedAssetHosts]);if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{r.add(new URL(e.targetOrigin).hostname);}catch{}for(let s of Object.keys(e.extraReplacements||{}))try{r.add(new URL(s).hostname);}catch{}return r}function cr(e,t){return lr(e).has(t.hostname)}function dr(e){let t=E(e.trim()).replace(/\\\//g,"/").replace(/^['"]|['"]$/g,"").trim();return t=t.replace(/[)]+$/g,"").trim(),t=t.replace(/;.*$/g,"").trim(),t}function tt(e){let t=E(e).replace(/\\\//g,"/");return /[{}]|\bwindow\.|\blocation\.|\bincludes\(|\?\?null|\+|%7B|%7D|%22|<|>|\s/.test(t)}function ee(e){return Jt.some(t=>e.pathname.startsWith(t))}function R(e,t,r=e.sourceOrigin,s,n="url"){let i=dr(t);if(!i||i.startsWith("data:")||i.startsWith("blob:")||i.startsWith("mailto:")||i.startsWith("tel:")||i.startsWith("#"))return s?.ignore(n,t,"empty or unsupported scheme",r),null;if(tt(i))return s?.ignore(n,t,"looks like JavaScript/code fragment",r),null;try{let u=new URL(i,r);if(!["http:","https:"].includes(u.protocol))return s?.ignore(n,t,"unsupported protocol: ",r),null;if(!cr(e,u))return s?.ignore(n,u.toString(),"host not allowed",r),null;let o=et(e,u);if(o)return s?.reject(n,u.toString(),o,r),null;let a=new URL(e.sourceOrigin);return u.protocol=a.protocol,u.host=a.host,u.hash="",u}catch{return s?.reject(n,t,"invalid URL",r),null}}function rt(e){return _t.has(f.extname(e.pathname).toLowerCase())}function q(e){return ee(e)?false:Wt.has(f.extname(e.pathname).toLowerCase())}function te(e){let t=e.pathname.toLowerCase();return t.endsWith(".xml")&&(t.includes("sitemap")||t.endsWith("/sitemap.xml"))}function b(e,t){return te(t)||t.pathname==="/robots.txt"||t.pathname==="/llms.txt"||t.pathname.toLowerCase().endsWith(".xsl")?true:rt(t)?e.assetPathPrefixes.length===0?true:e.assetPathPrefixes.some(r=>fe(t.pathname,r)):false}function Y(e,t){let r=new URL(t),s=decodeURIComponent(r.pathname);return s.endsWith("/")?s+="index.html":f.extname(s)||(s+="/index.html"),f.join(e.outputDir,s)}function we(e,t){let r=new URL(t),s=decodeURIComponent(r.pathname);s.endsWith("/")&&(s+="index.html");let n=!!r.search,i=s,u=f.join(e.outputDir,i),o=ue(e.targetOrigin,i),a=`${o}${r.search}`;if(!n)return {originalPathname:i,originalFilePath:u,originalPublicUrl:o,originalPublicUrlWithSearch:a,preferQueryHashed:n};let l=f.extname(s),m=`${l?s.slice(0,-l.length):s}.${ke(r.search)}${l||".bin"}`;return {originalPathname:i,originalFilePath:u,originalPublicUrl:o,originalPublicUrlWithSearch:a,preferQueryHashed:n,hashedPathname:m,hashedFilePath:f.join(e.outputDir,m),hashedPublicUrl:ue(e.targetOrigin,m)}}function pr(e,t,r,s,n){t[r]=s;try{let i=new URL(r),o=[new URL(e.sourceOrigin).origin,...Object.keys(e.extraReplacements||{})];if(e.targetOrigin&&e.targetOrigin!=="."&&e.targetOrigin!=="/")try{o.push(new URL(e.targetOrigin).origin);}catch{}for(let a of o)try{let l=new URL(a);t[l.origin+i.pathname+i.search]=s;}catch{}try{let a=(()=>{let l=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin);return `${l.pathname}${l.search}`})();t[i.pathname+i.search]=a;}catch{}try{let a=new URL(s,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=a;}catch{}try{let a=new URL(n,e.targetOrigin==="."?"https://relative.invalid":e.targetOrigin).pathname;t[i.pathname]=a;}catch{}}catch{}}async function ge(e){try{return await y.readFile(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function st(e){try{return await y.stat(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}function gr(e){let t=String(e["content-length"]||"").trim();if(!t)return null;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>=0?r:null}function nt(e){let t=String(e["last-modified"]||"").trim();if(!t)return null;let r=Date.parse(t);return Number.isFinite(r)?r:null}function hr(e,t){let r=nt(t),s=gr(t),n=e.mtime.getTime();return r!==null&&Math.abs(n-r)>=1e3||s!==null&&e.size!==s?false:r!==null||s!==null}async function mr(e,t){if(!t)return;let r=nt(t);if(r===null)return;let s=await st(e);if(!s)return;let n=new Date(r);await y.utimes(e,s.atime,n).catch(()=>{});}function de(e,t){let r=f.extname(e.pathname).toLowerCase(),s=t["content-type"]||"";return Ht.has(r)||qt.some(n=>s.includes(n))&&!s.startsWith("image/")&&!s.includes("font")}function _e(e,t){(e.doneAssets.size%25===0||e.doneAssets.size===1||e.doneAssets.size===e.stats.assetsQueued)&&t.progress(`Asset download progress: downloaded ${e.doneAssets.size}, discovered ${e.stats.assetsQueued}.`,{doneAssets:e.doneAssets.size,assetsQueued:e.stats.assetsQueued,phase:"download-assets"});}async function he(e,t,r,s,n,i,u){let o=we(e,r),a=o.originalFilePath,l=o.originalPublicUrlWithSearch;if(o.preferQueryHashed&&o.hashedFilePath&&o.hashedPublicUrl){let d=await ge(o.originalFilePath);d!==null&&!d.equals(s)&&(a=o.hashedFilePath,l=o.hashedPublicUrl);}pr(e,t,r,l,o.originalPublicUrl);let c=await ge(a),m=false;return (c===null||!c.equals(s))&&(await ae(a),await y.writeFile(a,s),m=true),await mr(a,u),n.stats.assetsSaved++,i&&(n.stats.assetsSaved%50===0||n.stats.assetsSaved===1)&&i.progress(`Asset progress: saved ${n.stats.assetsSaved}, discovered ${n.stats.assetsQueued}, pending ${n.assetQueue.length}.`,{assetsSaved:n.stats.assetsSaved,assetsQueued:n.stats.assetsQueued,assetQueue:n.assetQueue.length,phase:"download-assets"}),{outputPath:a,publicUrl:l,wroteFile:m}}function Z(e,t,r,s,n){let i=n&&/^https?:\/\//i.test(n)?n:e.sourceOrigin,u=R(e,r,i,s,"page");if(!u)return;if(!q(u)||rt(u)){if(b(e,u)){s.info(`Seeded/non-page URL queued as asset: ${u.toString()}`,{url:u.toString(),source:n}),T(e,t,u.toString(),s,n);return}s.reject("page",u.toString(),ee(u)?"asset/internal path cannot be page":"not page-like",n);return}let o=u.toString();!t.donePages.has(o)&&!t.queuedPages.has(o)&&(t.queuedPages.add(o),t.pageQueue.push(o),t.stats.pagesQueued++,(t.stats.pagesQueued%25===0||t.stats.pagesQueued===1)&&s.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,pageQueue:t.pageQueue.length,phase:"discovery"}));}function T(e,t,r,s,n){let i=n&&/^https?:\/\//i.test(n)?n:e.sourceOrigin,u=R(e,r,i,s,"asset");if(!u)return;if(!b(e,u)){s.reject("asset",u.toString(),"not a safe asset path/prefix",n);return}let o=u.toString();!t.doneAssets.has(o)&&!t.queuedAssets.has(o)&&(t.queuedAssets.add(o),t.assetQueue.push(o),t.stats.assetsQueued++,(t.stats.assetsQueued%100===0||t.stats.assetsQueued===1)&&s.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,assetQueue:t.assetQueue.length,phase:"discovery"}));}function Pe(e,t,r,s,n){let i=n&&/^https?:\/\//i.test(n)?n:e.sourceOrigin,u=R(e,r,i,s,"sitemap");if(!u)return;if(!te(u)){s.reject("sitemap",u.toString(),"not sitemap-like",n);return}let o=u.toString();!t.doneSitemaps.has(o)&&!t.queuedSitemaps.has(o)&&(t.queuedSitemaps.add(o),t.sitemapQueue.push(o),t.stats.sitemapsQueued++,(t.stats.sitemapsQueued%10===0||t.stats.sitemapsQueued===1)&&s.progress(`Discovery progress: pages ${t.stats.pagesQueued}, assets ${t.stats.assetsQueued}, sitemaps ${t.stats.sitemapsQueued}.`,{pagesQueued:t.stats.pagesQueued,assetsQueued:t.stats.assetsQueued,sitemapsQueued:t.stats.sitemapsQueued,sitemapQueue:t.sitemapQueue.length,phase:"discovery"}));}function fr(e){let t=E(e),r=[...t.matchAll(/<url>\s*([\s\S]*?)\s*<\/url>/gi)].map(s=>s[1]);return r.length>0?r.map(s=>{let n=s.match(/<loc>\s*([^<]+?)\s*<\/loc>/i);if(!n?.[1])return null;let i=s.match(/<lastmod>\s*([^<]+?)\s*<\/lastmod>/i);return {loc:n[1].trim(),lastmod:V(i?.[1]??null)}}).filter(s=>!!s):[...t.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)].map(s=>({loc:s[1].trim(),lastmod:null})).filter(s=>s.loc)}function wr(e){return e.split(",").map(t=>t.trim().split(/\s+/)[0]).filter(Boolean)}function Pr(e){let t=[],r=/url\(\s*(?:"([^"]+)"|'([^']+)'|([^)]*?))\s*\)/gi;for(let s of e.matchAll(r)){let n=(s[1]||s[2]||s[3]||"").trim();n&&t.push(n);}return t}function pe(e){return e.trim().replace(/\\/g,"/").replace(/^https?:\/\/[^/]+/i,"").replace(/^\/+/,"")}async function it(e,t){let r=[];await y.mkdir(t,{recursive:true});let s=await y.readdir(e,{withFileTypes:true});for(let n of s){let i=f.join(e,n.name),u=f.join(t,n.name);if(n.isDirectory()){r.push(...await it(i,u));continue}await y.copyFile(i,u),r.push(u);}return r}async function yr(e,t){let r=Object.entries(e.postCrawlCopyMap||{}).map(([i,u])=>({sourcePath:i.trim(),prefix:String(u||"").trim()}));if(r.length===0)return [];let s=0,n=[];t.mark("copy-extra-paths");for(let i of r){let u=i.sourcePath,o=i.prefix;if(!u||!o){t.warn("Skipped post-crawl copy mapping with empty key/value",{sourcePath:u,prefixPath:o});continue}let a=Gt(u);if(!a.resolvedPath){t.warn("Skipped post-crawl copy source because alias root is not configured",{sourcePath:u,alias:a.alias||"",requiredEnv:a.requiredEnv||"",prefixPath:o});continue}let l=a.resolvedPath,c=pe(o);if(!c){t.warn("Skipped post-crawl copy mapping with invalid export prefix",{sourcePath:u,prefixPath:o});continue}let m;try{m=await y.stat(l);}catch{t.warn("Skipped post-crawl copy source because it does not exist",{sourcePath:u,sourceAbs:l,prefixPath:o});continue}let d=f.resolve(e.outputDir,c);if(m.isDirectory()){n.push(...await it(l,d)),s++,t.progress(`Copied static directory to export: ${l} -> /${c}`,{phase:"copy-extra-paths",sourcePath:l,targetPath:`/${c}`,copiedItems:s});continue}let h=f.basename(l),p=o.endsWith("/")?f.join(d,h):d;await y.mkdir(f.dirname(p),{recursive:true}),await y.copyFile(l,p),n.push(p),s++,t.progress(`Copied static file to export: ${l} -> /${pe(o.endsWith("/")?`${o}${h}`:o)}`,{phase:"copy-extra-paths",sourcePath:l,targetPath:`/${pe(o.endsWith("/")?`${o}${h}`:o)}`,copiedItems:s});}return t.endMark("copy-extra-paths",{mappedSources:r.length,copiedItems:s}),n}function N(e,t,r,s,n){let i=new Set,u=E(r).replace(/\\\//g,"/");for(let l of Pr(u)){let c=R(e,l,t,s,`${n}:css-url`);c&&b(e,c)&&i.add(c.toString());}for(let l of u.matchAll(/@import\s+(?:url\()?\s*['"]?([^'"\s;]+)['"]?\s*\)?/gi)){let c=R(e,l[1],t,s,`${n}:css-import`);c&&b(e,c)&&i.add(c.toString());}for(let l of u.matchAll(/<\?xml-stylesheet[^>]+href=["']([^"']+)["'][^>]*\?>/gi)){let c=R(e,l[1],t,s,`${n}:xml-stylesheet`);c&&b(e,c)&&i.add(c.toString());}let o="(?:css|js|mjs|json|map|xml|xsl|rss|atom|txt|enc|jws|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|pdf|mp4|webm)",a=new RegExp(`(?:https?:)?//[^\\s'"<>\\);]+\\.${o}(?:\\?[^\\s'"<>\\);]*)?|(?<!\\.)/[^\\s'"<>\\);]+\\.${o}(?:\\?[^\\s'"<>\\);]*)?`,"gi");for(let l of u.matchAll(a)){let c=l[0].startsWith("//")?`${new URL(e.sourceOrigin).protocol}${l[0]}`:l[0];if(tt(c)){s.ignore(`${n}:serialized-url`,c,"looks like JavaScript/code fragment",t);continue}let m=R(e,c,t,s,`${n}:serialized-url`);m&&b(e,m)?i.add(m.toString()):m&&s.ignore("asset",m.toString(),"serialized URL did not pass safe asset path filter",t);}return [...i]}function Sr(e,t,r,s){let n=new Set,i=E(r);for(let u of i.matchAll(/href=["']([^"'#\s][^"']*?)["']/gi)){let o=u[1],a=R(e,o,t,s,"page-link");a&&(et(e,a)||q(a)&&!ee(a)&&!b(e,a)&&n.add(a.toString()));}return [...n]}async function We(e,t,r,s){for(;r.sitemapQueue.length>0;){let n=r.sitemapQueue.shift();if(r.queuedSitemaps.delete(n),!r.doneSitemaps.has(n)){r.doneSitemaps.add(n),s.sitemap(`Fetching sitemap ${n}`,{url:n});try{let i=await t.get(n,{timeout:6e4});if(!i.ok()){s.skip("sitemap",n,i.status());continue}let u=await i.body(),o=i.url()||n;await he(e,r.assetMap,o,u,r,s);let a=u.toString("utf8");for(let l of N(e,o,a,s,"sitemap"))T(e,r,l,s,o);for(let l of fr(a)){let c=R(e,l.loc,o,s,"sitemap-loc");c&&(te(c)?Pe(e,r,c.toString(),s,o):b(e,c)?T(e,r,c.toString(),s,o):q(c)?(l.lastmod&&(r.sitemapLastmodByPage[c.toString()]=l.lastmod),Z(e,r,c.toString(),s,o)):s.reject("sitemap-loc",c.toString(),"not page/sitemap/asset-like",o));}}catch(i){s.error(`Failed sitemap ${n}`,{url:n,error:String(i)});}}}}async function vr(e,t,r,s,n,i,u){let o=R(e,s,e.sourceOrigin,n,"asset-fetch");if(!o||!b(e,o))return;let a=o.toString();if(!r.doneAssets.has(a)){n.asset(`Fetching asset ${a}`,{url:a});try{let l=K(e,r.assetMap,a),c=l?await st(l):null;if(l&&c)try{let w=await t.head(a,{timeout:6e4}),S=w.headers();if(w.ok()&&hr(c,S)){let v=await ge(l);if(v!==null){let I=w.url()||a,C=await he(e,r.assetMap,I,v,r,n,S);C.wroteFile&&(D(u,e,C.outputPath),$(C.outputPath)&&B(u,C.outputPath)),r.doneAssets.add(a),n.info(`Reused existing asset ${a} based on response headers.`,{url:a,filePath:l,lastModified:S["last-modified"]||"",contentLength:S["content-length"]||"",phase:"download-assets"}),_e(r,n);let x=i.enabled?i.previousManifest.assets[a]:void 0,ye=de(o,S),re=x?.discoveredAssets?[...x.discoveredAssets]:[];if(ye||x?.isText){let at=v.toString("utf8"),Se=N(e,I,at,n,"asset:cached");(Se.length>0||!x)&&(re=Se);for(let ut of re)T(e,r,ut,n,I);}i.enabled&&(i.manifest.assets[a]={url:a,outputPath:C.outputPath,isText:ye||!!x?.isText,discoveredAssets:re,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId});return}}}catch{}let m=await t.get(a,{timeout:6e4});if(!m.ok()){n.skip("asset",a,m.status());return}let d=await m.body(),h=m.url()||a,p=m.headers(),P=await he(e,r.assetMap,h,d,r,n,p);P.wroteFile&&(D(u,e,P.outputPath),$(P.outputPath)&&B(u,P.outputPath)),r.doneAssets.add(a),_e(r,n);let g=[];if(de(o,p)){let w=d.toString("utf8");g=N(e,h,w,n,`asset:${f.extname(o.pathname).toLowerCase()||p["content-type"]||"unknown"}`);for(let S of g)T(e,r,S,n,h);}i.enabled&&(i.manifest.assets[a]={url:a,outputPath:P.outputPath,isText:de(o,p),discoveredAssets:g,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId});}catch(l){n.error(`Failed asset ${a}`,{url:a,error:String(l)});}}}async function br(e,t,r,s,n,i){let u=Math.max(1,Number(e.assetDownloadConcurrency||e.concurrency||1)),o=Array.from({length:u},async()=>{for(;r.assetQueue.length>0;){let a=r.assetQueue.shift();a&&(r.queuedAssets.delete(a),await vr(e,t,r,a,s,n,i));}});await Promise.all(o);}async function Rr(e){await e.evaluate(async()=>{await new Promise(t=>{let r=0,s=700,n=window.setInterval(()=>{window.scrollBy(0,s),r+=s,r>=document.body.scrollHeight+window.innerHeight&&(window.clearInterval(n),window.scrollTo(0,0),t());},120);});});}async function Cr(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForFunction&&await t.waitForFunction(e.readiness.waitForFunction,void 0,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await Rr(t),await t.waitForTimeout(e.readiness.fallbackWaitMs);}async function xr(e,t){await t.waitForLoadState("domcontentloaded",{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForLoadState("load",{timeout:e.readiness.timeoutMs}).catch(()=>{}),e.readiness.waitForSelector&&await t.waitForSelector(e.readiness.waitForSelector,{timeout:e.readiness.timeoutMs}).catch(()=>{}),await t.waitForTimeout(e.readiness.fallbackWaitMs);}function Ar(e,t){return e.noJavaScriptRenderPathPrefixes.some(r=>fe(t,r))}async function kr(e,t,r,s,n=true){let i=new Set;if(n){let o=await t.evaluate(()=>{let a=new Set,l=["href","src","poster","data-src","data-lazy-src","data-original","data-bg","data-background","data-href"],c=new Set,m=["srcset","data-srcset","data-lazy-srcset"];return document.querySelectorAll("*").forEach(d=>{for(let p of l){let P=d.getAttribute(p);P&&a.add(P);}for(let p of m){let P=d.getAttribute(p);P&&P.split(",").forEach(g=>{let w=g.trim().split(/\s+/)[0];w&&a.add(w);});}let h=d.getAttribute("style");h&&c.add(h);}),{attrs:[...a],styles:[...c]}});for(let a of o.attrs)for(let l of wr(a)){let c=R(e,l,r,s,"dom-attr");c&&b(e,c)&&i.add(c.toString());}for(let a of o.styles)for(let l of N(e,r,a,s,"dom-style"))i.add(l);}let u=await t.content();for(let o of N(e,r,u,s,"page-html"))i.add(o);return [...i]}async function He(e,t,r,s,n){let i=Y(e,t);await ae(i),await y.writeFile(i,r,"utf8"),s.stats.pagesSaved++,n&&(s.stats.pagesSaved%10===0||s.stats.pagesSaved===1)&&n.progress(`Page progress: processed ${s.donePages.size}, rendered ${s.stats.pagesRendered}, saved ${s.stats.pagesSaved}, discovered ${s.stats.pagesQueued}.`,{donePages:s.donePages.size,pagesRendered:s.stats.pagesRendered,pagesSaved:s.stats.pagesSaved,pagesQueued:s.stats.pagesQueued,pageQueue:s.pageQueue.length,phase:"save-pages"});}function Je(e){return e.donePages.size%5===0||e.donePages.size===1||e.donePages.size===e.stats.pagesQueued}function ze(e,t){t.progress(`Render progress: processed ${e.donePages.size}, rendered ${e.stats.pagesRendered}, saved ${e.stats.pagesSaved}, discovered ${e.stats.pagesQueued}.`,{donePages:e.donePages.size,pagesRendered:e.stats.pagesRendered,pagesSaved:e.stats.pagesSaved,pagesQueued:e.stats.pagesQueued,phase:"render-pages"});}async function Mr(e){await e.addInitScript(()=>{Object.defineProperty(window,"__WPSUITE_STATIC_EXPORT__",{value:true,writable:false,configurable:true});let t=r=>{if(r==null||String(r)==="")return true;try{let s=new URL(String(r),window.location.href),n=new URL(window.location.href);return s.hash="",n.hash="",s.href===n.href}catch{return false}};try{let r=window.location.assign.bind(window.location),s=window.location.replace.bind(window.location),n=window.location.reload.bind(window.location);Object.defineProperty(window.location,"assign",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.assign",i??"");return}return r(i)}}),Object.defineProperty(window.location,"replace",{configurable:!0,value:i=>{if(t(i)){console.warn("[smartcloud-static-publisher] blocked same-page location.replace",i??"");return}return s(i)}}),Object.defineProperty(window.location,"reload",{configurable:!0,value:()=>{console.warn("[smartcloud-static-publisher] blocked location.reload");}});}catch{}});}async function Tr(e,t,r,s,n,i,u){let o=await chromium.launch({headless:true}),a=await o.newContext({viewport:e.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",ignoreHTTPSErrors:e.ignoreHttpsErrors}),l=await o.newContext({viewport:e.viewport,userAgent:"WPSuiteStaticPublisher/0.8 Playwright SitemapOnly",javaScriptEnabled:false,ignoreHTTPSErrors:e.ignoreHttpsErrors});await Mr(a);try{for(;t.pageQueue.length>0&&!(e.maxPages>0&&t.donePages.size>=e.maxPages);){let c=t.pageQueue.shift();if(!c)break;if(t.queuedPages.delete(c),t.donePages.has(c))continue;t.donePages.add(c),i.enabled&&i.seenPages.add(c);let m=new URL(c),d=Ar(e,m.pathname);if(!q(m)||b(e,m)||ee(m)){if(b(e,m)){r.info(`Worker redirected non-page URL to asset queue: ${c}`,{url:c,source:"worker-guard"}),T(e,t,c,r,"worker-guard");continue}r.reject("page",c,"guard rejected non-page URL before rendering","worker");continue}let h=await tr(e,n,t,i,c,r);if(i.enabled&&s!=="single-url"){let g=i.manifest.pages[c];if(h.action==="reuse"&&g){for(let w of g.discoveredAssets)T(e,t,w,r,c);for(let w of g.discoveredPages)Z(e,t,w,r,c);g.lastSeenRunId=i.runId,g.sitemapLastmod=V(t.sitemapLastmodByPage[c])??g.sitemapLastmod,h.changeToken?.supported&&(g.changeToken=h.changeToken.token,g.tokenSource=h.changeToken.tokenSource??g.tokenSource),r.info(`Incremental reuse skipped unchanged page ${c}`,{url:c,mode:"incremental",reason:h.changeToken?.supported===!0?"change-token-match":"sitemap-lastmod-match"}),Je(t)&&ze(t,r);continue}}let p=await(d?l.newPage():a.newPage()),P=!1;await p.route("**/*",async g=>{let w=g.request();if(w.isNavigationRequest()&&w.frame()===p.mainFrame())try{let S=new URL(w.url()),v=new URL(c);if(S.hash="",v.hash="",S.href===v.href){if(P){r.warn(`Blocked same-page navigation/reload for ${c}`,{url:c,requestUrl:w.url()}),await g.abort("aborted");return}P=!0;}}catch{}await g.continue();}),p.on("response",g=>{try{let w=R(e,g.url(),e.sourceOrigin,void 0,"network-response");w&&b(e,w)&&T(e,t,w.toString(),r,c);}catch{}}),r.page(`Rendering ${c}`,{url:c});try{let g=null,w=null;try{if(g=await p.goto(c,{waitUntil:"domcontentloaded",timeout:e.navigationTimeoutMs}),g&&g.ok())try{w=await g.text();}catch{w=null;}}catch(x){r.warn(`Navigation issue for ${c}; saving current DOM if available`,{url:c,error:String(x)});}if(g&&!g.ok()){r.skip("page",c,g.status()),await p.close();continue}d?(r.info(`Rendering without JS execution for ${c}`,{url:c,mode:"no-js"}),await xr(e,p)):await Cr(e,p),t.stats.pagesRendered++,Je(t)&&ze(t,r);let S=await kr(e,p,c,r,!d);for(let x of S)T(e,t,x,r,c);let v=w??await p.content(),I=s!=="single-url"?Sr(e,c,v,r):[];if(s!=="single-url")for(let x of I)Z(e,t,x,r,c);await He(e,c,v,t,r);let C=Y(e,c);D(u,e,C),B(u,C),i.enabled&&(i.manifest.pages[c]={url:c,outputPath:C,changeToken:h.changeToken?.supported?h.changeToken.token:null,tokenSource:h.changeToken?.supported?h.changeToken.tokenSource??null:null,sitemapLastmod:V(t.sitemapLastmodByPage[c])??null,discoveredPages:I,discoveredAssets:S,lastCrawledAt:new Date().toISOString(),lastSeenRunId:i.runId});}catch(g){try{let w=await p.content();if(w&&w.trim()){await He(e,c,w,t,r);let S=Y(e,c);D(u,e,S),B(u,S),r.warn(`Saved partial DOM for ${c}`,{url:c,error:String(g)});}}catch(w){r.error(`Could not save partial DOM for ${c}`,{url:c,error:String(w)});}r.error(`Failed page ${c}`,{url:c,error:String(g)});}finally{await p.close();}}}finally{await l.close(),await a.close(),await o.close();}}async function Lr(e){try{let t=await y.readFile(e),s=(e.endsWith(".gz")?gunzipSync(t):t).toString("utf8").trim();if(!s)return [];try{let n=JSON.parse(s);if(Array.isArray(n))return n;if(n&&typeof n=="object")return [n]}catch{return s.split(/\r?\n/).map(n=>n.trim()).filter(Boolean).map(n=>{try{let i=JSON.parse(n);return i&&typeof i=="object"?i:null}catch{return null}}).filter(n=>n!==null)}return []}catch{return []}}function Be(e){let t=String(e||"").toLowerCase();return t.includes("timeout")||t.includes("timed out")||t.includes("navigation timeout")}function Er(e){let t=String(e?.job?.command||"").trim(),r=String(e?.job?.crawlMode||"full").trim();return t!=="publish"&&t!=="crawl"?false:r!=="incremental"}function Dr(e){let t=[e?.archivedAt,e?.job?.endedAt,e?.job?.startedAt];for(let r of t){let s=Date.parse(String(r||""));if(Number.isFinite(s))return s}return 0}async function ot(e){try{let t=await y.readFile(e,"utf8"),r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function Ve(e){let t=String(e.originalFileName||"").toLowerCase();return t.endsWith("errors.jsonl")?0:t.endsWith("errors.json")?1:2}function Ir(e,t){let r=Array.isArray(t?.artifacts)?t.artifacts.filter(s=>String(s?.role||"").trim()==="errors"&&String(s?.storedFileName||"").trim()!=="").sort((s,n)=>Ve(s)-Ve(n)).map(s=>f.join(e,String(s.storedFileName))):[];return [...new Set([...r,f.join(e,"errors.jsonl"),f.join(e,"errors.json"),f.join(e,"errors.jsonl.gz"),f.join(e,"errors.json.gz")])]}async function Ge(e){let t=await ot(f.join(e,"job.json"));for(let r of Ir(e,t)){let s=await Lr(r);if(s.length>0)return s}return []}async function Fr(e){let t=f.join(e.logDir,"archive"),r;try{r=await y.readdir(t);}catch{return ""}let s="",n=0;for(let i of r){let u=f.join(t,i);if(!(await y.stat(u).catch(()=>null))?.isDirectory())continue;let a=await ot(f.join(u,"job.json"));if(!Er(a))continue;let l=Dr(a);l>=n&&(n=l,s=u);}return s}async function jr(e){let t=await Fr(e),r=t!==""?await Ge(t):await Ge(e.logDir),s=new Set;for(let n of r)if(Be(n.error)||Be(n.message)){let i=n.url;typeof i=="string"&&i&&s.add(i);}return [...s]}async function Or(e){let t=[];for(let r of e)if(r.startsWith("@")){let s=r.slice(1),n=await y.readFile(s,"utf8");t.push(...n.split(/\r?\n/).map(i=>i.trim()).filter(i=>i&&!i.startsWith("#")));}else t.push(r);return t}async function $r(e){try{let t=await y.readFile(f.join(e.outputDir,"asset-map.json"),"utf8");return JSON.parse(t)}catch{return {}}}async function Ur(e){let t=["crawl.log.jsonl","current-crawl-event.json","rejected.jsonl","ignored.jsonl","skipped-http.jsonl","errors.jsonl","timings.jsonl","rejected.json","ignored.json","skipped-http.json","errors.json","timings.json"];await y.mkdir(e,{recursive:true}),await Promise.all(t.map(async r=>{try{await y.unlink(f.join(e,r));}catch(s){if(s.code!=="ENOENT")throw s}}));}function Ke(e,t,r,s,n){let i=R(e,r,e.sourceOrigin,s,"manual-url");i&&(te(i)?Pe(e,t,i.toString(),s,n):b(e,i)?T(e,t,i.toString(),s,n):q(i)?Z(e,t,i.toString(),s,n):s.reject("manual-url",i.toString(),"not page/sitemap/asset-like",n));}async function Qr(){let e=await oe(),t=zt(process.argv.slice(2));if(t.resumeRewrite&&t.mode!=="full")throw new Error("--resume-rewrite is only supported for full crawl/publish jobs.");let r=[];t.mode==="retry-timeouts"&&(r=await jr(e)),t.mode==="single-url"&&(r=await Or(t.urls));let s=t.crawlMode==="incremental"&&t.mode==="full",n=t.preserveOutput?await $r(e):{},i=s?await Xt(e):Ze(),u={enabled:s,manifest:$e(i),previousManifest:$e(i),runId:`${Date.now()}`,seenPages:new Set,changeTokenCache:new Map};await Ur(e.logDir);let o={pageQueue:[],queuedPages:new Set,donePages:new Set,assetQueue:[],queuedAssets:new Set,doneAssets:new Set,sitemapQueue:[],queuedSitemaps:new Set,doneSitemaps:new Set,sitemapLastmodByPage:{},assetMap:{...n},stats:{pagesQueued:0,pagesRendered:0,assetsQueued:0,sitemapsQueued:0,assetsSaved:0,pagesSaved:0}},a=Kt();t.preserveOutput||await y.rm(e.outputDir,{recursive:true,force:true}),await y.mkdir(e.outputDir,{recursive:true});let l=new Q(e.logDir,e.logLevel);if(t.resumeRewrite)l.info("Resuming final rewrite from existing output.",{phase:"rewrite-text",mode:t.mode,crawlMode:t.crawlMode});else {let p=await chromium.launch({headless:true}),P=await p.newContext({ignoreHTTPSErrors:e.ignoreHttpsErrors}),g=P.request;try{if(l.mark("discovery"),t.mode==="full"?(e.sitemapPaths.forEach(S=>Pe(e,o,S,l)),await We(e,g,o,l),e.seedPaths.forEach(S=>Ke(e,o,S,l,"seed-path"))):(r.forEach(S=>Ke(e,o,S,l,"cli")),await We(e,g,o,l)),l.endMark("discovery",{pages:o.pageQueue.length,assets:o.assetQueue.length,sitemaps:o.sitemapQueue.length}),l.summary(`Queued ${o.pageQueue.length} pages, ${o.assetQueue.length} assets, ${o.sitemapQueue.length} sitemaps.`,{mode:t.mode,crawlMode:t.crawlMode,queuedPages:o.pageQueue.length,queuedAssets:o.assetQueue.length,queuedSitemaps:o.sitemapQueue.length}),t.mode==="retry-timeouts"&&o.pageQueue.length===0&&o.assetQueue.length===0&&o.sitemapQueue.length===0){l.summary("No timed-out URLs were queued. Skipping retry crawl.",{mode:t.mode,crawlMode:t.crawlMode,queuedPages:0,queuedAssets:0,queuedSitemaps:0}),await l.flush();return}l.mark("render-pages");let w=Array.from({length:Math.max(1,e.concurrency)},()=>Tr(e,o,l,t.mode,g,u,a));if(await Promise.all(w),l.endMark("render-pages",{pages:o.donePages.size}),l.mark("download-assets"),await br(e,g,o,l,u,a),l.endMark("download-assets",{assets:o.doneAssets.size}),u.enabled&&e.maxPages===0&&await rr(e,o,u,l,a),t.mode==="full"){let S=await yr(e,l);for(let v of S)D(a,e,v);}}finally{await P.close(),await p.close();}}u.enabled&&!t.resumeRewrite&&(u.manifest.updatedAt=new Date().toISOString(),await Yt(e,u.manifest)),await y.writeFile(f.join(e.outputDir,"asset-map.json"),JSON.stringify(o.assetMap,null,2),"utf8"),JSON.stringify(n,null,2)!==JSON.stringify(o.assetMap,null,2)&&D(a,e,f.join(e.outputDir,"asset-map.json"));let c=t.mode==="single-url"?or(e,o):u.enabled&&!t.resumeRewrite?sr(e,u,a,n,o.assetMap):void 0;l.mark("rewrite-text");let m=t.mode==="single-url"?`Rewriting text files touched by URL crawl: 0/${c?.length??0}`:"Rewriting text files...";l.progress(m,{phase:"rewrite-text",index:0,totalFiles:c?.length,changedTextFiles:0}),await qe(m);let d=Date.now(),h=await De(e,o.assetMap,{files:c,previousAssetMap:n,onProgress:async({index:p,totalFiles:P,changedTextFiles:g,file:w,changed:S})=>{S&&D(a,e,f.join(e.outputDir,w)),l.checkpoint(`Rewriting text file ${p}/${P}`,{phase:"rewrite-text",index:p,totalFiles:P,changedTextFiles:g,file:w});let v=Date.now();if(!(p===1||p===P||v-d>=5e3))return;d=v;let C=`Rewriting text files: ${p}/${P}`;l.progress(C,{phase:"rewrite-text",index:p,totalFiles:P,changedTextFiles:g,file:w}),await qe(C);}});l.endMark("rewrite-text",{changedTextFiles:h}),await Re(e,{generatedAt:new Date().toISOString(),outputDir:f.resolve(e.outputDir),runMode:t.mode,crawlMode:t.crawlMode,fullSyncRequired:!(u.enabled&&!t.resumeRewrite),changedFiles:u.enabled&&!t.resumeRewrite?[...a.changedFiles].sort():[],deletedFiles:u.enabled&&!t.resumeRewrite?[...a.deletedFiles].sort():[],rewriteTargets:u.enabled&&!t.resumeRewrite?[...new Set((c||[]).map(p=>_(e.outputDir,f.isAbsolute(p)?p:f.join(e.outputDir,p))).filter(p=>p!==null))].sort():[]}),l.summary(t.resumeRewrite?`Done. Resumed final rewrite over existing output and changed ${h} text files.`:`Done. Rendered ${o.stats.pagesRendered} pages, processed ${o.doneSitemaps.size} sitemaps, downloaded ${o.doneAssets.size} assets.`,{mode:t.mode,crawlMode:t.crawlMode,resumeRewrite:t.resumeRewrite,...o.stats,pagesRendered:o.stats.pagesRendered,donePages:o.donePages.size,doneSitemaps:o.doneSitemaps.size,doneAssets:o.doneAssets.size,changedTextFiles:h}),await l.flush();}Qr().catch(async e=>{console.error(e);try{let r=(await oe().catch(()=>null))?.logDir??"logs",s=new Q(r,"debug");s.error(`Unhandled error: ${e instanceof Error?e.message:String(e)}`,e instanceof Error?{stack:e.stack}:void 0),await s.flush();}catch{}process.exit(1);});
|
package/dist/deploy.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {S3Client,ListObjectsV2Command,HeadObjectCommand,GetObjectCommand,DeleteObjectsCommand}from'@aws-sdk/client-s3';import {Upload}from'@aws-sdk/lib-storage';import {
|
|
2
|
-
`,"utf8");}var
|
|
3
|
-
`,"utf8");});}enqueueJsonLine(r,e){this.enqueueTask(()=>
|
|
1
|
+
import {S3Client,ListObjectsV2Command,HeadObjectCommand,GetObjectCommand,DeleteObjectsCommand}from'@aws-sdk/client-s3';import {Upload}from'@aws-sdk/lib-storage';import {createHash}from'crypto';import rt from'fast-glob';import $ from'fs/promises';import S from'path';import Dt from'mime-types';import {availableParallelism}from'os';import {Worker}from'worker_threads';function ge(t){let r=t.trim();return r==="."?".":r.replace(/\/$/,"")}function Q(t){return !t||typeof t!="object"?{}:Object.fromEntries(Object.entries(t).map(([r,e])=>[r.trim(),String(e??"")]).filter(([r])=>r.length>0))}function Je(t){if(!t||typeof t!="object")return {};let r={};for(let[e,n]of Object.entries(t)){let s=e.trim();if(!s||!n||typeof n!="object")continue;let i=n,o={};if(typeof i.targetOrigin=="string"){let a=ge(i.targetOrigin);a&&(o.targetOrigin=a);}let u=Q(i.extraReplacements);if(Object.keys(u).length>0&&(o.extraReplacements=u),i.s3&&typeof i.s3=="object"){let a={},l=i.s3;typeof l.bucket=="string"&&(a.bucket=l.bucket.trim()),typeof l.prefix=="string"&&(a.prefix=l.prefix.trim()),typeof l.region=="string"&&(a.region=l.region.trim()),typeof l.htmlCacheControl=="string"&&(a.htmlCacheControl=l.htmlCacheControl.trim()),typeof l.assetCacheControl=="string"&&(a.assetCacheControl=l.assetCacheControl.trim()),Object.keys(a).length>0&&(o.s3=a);}if(i.cloudFront&&typeof i.cloudFront=="object"){let a={},l=i.cloudFront;typeof l.distributionId=="string"&&(a.distributionId=l.distributionId.trim()),Array.isArray(l.invalidationPaths)&&(a.invalidationPaths=l.invalidationPaths.map(g=>String(g??"").trim()).filter(g=>g.length>0)),Object.keys(a).length>0&&(o.cloudFront=a);}r[s]=o;}return r}function V(t,r){let n=String(t||"").replace(/\\/g,"/").trim().replace(/^\/+|\/+$/g,"");if(!n)return r;let s=n.split("/").map(i=>i.trim()).filter(i=>i.length>0&&i!=="."&&i!=="..");return s.length>0?s.join("/"):r}function Ke(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?S.resolve(t):""}function ue(t,r,e){let n=String(r||"").trim();return n&&S.isAbsolute(n)?S.resolve(n):S.resolve(t,V(n,e))}async function G(){let t=process.env.PUBLISHER_CONFIG||"publisher.config.json",r=await $.readFile(t,"utf8"),e=JSON.parse(r);e.sourceOrigin=e.sourceOrigin.replace(/\/$/,""),e.targetOrigin=ge(e.targetOrigin),e.ignoreHttpsErrors??=false,e.outputDir=String(e.outputDir||"export").trim()||"export",e.urlRewriteMode||=e.targetOrigin==="."?"relative":"absolute",e.noJavaScriptRenderPathPrefixes||=[],e.seedPaths||=[],e.sitemapPaths||=["/sitemap_index.xml","/sitemap.xml"],e.allowedAssetHosts||=[],e.assetPathPrefixes||=["/wp-content/","/wp-includes/","/static/","/assets/","/build/","/_next/","/docs/","/sitemap","/robots.txt","/llms.txt"],e.blockedPathPrefixes||=[],e.blockedSearchFragments||=[],e.concurrency||=1,e.maxPages||=0,e.extraReplacements=Q(e.extraReplacements),e.postCrawlCopyMap=Q(e.postCrawlCopyMap),e.logDir=String(e.logDir||"logs").trim()||"logs",e.verbose??=false,e.logLevel||=e.verbose?"debug":"info",e.s3SyncMode||="sdk-upload-delete",e.readiness||={waitForSelector:null,waitForFunction:null,timeoutMs:1500,fallbackWaitMs:1500},e.readiness.timeoutMs??=1500,e.readiness.fallbackWaitMs??=1500,e.viewport||={width:1440,height:1200},e.navigationTimeoutMs||=3e4,e.scheduler||={enabled:false,timezone:"UTC",rules:[]},e.scheduler.enabled??=false,e.scheduler.timezone||="UTC",e.scheduler.rules||=[],e.deploymentProfiles=Je(e.deploymentProfiles),e.assetDownloadConcurrency=Number(e.assetDownloadConcurrency)>0?Number(e.assetDownloadConcurrency):e.concurrency,e.rewriteConcurrency=Number(e.rewriteConcurrency)>0?Number(e.rewriteConcurrency):e.assetDownloadConcurrency,e.defaultDeploymentProfile=String(e.defaultDeploymentProfile??"").trim(),e.defaultDeploymentProfile&&!e.deploymentProfiles[e.defaultDeploymentProfile]&&(e.defaultDeploymentProfile="");let n=Ke(),s=n?S.resolve(n,".."):"";return s?(e.outputDir=ue(s,e.outputDir,"export"),e.logDir=ue(s,e.logDir,"logs")):(S.isAbsolute(e.outputDir)||(e.outputDir=V(e.outputDir,"export")),S.isAbsolute(e.logDir)||(e.logDir=V(e.logDir,"logs"))),e}var Be=".deploy-plan.json",We="deploy-plan.json";function qe(){let t=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"";return t.trim()?S.resolve(t):""}function Qe(t){let r=String(t||"").replace(/\\/g,"/").replace(/^\/+/,"").trim();return !r||r==="."||r.startsWith("../")||r===".."?null:r}function Z(t){return [...new Set(t.map(Qe).filter(r=>r!==null))]}function Ve(t,r){return {schemaVersion:1,generatedAt:String(r.generatedAt||new Date().toISOString()),outputDir:S.resolve(t.outputDir),runMode:r.runMode,crawlMode:r.crawlMode,fullSyncRequired:!!r.fullSyncRequired,changedFiles:Z(r.changedFiles||[]),deletedFiles:Z(r.deletedFiles||[]),rewriteTargets:Z(r.rewriteTargets||[])}}function Ge(t){if(!t||typeof t!="object")return false;let r=t;return r.schemaVersion===1&&typeof r.generatedAt=="string"&&typeof r.outputDir=="string"&&(r.runMode==="full"||r.runMode==="retry-timeouts"||r.runMode==="single-url")&&(r.crawlMode==="full"||r.crawlMode==="incremental")&&typeof r.fullSyncRequired=="boolean"&&Array.isArray(r.changedFiles)&&Array.isArray(r.deletedFiles)&&Array.isArray(r.rewriteTargets)}function pe(t){let r=S.join(S.resolve(t.outputDir),Be),e=qe();return e?[S.join(e,We),r]:[r]}async function de(t){let r=S.resolve(t.outputDir);for(let e of pe(t))try{let n=await $.readFile(e,"utf8"),s=JSON.parse(n);if(!Ge(s)||S.resolve(s.outputDir)!==r)continue;return Ve(t,s)}catch{}return null}async function fe(t){for(let r of pe(t))try{await $.unlink(r);}catch(e){if(e.code!=="ENOENT")throw e}}function me(t){let r="";for(let n=0;n<t.length;n++){let s=t[n];if(s==="--profile"){let i=(t[n+1]||"").trim();if(!i)throw new Error("Missing value for --profile.");r=i,n+=1;}else if(s.startsWith("--profile=")){let i=s.slice(10).trim();if(!i)throw new Error("Missing value for --profile.");r=i;}}let e=String(process.env.PUBLISHER_DEPLOY_PROFILE||process.env.PUBLISHER_DEPLOYMENT_PROFILE||"").trim();return r||e||null}function Ze(t,r){return {...t,...r??{}}}function Ye(t,r){return {...t,...r??{},invalidationPaths:[...(r?.invalidationPaths??t.invalidationPaths)||[]]}}function he(t,r){let e=String(r??t.defaultDeploymentProfile??"").trim();if(!e)return {name:null,profile:null,config:t};let n=t.deploymentProfiles?.[e];if(!n)throw new Error(`Unknown deployment profile "${e}". Check deploymentProfiles in publisher.config.json.`);return {name:e,profile:n,config:{...t,targetOrigin:n.targetOrigin??t.targetOrigin,s3:Ze(t.s3,n.s3),cloudFront:Ye(t.cloudFront,n.cloudFront)}}}var we={error:0,warn:1,info:2,debug:3},ye=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",H=ye?S.join(ye,"current-progress.json"):"",Pe=Promise.resolve();function be(t){return t.includes("crawl")?"crawl":t.includes("deploy")?"deploy":t.includes("invalidate")?"invalidate":t}function Xe(t,r){let e={...t},n=new Set(["pagesQueued","pagesRendered","assetsQueued","sitemapsQueued","pagesDiscovered","assetsDiscovered","sitemapsDiscovered","pagesSaved","assetsSaved","donePages","doneAssets","doneSitemaps","changedTextFiles","uploaded","failed","index","totalFiles","pageQueue","assetQueue","sitemapQueue"]);for(let[s,i]of Object.entries(r)){let o=e[s];if(typeof o=="number"&&typeof i=="number"&&n.has(s)){e[s]=Math.max(o,i);continue}e[s]=i;}return e}function et(t,r,e){H&&(Pe=Pe.then(async()=>{let n=new Date,s=n.toISOString();await $.mkdir(S.dirname(H),{recursive:true});let i=await $.readFile(H,"utf8").then(b=>JSON.parse(b)).catch(()=>null),o=i&&typeof i.details=="object"&&i.details?i.details:{},u=be(t),a=i?.currentStep||be(i?.source||""),l=i?.startedAt||s,g={...i?.stepDurationsSec??{}},m=i?.stepStartedAt||s;if(a&&a!==u&&i?.stepStartedAt){let b=Math.max(0,Math.round((n.getTime()-new Date(i.stepStartedAt).getTime())/1e3));g[a]=(g[a]??0)+b,m=s;}let c=Math.max(0,Math.round((n.getTime()-new Date(m).getTime())/1e3)),w=Math.max(0,Math.round((n.getTime()-new Date(l).getTime())/1e3)),P={checkedAt:s,source:t,message:r,details:Xe(o,e??{}),startedAt:l,currentStep:u,stepStartedAt:m,stepElapsedSec:c,totalElapsedSec:w,stepDurationsSec:g};await $.writeFile(H,JSON.stringify(P,null,2),"utf8");}).catch(()=>{}));}async function tt(t,r){await $.mkdir(S.dirname(t),{recursive:true}),await $.appendFile(t,`${JSON.stringify(r)}
|
|
2
|
+
`,"utf8");}var A=class{constructor(r,e,n="info"){this.logDir=r;this.logFile=e;this.level=n;this.ensureLogFileReady();}logDir;logFile;level;startedAt=Date.now();marks=new Map;initPromise=null;writeQueue=Promise.resolve();writeError=null;get logPath(){return S.join(this.logDir,this.logFile)}get errorsPath(){return S.join(this.logDir,this.logFile.replace(".log.jsonl",".errors.jsonl"))}ensureLogFileReady(){return this.initPromise||(this.initPromise=(async()=>{await $.mkdir(this.logDir,{recursive:true}),await $.writeFile(this.logPath,"","utf8");})()),this.initPromise}enqueueTask(r){this.writeQueue=this.writeQueue.then(r).catch(e=>{this.writeError=e instanceof Error?e:new Error(String(e));});}enqueueLine(r){this.enqueueTask(async()=>{await this.ensureLogFileReady(),await $.appendFile(this.logPath,`${r}
|
|
3
|
+
`,"utf8");});}enqueueJsonLine(r,e){this.enqueueTask(()=>tt(r,e));}accepts(r){return we[r]<=we[this.level]}push(r,e,n){if(!this.accepts(r))return;let s=JSON.stringify({time:new Date().toISOString(),level:r,message:e,...n||{}});this.enqueueLine(s),r==="error"?console.error(`[ERROR] ${e}`,n?JSON.stringify(n):""):r==="warn"?console.warn(`[WARN] ${e}`,n?JSON.stringify(n):""):console.log(`[${r.toUpperCase().padEnd(5)}] ${e}`);}info(r,e){this.push("info",r,e);}progress(r,e){et(this.logFile,r,e);}debug(r,e){this.push("debug",r,e);}warn(r,e){this.push("warn",r,e);}error(r,e){this.enqueueJsonLine(this.errorsPath,{message:r,...e||{}}),this.push("error",r,e);}mark(r){this.marks.set(r,Date.now());}endMark(r,e){let n=this.marks.get(r);if(!n)return;let s=Date.now()-n,i=Number((s/1e3).toFixed(2));this.push("info",`Timing ${r}: ${i}s`,{name:r,ms:s,seconds:i,...e||{}});}async flush(){let r=Date.now()-this.startedAt,e=Number((r/1e3).toFixed(2));if(this.push("info",`Total time: ${e}s`,{name:"total",ms:r,seconds:e}),await this.writeQueue,this.writeError)throw this.writeError}};function Se(t){return [".html",".htm",".css",".js",".mjs",".json",".xml",".xsl",".txt",".svg",".map",".enc",".jws"].includes(S.extname(t).toLowerCase())}function xe(t){return t.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function F(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function J(t){return t.replace(/\//g,"\\/")}function ve(t){return t.replace(/\//g,"\\\\/")}function K(t,r,e){if(!r)return;t[r]=e;let n=J(r),s=J(e);t[n]=s;let i=ve(r),o=ve(e);t[i]=o;let u=F(r),a=F(e);t[u]=a;let l=F(n),g=F(s);t[l]=g;let m=F(i),c=F(o);t[m]=c;}function De(t,r){try{return new URL(t,r==="."?"https://relative.invalid":r).pathname}catch{return t.startsWith("/")?t:`/${t.replace(/^\.\//,"")}`}}function $e(t,r,e){if(!r)return e;let n=S.dirname(S.resolve(r)),s=S.resolve(t,e.replace(/^\/+/,"")),i=S.relative(n,s).replace(/\\/g,"/");return i?(i.startsWith(".")||(i=`./${i}`),i):"."}var st=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],ot=new Set([".html",".htm"]),Ce="WPSuite.io Static Publisher",at=Ce.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function lt(t,r,e){if(t.wpsuite?.subscriber===true||!e)return false;let n=S.extname(e).toLowerCase();return ot.has(n)?/<head\b|<html\b|<!doctype html/i.test(r):false}function ut(t){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${at}\\2)[^>]*\\/?>`,"i").test(t))return t;let r=`<meta name="generator" content="${Ce}" />`;if(t.match(/(\r?\n)([ \t]*)<\/head>/i))return t.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${r}$1$2</head>`);let n=t.includes(`\r
|
|
4
4
|
`)?`\r
|
|
5
5
|
`:`
|
|
6
|
-
`;return t.replace(/<head\b[^>]*>/i,s=>`${s}${i} ${r}`)}function Ke(t){let r=pe(t).trim();return r.startsWith("{")||r.startsWith("[")||r.includes("\\/")||/"@context"|"@type"/.test(r)}function qe(t,r){let e=[...new Set(r)].filter(n=>n.includes("/")&&!/\\+\//.test(n)).map(n=>[n,N(n)]).filter(([n,o])=>n!==o).sort((n,o)=>o[0].length-n[0].length);if(!e.length)return t;let i=n=>{let o=n;for(let[l,a]of e)o=o.split(l).join(a);return o},s=t.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(n,o,l,a)=>`${o}${i(l)}${a}`);return s=s.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(n,o,l,a,c)=>Ke(a)?`${o}${i(a)}${c}`:n),s}function Qe(t,r){if(!r)return null;let e=v.dirname(v.resolve(r)),i=v.resolve(t.outputDir),s=v.relative(e,i).replace(/\\/g,"/");return s?(s.startsWith(".")||(s=`./${s}`),s.endsWith("/")?s:`${s}/`):"./"}function Ve(t,r,e){let i=Qe(r,e);if(!i)return t;let s=t;for(let n of Ue){let o=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l=new RegExp(`(?:\\.{1,}/)+${o}`,"g"),a=new RegExp(`(?<!\\.)/${o}`,"g");s=s.replace(l,`${i}${n}`).replace(a,`${i}${n}`);let c=n.replace(/\//g,"\\/"),u=i.replace(/\//g,"\\/"),g=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),d=new RegExp(`(?:\\.{1,}\\\\/)+${g}`,"g"),p=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${g}`,"g"),x=new RegExp(`(?<![\\.\\\\])\\/${g}`,"g");s=s.replace(d,`${u}${c}`).replace(p,`${u}${c}`).replace(x,`${u}${c}`);}return s}function Ge(t,r,e){if(t.urlRewriteMode==="absolute")return r;let i=(()=>{try{return new URL(r,t.targetOrigin==="."?"https://relative.invalid":t.targetOrigin)}catch{return null}})(),s=i?i.pathname:fe(r,t.targetOrigin),n=i?`${i.search}${i.hash}`:"";return t.urlRewriteMode==="root-relative"?`${s}${n}`:`${me(t.outputDir,e,s)}${n}`}function V(t,r,e,i,s){de(t,e,Ge(r,i,s));}function Ze(t,r,e,i){let s=t,n={};V(n,r,r.sourceOrigin,r.targetOrigin,i);for(let[l,a]of Object.entries(r.extraReplacements))V(n,r,l,a,i);for(let[l,a]of Object.entries(e))V(n,r,l,a,i);let o=Object.entries(n).sort((l,a)=>a[0].length-l[0].length);for(let[l,a]of o)s=s.split(l).join(a);return r.urlRewriteMode!=="absolute"&&(s=Ve(s,r,i)),s=qe(s,o.map(([,l])=>l)),Je(r,s,i)&&(s=Be(s)),s}async function Ye(t,r,e){let i=v.join(t.outputDir,e),s=v.extname(i).toLowerCase(),n;try{n=await $.readFile(i,"utf8");}catch(a){if(a.code!=="ENOENT")throw a;return {changed:false}}let l=Ze(n,t,r,s===".js"||s===".mjs"?void 0:i);return l!==n?(await $.writeFile(i,l,"utf8"),{changed:true}):{changed:false}}async function Xe(t,r){return await new Promise((e,i)=>{let s=a=>{if(l(),a?.error){i(new Error(a.error));return}e({changed:!!a?.changed});},n=a=>{l(),i(a);},o=a=>{l(),a!==0&&i(new Error(`Rewrite worker exited with code ${a}.`));},l=()=>{t.off("message",s),t.off("error",n),t.off("exit",o);};t.on("message",s),t.on("error",n),t.on("exit",o),t.postMessage({file:r});})}async function ye(t,r,e={}){let s=(e.files?[...new Set(e.files)].map(d=>v.resolve(d)).filter(d=>d.startsWith(v.resolve(t.outputDir))).map(d=>v.relative(t.outputDir,d).replace(/\\/g,"/")).filter(d=>d.length>0):await Ae(["**/*"],{cwd:t.outputDir,onlyFiles:true,dot:true})).filter(d=>d!=="asset-map.json"&&ge(d)),n=0;if(s.length===0)return 0;let o=Math.max(1,Number(t.rewriteConcurrency||t.assetDownloadConcurrency||1)),l=Math.max(1,Math.min(o,s.length,availableParallelism())),a=0,c=0,u=null;if(l===1){for(let d of s)(await Ye(t,r,d)).changed&&(n+=1),c+=1,await e.onProgress?.({index:c,totalFiles:s.length,changedTextFiles:n,file:d});return n}let g=Array.from({length:l},async()=>{let d=new Worker(new URL("./rewrite-worker.js",import.meta.url),{workerData:{config:t,assetMap:r}});try{for(;!u;){let p=a;if(p>=s.length)return;a+=1;let x=s[p];(await Xe(d,x)).changed&&(n+=1),c+=1,await e.onProgress?.({index:c,totalFiles:s.length,changedTextFiles:n,file:x});}}catch(p){throw u=p instanceof Error?p:new Error(String(p)),u}finally{await d.terminate().catch(()=>{});}});return await Promise.all(g),n}var $e="wpsuite-sha256",xe="wpsuite-normalized-sha256",at=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,ee=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function lt(t){return t&&(ee.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)?"__hex__":/^[0-9]{8,}$/.test(t)?"__num__":/^(?=.*[a-z])(?=.*\d)[a-z0-9]{8,}$/i.test(t)?"__alnum__":t)}function Z(t){return t.split(/([_:.\-/=?&#]+)/g).map((r,e)=>e%2===1?r:lt(r)).join("")}function ut(t){return t.split(/([_:.\-/=?&#]+)/g).map((r,e)=>e%2===1?r:ee.test(r)?"__uuid__":/^[0-9a-f]{6,}$/i.test(r)?"__hex__":/^[0-9]{6,}$/.test(r)?"__num__":/^[a-z0-9_-]{6,}$/i.test(r)?"__id__":r).join("")}function U(t,r){return Array.isArray(t)?t.map(e=>U(e,r)):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([e,i])=>[e,U(i,e)])):typeof t!="string"?t:r&&at.test(r)?ut(t):ee.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)||/^[0-9]{8,}$/.test(t)?Z(t):t}function ct(t){return t.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function gt(t,r){let e=r.trim();if((e.startsWith("{")||e.startsWith("[")||e.startsWith('"'))&&t.startsWith("data-"))try{let s=JSON.parse(e);return JSON.stringify(U(s))}catch{}if(t.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(e))try{let s=Buffer.from(e,"base64").toString("utf8"),n=JSON.parse(s),o=JSON.stringify(U(n));return Buffer.from(o,"utf8").toString("base64")}catch{}return r}function pt(t,r){let e=t.toLowerCase();return e==="class"?r.split(/(\s+)/).map((i,s)=>s%2===1?i:Z(i)).join(""):e==="id"||e==="for"||e==="aria-controls"||e==="aria-labelledby"||e==="aria-describedby"||e==="aria-owns"||e==="aria-activedescendant"||e==="name"?Z(r):e==="href"||e==="src"?ct(r):gt(e,r)}function dt(t){return t.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(r,e,i)=>{if(e.startsWith("/"))return r;let s=i.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(n,o,l,a)=>{let c=pt(o,a);return ` ${o}=${l}${c}${l}`});return `<${e}${s}>`})}function G(t){let r=v.extname(t).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(r)||["robots.txt","sitemap.xml"].includes(v.basename(t))}function be(t,r){return [t.replace(/^\/+|\/+$/g,""),r.replace(/^\/+/,"")].filter(Boolean).join("/")}async function ft(t,r,e,i){let s=new Map,n,o=0;do{o++;let l=await t.send(new ListObjectsV2Command({Bucket:r,Prefix:e||void 0,ContinuationToken:n}));for(let a of l.Contents||[]){if(!a.Key)continue;let c=(a.ETag||"").replace(/^"|"$/g,"").toLowerCase(),u=Number(a.Size??0);s.set(a.Key,{etag:c,size:u});}n=l.NextContinuationToken,i.debug(`Listed S3 keys page ${o}: ${s.size} keys so far`);}while(n);return s}async function mt(t,r,e,i,s){let n=Array.from(e).filter(o=>!i.has(o));if(n.length===0)return s.info("No stale S3 objects to delete."),[];s.info(`Deleting ${n.length} stale S3 object(s)\u2026`);for(let o=0;o<n.length;o+=1e3){let l=n.slice(o,o+1e3);if(l.length!==0){await t.send(new DeleteObjectsCommand({Bucket:r,Delete:{Objects:l.map(a=>({Key:a}))}})),s.info(`Deleted batch of ${l.length} object(s).`);for(let a of l)s.debug(` deleted: ${a}`);}}return n}function ht(t){return createHash("md5").update(t).digest("hex")}function Pe(t){return createHash("sha256").update(t).digest("hex")}function Y(t){return createHash("sha256").update(dt(t.toString("utf8"))).digest("hex")}async function wt(t,r,e,i){if(i.has(e))return i.get(e)??null;try{let o=((await t.send(new HeadObjectCommand({Bucket:r,Key:e}))).Metadata?.[$e]||"").trim().toLowerCase()||null;return i.set(e,o),o}catch{return i.set(e,null),null}}async function yt(t,r,e,i,s){if(i.has(e))return i.get(e)??null;try{let o=((await t.send(new HeadObjectCommand({Bucket:r,Key:e}))).Metadata?.[xe]||"").trim().toLowerCase();if(o)return i.set(e,o),o}catch{return i.set(e,null),null}if(s.has(e)){let n=s.get(e)??null;return i.set(e,n),n}try{let o=await(await t.send(new GetObjectCommand({Bucket:r,Key:e}))).Body?.transformToByteArray(),l=o?Y(Buffer.from(o)):null;return s.set(e,l),i.set(e,l),l}catch{return s.set(e,null),i.set(e,null),null}}function bt(t){return (t.split(`
|
|
7
|
-
`).find(e=>e.trim()!=="")??t).trim()}function Pt(t){return t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function vt(t,r){let e=t,i=Object.entries(r).sort((s,n)=>n[0].length-s[0].length);for(let[s,n]of i)s&&(e=e.split(s).join(n));return e}async function St(t,r,e,i){let s=v.join(t,"asset-map.json"),n;try{n=await $.readFile(s,"utf8");}catch(a){if(a.code==="ENOENT")return;throw a}let o=JSON.parse(n);if(!o||typeof o!="object")return;let l=Object.fromEntries(Object.entries(o).map(([a,c])=>{let u=String(c??"");return r.urlRewriteMode==="absolute"&&r.targetOrigin&&e.targetOrigin&&r.targetOrigin!==e.targetOrigin&&(u=u.split(r.targetOrigin).join(e.targetOrigin)),u=vt(u,i),[a,u]}));await $.writeFile(s,JSON.stringify(l,null,2),"utf8");}async function $t(t,r,e,i,s){let n=t.targetOrigin!==r.targetOrigin,o=Object.keys(i).length>0;if(!e||!n&&!o)return {outputDir:t.outputDir,cleanup:async()=>{}};if(n&&t.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${e}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let l=v.join(v.dirname(t.outputDir),`.deploy-profile-${Pt(e)}-${Date.now()}`);s.info(`Preparing deployment profile "${e}" from existing crawl output...`),await $.rm(l,{recursive:true,force:true}),await $.cp(t.outputDir,l,{recursive:true});let a={...t,sourceOrigin:t.targetOrigin,targetOrigin:r.targetOrigin,extraReplacements:i,outputDir:l},c=await ye(a,{});return await St(l,t,r,i),s.info(`Prepared deployment profile "${e}" in ${l} (${c} rewritten text file(s)).`),{outputDir:l,cleanup:async()=>{await $.rm(l,{recursive:true,force:true});}}}async function xt(t,r,e){await new Promise((i,s)=>{let n=`${t.outputDir.replace(/\/+$/,"")}/`,o=`s3://${t.s3.bucket}/${t.s3.prefix.replace(/^\/+|\/+$/g,"")}`.replace(/\/$/,""),l=["s3"];r==="aws-s3-cp-recursive"?l.push("cp",n,o,"--recursive","--region",t.s3.region):(l.push("sync",n,o,"--region",t.s3.region),r==="aws-s3-sync-delete"&&l.push("--delete")),e.info(`Running AWS CLI: aws ${l.join(" ")}`);let a=spawn("aws",l,{stdio:["ignore","pipe","pipe"]}),c=Date.now(),u=setInterval(()=>{let g=Math.floor((Date.now()-c)/1e3);e.progress(`AWS CLI is still running (${g}s elapsed) \u2014 syncing/copying in progress...`,{mode:r,elapsedSec:g}),e.info(`AWS CLI is still running (${g}s elapsed) \u2014 syncing/copying in progress...`);},15e3);a.stdout.setEncoding("utf8"),a.stderr.setEncoding("utf8"),a.stdout.on("data",g=>{g.split(/\r?\n/).map(d=>d.trim()).filter(d=>d.length>0).forEach(d=>e.info(d));}),a.stderr.on("data",g=>{g.split(/\r?\n/).map(d=>d.trim()).filter(d=>d.length>0).forEach(d=>e.warn(d));}),a.on("error",g=>{clearInterval(u),s(new Error(`Failed to start aws CLI: ${g.message}`));}),a.on("close",g=>{if(clearInterval(u),g===0){i();return}s(new Error(`aws CLI exited with code ${g??-1}`));});});}async function Dt(){let t=await Q(),r=ie(process.argv.slice(2)),e=se(t,r),i=v.resolve(e.config.logDir||"logs"),s=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",n=s?v.join(v.resolve(s),"deploy-diff.json"):"",o=new j(i,"deploy.log.jsonl",e.config.logLevel??"info"),l=e.profile?.extraReplacements??{},a=async()=>{};try{let c=await $t(t,e.config,e.name,l,o);a=c.cleanup;let u={...e.config,outputDir:c.outputDir},g=u.s3SyncMode??"sdk-upload-delete";e.name&&o.info(`Using deployment profile: ${e.name}`),o.info(`Starting deploy \u2014 s3://${u.s3.bucket}/${u.s3.prefix||""} (region: ${u.s3.region})`),o.info(`S3 sync mode: ${g}`),o.mark("deploy");try{let y=await new Promise((B,f)=>{let P=spawn("aws",["--version"],{stdio:["ignore","pipe","pipe"]}),T="",m="";P.stdout.setEncoding("utf8"),P.stderr.setEncoding("utf8"),P.stdout.on("data",h=>{T+=h;}),P.stderr.on("data",h=>{m+=h;}),P.on("error",h=>f(h)),P.on("close",h=>{h===0?B(bt(T||m)):f(new Error(`aws --version exited with ${h??-1}`));});});o.debug(`AWS CLI detected: ${y}`);}catch(y){o.warn(`AWS CLI version check failed: ${y.message}`);}if(g==="aws-s3-sync-delete"||g==="aws-s3-sync"||g==="aws-s3-cp-recursive"){await xt(u,g,o),n&&(await $.mkdir(v.dirname(n),{recursive:!0}),await $.writeFile(n,JSON.stringify({generatedAt:new Date().toISOString(),mode:g,summary:{strategy:"cli-mode",note:"Detailed object-level diff is not collected in AWS CLI modes.",...e.name?{profile:e.name}:{}},uploadedKeys:[],skippedKeys:[],failedKeys:[],deletedKeys:[]},null,2),"utf8")),o.endMark("deploy"),await o.flush();return}let d=new S3Client({region:u.s3.region}),p=await Ae(["**/*"],{cwd:u.outputDir,onlyFiles:!0,dot:!0}),x=new Set(p.map(y=>be(u.s3.prefix,y)));o.info(`Found ${p.length} file(s) in output directory "${u.outputDir}".`);let w=0,b=0,C=0,W=[],k=[],H=[],J=[],_=new Map,De=new Map,Ce=new Map,Re=new Map;(g==="sdk-upload-delete"||g==="sdk-upload-only")&&(o.info("Listing existing S3 objects to detect unchanged files..."),_=await ft(d,u.s3.bucket,u.s3.prefix,o),o.info(`Found ${_.size} existing key(s) in S3.`));for(let y of p){let B=v.join(u.outputDir,y),f=be(u.s3.prefix,y),P=ot.lookup(y)||"application/octet-stream",T=G(y)?u.s3.htmlCacheControl:u.s3.assetCacheControl,m=w+b+C+1;p.length<=200||m<=5||m%10===0||m===p.length?(o.progress(`Uploading [${m}/${p.length}] ${f} (${P})`,{file:y,key:f,index:m,totalFiles:p.length,contentType:P,mode:g}),o.info(`Uploading [${m}/${p.length}] ${f} (${P})`)):o.debug(`Uploading [${m}/${p.length}] ${f} (${P})`);try{let h=await $.readFile(B),I=_.get(f),F=null,L=null;if(I){let Le=h.byteLength;if(I.size===Le){let A=I.etag.includes("-");if(I.etag!==""&&!A){let Ee=ht(h);if(I.etag===Ee){b++,p.length<=200||b<=5||b%25===0?(o.progress(`Skipped unchanged [${m}/${p.length}] ${f}`,{file:y,key:f,index:m,totalFiles:p.length,uploaded:w,skipped:b,failed:C,mode:g,reason:"etag-md5-match"}),o.info(`Skipped unchanged [${m}/${p.length}] ${f}`)):o.debug(`Skipped unchanged [${m}/${p.length}] ${f}`),k.push(f);continue}}F=Pe(h);let te=await wt(d,u.s3.bucket,f,De);if(te&&te===F){b++,p.length<=200||b<=5||b%25===0?(o.progress(`Skipped unchanged [${m}/${p.length}] ${f}`,{file:y,key:f,index:m,totalFiles:p.length,uploaded:w,skipped:b,failed:C,mode:g,reason:"metadata-sha256-match"}),o.info(`Skipped unchanged [${m}/${p.length}] ${f}`)):o.debug(`Skipped unchanged [${m}/${p.length}] ${f}`),k.push(f);continue}}if(G(y)){L=Y(h);let A=await yt(d,u.s3.bucket,f,Ce,Re);if(A&&A===L){b++,p.length<=200||b<=5||b%25===0?(o.progress(`Skipped semantically unchanged [${m}/${p.length}] ${f}`,{file:y,key:f,index:m,totalFiles:p.length,uploaded:w,skipped:b,failed:C,mode:g,reason:"normalized-html-match"}),o.info(`Skipped semantically unchanged [${m}/${p.length}] ${f}`)):o.debug(`Skipped semantically unchanged [${m}/${p.length}] ${f}`),k.push(f);continue}}}F=F??Pe(h),L=L??(G(y)?Y(h):null),await new Upload({client:d,params:{Bucket:u.s3.bucket,Key:f,Body:h,ContentType:P,CacheControl:T,Metadata:{[$e]:F,...L?{[xe]:L}:{}}}}).done(),w++,W.push(f),(w%25===0||w===p.length)&&(o.progress(`Uploaded ${w}/${p.length} file(s)\u2026`,{uploaded:w,skipped:b,failed:C,totalFiles:p.length,mode:g}),o.info(`Uploaded ${w}/${p.length} file(s)\u2026`));}catch(h){C++,H.push(f),o.error(`Failed to upload ${f}: ${h.message}`,{key:f,error:String(h)});}}o.info(`Upload complete: ${w} uploaded, ${b} skipped unchanged, ${C} failed.`),(g==="sdk-upload-delete"||g==="sdk-upload-only")&&(g==="sdk-upload-delete"?J=await mt(d,u.s3.bucket,_.keys(),x,o):o.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion.")),n&&(await $.mkdir(v.dirname(n),{recursive:!0}),await $.writeFile(n,JSON.stringify({generatedAt:new Date().toISOString(),mode:g,summary:{totalFiles:p.length,uploaded:W.length,skipped:k.length,failed:H.length,deleted:J.length,...e.name?{profile:e.name}:{}},uploadedKeys:W,skippedKeys:k,failedKeys:H,deletedKeys:J},null,2),"utf8")),o.endMark("deploy"),await o.flush();}finally{await a().catch(()=>{});}}Dt().catch(async t=>{console.error(t);try{let e=(await Q().catch(()=>null))?.logDir??"logs",i=new j(e,"deploy.log.jsonl","debug");i.error(`Unhandled error: ${t instanceof Error?t.message:String(t)}`,t instanceof Error?{stack:t.stack}:void 0),await i.flush();}catch{}process.exit(1);});
|
|
6
|
+
`;return t.replace(/<head\b[^>]*>/i,s=>`${s}${n} ${r}`)}function gt(t){let r=xe(t).trim();return r.startsWith("{")||r.startsWith("[")||r.includes("\\/")||/"@context"|"@type"/.test(r)}function ct(t,r){let e=[...new Set(r)].filter(i=>i.includes("/")&&!/\\+\//.test(i)).map(i=>[i,J(i)]).filter(([i,o])=>i!==o).sort((i,o)=>o[0].length-i[0].length);if(!e.length)return t;let n=i=>{let o=i;for(let[u,a]of e)o=o.split(u).join(a);return o},s=t.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(i,o,u,a)=>`${o}${n(u)}${a}`);return s=s.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(i,o,u,a,l)=>gt(a)?`${o}${n(a)}${l}`:i),s}function pt(t,r){if(!r)return null;let e=S.dirname(S.resolve(r)),n=S.resolve(t.outputDir),s=S.relative(e,n).replace(/\\/g,"/");return s?(s.startsWith(".")||(s=`./${s}`),s.endsWith("/")?s:`${s}/`):"./"}function dt(t,r,e){let n=pt(r,e);if(!n)return t;let s=t;for(let i of st){let o=i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),u=new RegExp(`(?:\\.{1,}/)+${o}`,"g"),a=new RegExp(`(?<!\\.)/${o}`,"g");s=s.replace(u,`${n}${i}`).replace(a,`${n}${i}`);let l=i.replace(/\//g,"\\/"),g=n.replace(/\//g,"\\/"),m=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`(?:\\.{1,}\\\\/)+${m}`,"g"),w=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${m}`,"g"),P=new RegExp(`(?<![\\.\\\\])\\/${m}`,"g");s=s.replace(c,`${g}${l}`).replace(w,`${g}${l}`).replace(P,`${g}${l}`);}return s}function X(t,r,e){if(t.urlRewriteMode==="absolute")return r;let n=(()=>{try{return new URL(r,t.targetOrigin==="."?"https://relative.invalid":t.targetOrigin)}catch{return null}})(),s=n?n.pathname:De(r,t.targetOrigin),i=n?`${n.search}${n.hash}`:"";return t.urlRewriteMode==="root-relative"?`${s}${i}`:`${$e(t.outputDir,e,s)}${i}`}function Y(t,r,e,n,s){K(t,e,X(r,n,s));}function ft(t,r,e,n,s){if(!e||e===n)return;K(t,e,n);let i=X(r,e,s),o=X(r,n,s);K(t,i,o);}function mt(t,r,e,n,s={}){let i=t,o={};Y(o,r,r.sourceOrigin,r.targetOrigin,n);for(let[a,l]of Object.entries(r.extraReplacements))Y(o,r,a,l,n);for(let[a,l]of Object.entries(e))Y(o,r,a,l,n);for(let[a,l]of Object.entries(s)){let g=e[a];!g||g===l||ft(o,r,l,g,n);}let u=Object.entries(o).sort((a,l)=>l[0].length-a[0].length);for(let[a,l]of u)i=i.split(a).join(l);return r.urlRewriteMode!=="absolute"&&(i=dt(i,r,n)),i=ct(i,u.map(([,a])=>a)),lt(r,i,n)&&(i=ut(i)),i}async function ht(t,r,e,n){let s=S.join(t.outputDir,n),i=S.extname(s).toLowerCase(),o;try{o=await $.readFile(s,"utf8");}catch(l){if(l.code!=="ENOENT")throw l;return {changed:false}}let a=mt(o,t,r,i===".js"||i===".mjs"?void 0:s,e);return a!==o?(await $.writeFile(s,a,"utf8"),{changed:true}):{changed:false}}async function wt(t,r){return await new Promise((e,n)=>{let s=a=>{if(u(),a?.error){n(new Error(a.error));return}e({changed:!!a?.changed});},i=a=>{u(),n(a);},o=a=>{u(),a!==0&&n(new Error(`Rewrite worker exited with code ${a}.`));},u=()=>{t.off("message",s),t.off("error",i),t.off("exit",o);};t.on("message",s),t.on("error",i),t.on("exit",o),t.postMessage({file:r});})}async function Ee(t,r,e={}){let s=(e.files?[...new Set(e.files)].map(c=>S.resolve(c)).filter(c=>c.startsWith(S.resolve(t.outputDir))).map(c=>S.relative(t.outputDir,c).replace(/\\/g,"/")).filter(c=>c.length>0):await rt(["**/*"],{cwd:t.outputDir,onlyFiles:true,dot:true})).filter(c=>c!=="asset-map.json"&&Se(c)),i=0;if(s.length===0)return 0;let o=Math.max(1,Number(t.rewriteConcurrency||t.assetDownloadConcurrency||1)),u=Math.max(1,Math.min(o,s.length,availableParallelism())),a=0,l=0,g=null;if(u===1){for(let c of s){let w=await ht(t,r,e.previousAssetMap??{},c);w.changed&&(i+=1),l+=1,await e.onProgress?.({index:l,totalFiles:s.length,changedTextFiles:i,file:c,changed:w.changed});}return i}let m=Array.from({length:u},async()=>{let c=new Worker(new URL("./rewrite-worker.js",import.meta.url),{workerData:{config:t,assetMap:r,previousAssetMap:e.previousAssetMap??{}}});try{for(;!g;){let w=a;if(w>=s.length)return;a+=1;let P=s[w],b=await wt(c,P);b.changed&&(i+=1),l+=1,await e.onProgress?.({index:l,totalFiles:s.length,changedTextFiles:i,file:P,changed:b.changed});}}catch(w){throw g=w instanceof Error?w:new Error(String(w)),g}finally{await c.terminate().catch(()=>{});}});return await Promise.all(m),i}var Le="wpsuite-sha256",Fe="wpsuite-normalized-sha256",$t=/(?:^|[-_:.])(id|uid|nonce|token|hash|instance)(?:$|[-_:.])/i,oe=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function Rt(t){return t&&(oe.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)?"__hex__":/^[0-9]{8,}$/.test(t)?"__num__":/^(?=.*[a-z])(?=.*\d)[a-z0-9]{8,}$/i.test(t)?"__alnum__":t)}function re(t){return t.split(/([_:.\-/=?&#]+)/g).map((r,e)=>e%2===1?r:Rt(r)).join("")}function Ct(t){return t.split(/([_:.\-/=?&#]+)/g).map((r,e)=>e%2===1?r:oe.test(r)?"__uuid__":/^[0-9a-f]{6,}$/i.test(r)?"__hex__":/^[0-9]{6,}$/.test(r)?"__num__":/^[a-z0-9_-]{6,}$/i.test(r)?"__id__":r).join("")}function B(t,r){return Array.isArray(t)?t.map(e=>B(e,r)):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([e,n])=>[e,B(n,e)])):typeof t!="string"?t:r&&$t.test(r)?Ct(t):oe.test(t)?"__uuid__":/^[0-9a-f]{6,}$/i.test(t)||/^[0-9]{8,}$/.test(t)?re(t):t}function Et(t){return t.replace(/((?:https?:\/\/[^"'\s>]+|\/)(?:wp-content|wp-includes)\/[^"'\s>?]+)\?ver=[A-Za-z0-9._-]+(?=$|[#"'])/gi,"$1")}function Mt(t,r){let e=r.trim();if((e.startsWith("{")||e.startsWith("[")||e.startsWith('"'))&&t.startsWith("data-"))try{let s=JSON.parse(e);return JSON.stringify(B(s))}catch{}if(t.startsWith("data-")&&/^[A-Za-z0-9+/=]+$/.test(e))try{let s=Buffer.from(e,"base64").toString("utf8"),i=JSON.parse(s),o=JSON.stringify(B(i));return Buffer.from(o,"utf8").toString("base64")}catch{}return r}function Lt(t,r){let e=t.toLowerCase();return e==="class"?r.split(/(\s+)/).map((n,s)=>s%2===1?n:re(n)).join(""):e==="id"||e==="for"||e==="aria-controls"||e==="aria-labelledby"||e==="aria-describedby"||e==="aria-owns"||e==="aria-activedescendant"||e==="name"?re(r):e==="href"||e==="src"?Et(r):Mt(e,r)}function Ft(t){return t.replace(/<([a-z][^\s/>]*)([^<>]*?)>/gi,(r,e,n)=>{if(e.startsWith("/"))return r;let s=n.replace(/\s([:@a-zA-Z_][-:.a-zA-Z0-9_]*?)=(['"])([\s\S]*?)\2/g,(i,o,u,a)=>{let l=Lt(o,a);return ` ${o}=${u}${l}${u}`});return `<${e}${s}>`})}function ee(t){let r=S.extname(t).toLowerCase();return [".html",".htm",".xml",".xsl",".txt"].includes(r)||["robots.txt","sitemap.xml"].includes(S.basename(t))}function te(t,r){return [t.replace(/^\/+|\/+$/g,""),r.replace(/^\/+/,"")].filter(Boolean).join("/")}async function kt(t,r,e,n){let s=new Map,i,o=0;do{o++;let u=await t.send(new ListObjectsV2Command({Bucket:r,Prefix:e||void 0,ContinuationToken:i}));for(let a of u.Contents||[]){if(!a.Key)continue;let l=(a.ETag||"").replace(/^"|"$/g,"").toLowerCase(),g=Number(a.Size??0);s.set(a.Key,{etag:l,size:g});}i=u.NextContinuationToken,n.debug(`Listed S3 keys page ${o}: ${s.size} keys so far`);}while(i);return s}async function It(t,r,e,n){if(n.has(e))return n.get(e)??null;try{let s=await t.send(new HeadObjectCommand({Bucket:r,Key:e})),i={etag:(s.ETag||"").replace(/^"|"$/g,"").toLowerCase(),size:Number(s.ContentLength??0)};return n.set(e,i),i}catch{return n.set(e,null),null}}async function ke(t,r,e,n){let s=[...new Set(Array.from(e).filter(Boolean))];if(s.length===0)return n.info("No stale S3 objects to delete."),[];n.info(`Deleting ${s.length} stale S3 object(s)\u2026`);for(let i=0;i<s.length;i+=1e3){let o=s.slice(i,i+1e3);if(o.length!==0){await t.send(new DeleteObjectsCommand({Bucket:r,Delete:{Objects:o.map(u=>({Key:u}))}})),n.info(`Deleted batch of ${o.length} object(s).`);for(let u of o)n.debug(` deleted: ${u}`);}}return s}async function jt(t,r,e,n,s){return ke(t,r,Array.from(e).filter(i=>!n.has(i)),s)}function Ot(t){return createHash("md5").update(t).digest("hex")}function Me(t){return createHash("sha256").update(t).digest("hex")}function ne(t){return createHash("sha256").update(Ft(t.toString("utf8"))).digest("hex")}async function Tt(t,r,e,n){if(n.has(e))return n.get(e)??null;try{let o=((await t.send(new HeadObjectCommand({Bucket:r,Key:e}))).Metadata?.[Le]||"").trim().toLowerCase()||null;return n.set(e,o),o}catch{return n.set(e,null),null}}async function _t(t,r,e,n,s){if(n.has(e))return n.get(e)??null;try{let o=((await t.send(new HeadObjectCommand({Bucket:r,Key:e}))).Metadata?.[Fe]||"").trim().toLowerCase();if(o)return n.set(e,o),o}catch{return n.set(e,null),null}if(s.has(e)){let i=s.get(e)??null;return n.set(e,i),i}try{let o=await(await t.send(new GetObjectCommand({Bucket:r,Key:e}))).Body?.transformToByteArray(),u=o?ne(Buffer.from(o)):null;return s.set(e,u),n.set(e,u),u}catch{return s.set(e,null),n.set(e,null),null}}function At(t){return t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"profile"}function Nt(t,r){let e=t,n=Object.entries(r).sort((s,i)=>i[0].length-s[0].length);for(let[s,i]of n)s&&(e=e.split(s).join(i));return e}async function Ut(t,r,e,n){let s=S.join(t,"asset-map.json"),i;try{i=await $.readFile(s,"utf8");}catch(a){if(a.code==="ENOENT")return;throw a}let o=JSON.parse(i);if(!o||typeof o!="object")return;let u=Object.fromEntries(Object.entries(o).map(([a,l])=>{let g=String(l??"");return r.urlRewriteMode==="absolute"&&r.targetOrigin&&e.targetOrigin&&r.targetOrigin!==e.targetOrigin&&(g=g.split(r.targetOrigin).join(e.targetOrigin)),g=Nt(g,n),[a,g]}));await $.writeFile(s,JSON.stringify(u,null,2),"utf8");}async function zt(t,r,e,n,s){let i=t.targetOrigin!==r.targetOrigin,o=Object.keys(n).length>0;if(!e||!i&&!o)return {outputDir:t.outputDir,cleanup:async()=>{}};if(i&&t.urlRewriteMode!=="absolute")throw new Error(`Deployment profile "${e}" changes targetOrigin, but the base crawl output must use urlRewriteMode "absolute" for multi-target redeploys.`);let u=S.join(S.dirname(t.outputDir),`.deploy-profile-${At(e)}-${Date.now()}`);s.info(`Preparing deployment profile "${e}" from existing crawl output...`),await $.rm(u,{recursive:true,force:true}),await $.cp(t.outputDir,u,{recursive:true});let a={...t,sourceOrigin:t.targetOrigin,targetOrigin:r.targetOrigin,extraReplacements:n,outputDir:u},l=await Ee(a,{});return await Ut(u,t,r,n),s.info(`Prepared deployment profile "${e}" in ${u} (${l} rewritten text file(s)).`),{outputDir:u,cleanup:async()=>{await $.rm(u,{recursive:true,force:true});}}}async function Ht(){let t=await G(),r=me(process.argv.slice(2)),e=he(t,r),n=S.resolve(e.config.logDir||"logs"),s=process.env.STATIC_PUBLISHER_RUNTIME_DIR||process.env.WPSUITE_STATIC_PUBLISHER_RUNTIME_DIR||"",i=s?S.join(S.resolve(s),"deploy-diff.json"):"",o=new A(n,"deploy.log.jsonl",e.config.logLevel??"info"),u=e.profile?.extraReplacements??{},a=async()=>{};try{let l=await zt(t,e.config,e.name,u,o);a=l.cleanup;let g={...e.config,outputDir:l.outputDir},m=g.s3SyncMode??"sdk-upload-delete",c=await de(t),w=l.outputDir!==t.outputDir&&(t.targetOrigin!==e.config.targetOrigin||Object.keys(u).length>0),P=!!c&&!c.fullSyncRequired&&!w;e.name&&o.info(`Using deployment profile: ${e.name}`),o.info(`Starting deploy \u2014 s3://${g.s3.bucket}/${g.s3.prefix||""} (region: ${g.s3.region})`),o.info(`S3 sync mode: ${m}`),c&&c.fullSyncRequired?o.info("Deploy plan requests a full sync; scanning the whole output tree."):c&&w?o.info("Ignoring incremental deploy plan because deployment-profile rewrites require a full sync."):P&&o.info(`Using incremental deploy plan: ${c.changedFiles.length} changed file(s), ${c.deletedFiles.length} deleted file(s).`),o.mark("deploy");let b=new S3Client({region:g.s3.region}),p=P?(await Promise.all(c.changedFiles.map(async f=>{try{return (await $.stat(S.join(g.outputDir,f))).isFile()?f:null}catch{return null}}))).filter(f=>f!==null):await rt(["**/*"],{cwd:g.outputDir,onlyFiles:!0,dot:!0}),Ie=P?new Set:new Set(p.map(f=>te(g.s3.prefix,f)));P?o.info(`Using ${p.length} planned changed file(s) from deploy plan for upload.`):o.info(`Found ${p.length} file(s) in output directory "${g.outputDir}".`);let v=0,y=0,C=0,W=[],k=[],q=[],U=[],I=new Map,je=new Map,Oe=new Map,Te=new Map,_e=new Map;P||(o.info("Listing existing S3 objects to detect unchanged files..."),I=await kt(b,g.s3.bucket,g.s3.prefix,o),o.info(`Found ${I.size} existing key(s) in S3.`));let Ae=async f=>I.has(f)?I.get(f)??null:P?It(b,g.s3.bucket,f,je):null;for(let f of p){let ae=S.join(g.outputDir,f),d=te(g.s3.prefix,f),j=Dt.lookup(f)||"application/octet-stream",Ne=ee(f)?g.s3.htmlCacheControl:g.s3.assetCacheControl,h=v+y+C+1;p.length<=200||h<=5||h%10===0||h===p.length?(o.progress(`Uploading [${h}/${p.length}] ${d} (${j})`,{file:f,key:d,index:h,totalFiles:p.length,contentType:j,mode:m}),o.info(`Uploading [${h}/${p.length}] ${d} (${j})`)):o.debug(`Uploading [${h}/${p.length}] ${d} (${j})`);try{let x=await $.readFile(ae),O=await Ae(d),T=null,L=null;if(O){let Ue=x.byteLength;if(O.size===Ue){let z=O.etag.includes("-");if(O.etag!==""&&!z){let ze=Ot(x);if(O.etag===ze){y++,p.length<=200||y<=5||y%25===0?(o.progress(`Skipped unchanged [${h}/${p.length}] ${d}`,{file:f,key:d,index:h,totalFiles:p.length,uploaded:v,skipped:y,failed:C,mode:m,reason:"etag-md5-match"}),o.info(`Skipped unchanged [${h}/${p.length}] ${d}`)):o.debug(`Skipped unchanged [${h}/${p.length}] ${d}`),k.push(d);continue}}T=Me(x);let le=await Tt(b,g.s3.bucket,d,Oe);if(le&&le===T){y++,p.length<=200||y<=5||y%25===0?(o.progress(`Skipped unchanged [${h}/${p.length}] ${d}`,{file:f,key:d,index:h,totalFiles:p.length,uploaded:v,skipped:y,failed:C,mode:m,reason:"metadata-sha256-match"}),o.info(`Skipped unchanged [${h}/${p.length}] ${d}`)):o.debug(`Skipped unchanged [${h}/${p.length}] ${d}`),k.push(d);continue}}if(ee(f)){L=ne(x);let z=await _t(b,g.s3.bucket,d,Te,_e);if(z&&z===L){y++,p.length<=200||y<=5||y%25===0?(o.progress(`Skipped semantically unchanged [${h}/${p.length}] ${d}`,{file:f,key:d,index:h,totalFiles:p.length,uploaded:v,skipped:y,failed:C,mode:m,reason:"normalized-html-match"}),o.info(`Skipped semantically unchanged [${h}/${p.length}] ${d}`)):o.debug(`Skipped semantically unchanged [${h}/${p.length}] ${d}`),k.push(d);continue}}}T=T??Me(x),L=L??(ee(f)?ne(x):null),await new Upload({client:b,params:{Bucket:g.s3.bucket,Key:d,Body:x,ContentType:j,CacheControl:Ne,Metadata:{[Le]:T,...L?{[Fe]:L}:{}}}}).done(),v++,W.push(d),(v%25===0||v===p.length)&&(o.progress(`Uploaded ${v}/${p.length} file(s)\u2026`,{uploaded:v,skipped:y,failed:C,totalFiles:p.length,mode:m}),o.info(`Uploaded ${v}/${p.length} file(s)\u2026`));}catch(x){C++,q.push(d),o.error(`Failed to upload ${d}: ${x.message}`,{key:d,error:String(x)});}}o.info(`Upload complete: ${v} uploaded, ${y} skipped unchanged, ${C} failed.`),m==="sdk-upload-delete"?P?U=await ke(b,g.s3.bucket,c.deletedFiles.map(f=>te(g.s3.prefix,f)),o):U=await jt(b,g.s3.bucket,I.keys(),Ie,o):o.info("Sync mode is sdk-upload-only \u2014 skipping stale object deletion."),i&&(await $.mkdir(S.dirname(i),{recursive:!0}),await $.writeFile(i,JSON.stringify({generatedAt:new Date().toISOString(),mode:m,summary:{totalFiles:p.length,uploaded:W.length,skipped:k.length,failed:q.length,deleted:U.length,...e.name?{profile:e.name}:{}},uploadedKeys:W,skippedKeys:k,failedKeys:q,deletedKeys:U},null,2),"utf8")),await fe(t),o.endMark("deploy"),await o.flush();}finally{await a().catch(()=>{});}}Ht().catch(async t=>{console.error(t);try{let e=(await G().catch(()=>null))?.logDir??"logs",n=new A(e,"deploy.log.jsonl","debug");n.error(`Unhandled error: ${t instanceof Error?t.message:String(t)}`,t instanceof Error?{stack:t.stack}:void 0),await n.flush();}catch{}process.exit(1);});
|
package/dist/rewrite-worker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import S from'fs/promises';import f from'path';import {workerData,parentPort}from'worker_threads';import'fast-glob';import'os';import'crypto';function P(t){return t.replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function g(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function h(t){return t.replace(/\//g,"\\/")}function $(t){return t.replace(/\//g,"\\\\/")}function m(t,e,i){if(!e)return;t[e]=i;let n=h(e),s=h(i);t[n]=s;let r=$(e),o=$(i);t[r]=o;let c=g(e),a=g(i);t[c]=a;let l=g(n),u=g(s);t[l]=u;let p=g(r),x=g(o);t[p]=x;}function E(t,e){try{return new URL(t,e==="."?"https://relative.invalid":e).pathname}catch{return t.startsWith("/")?t:`/${t.replace(/^\.\//,"")}`}}function y(t,e,i){if(!e)return i;let n=f.dirname(f.resolve(e)),s=f.resolve(t,i.replace(/^\/+/,"")),r=f.relative(n,s).replace(/\\/g,"/");return r?(r.startsWith(".")||(r=`./${r}`),r):"."}var j=["wp-content/","wp-includes/","wp-admin/","wp-json/","_next/"],D=new Set([".html",".htm"]),M="WPSuite.io Static Publisher",A=M.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function k(t,e,i){if(t.wpsuite?.subscriber===true||!i)return false;let n=f.extname(i).toLowerCase();return D.has(n)?/<head\b|<html\b|<!doctype html/i.test(e):false}function H(t){if(new RegExp(`<meta\\b(?=[^>]*\\bname=(["'])generator\\1)(?=[^>]*\\bcontent=(["'])${A}\\2)[^>]*\\/?>`,"i").test(t))return t;let e=`<meta name="generator" content="${M}" />`;if(t.match(/(\r?\n)([ \t]*)<\/head>/i))return t.replace(/(\r?\n)([ \t]*)<\/head>/i,`$1$2${e}$1$2</head>`);let n=t.includes(`\r
|
|
2
2
|
`)?`\r
|
|
3
3
|
`:`
|
|
4
|
-
`;return
|
|
4
|
+
`;return t.replace(/<head\b[^>]*>/i,s=>`${s}${n} ${e}`)}function O(t){let e=P(t).trim();return e.startsWith("{")||e.startsWith("[")||e.includes("\\/")||/"@context"|"@type"/.test(e)}function L(t,e){let i=[...new Set(e)].filter(r=>r.includes("/")&&!/\\+\//.test(r)).map(r=>[r,h(r)]).filter(([r,o])=>r!==o).sort((r,o)=>o[0].length-r[0].length);if(!i.length)return t;let n=r=>{let o=r;for(let[c,a]of i)o=o.split(c).join(a);return o},s=t.replace(/(<script\b[^>]*\btype=["']application\/(?:ld\+)?json["'][^>]*>)([\s\S]*?)(<\/script>)/gi,(r,o,c,a)=>`${o}${n(c)}${a}`);return s=s.replace(/(<meta\b[^>]*\bcontent=(['"]))([\s\S]*?)(\2[^>]*>)/gi,(r,o,c,a,l)=>O(a)?`${o}${n(a)}${l}`:r),s}function U(t,e){if(!e)return null;let i=f.dirname(f.resolve(e)),n=f.resolve(t.outputDir),s=f.relative(i,n).replace(/\\/g,"/");return s?(s.startsWith(".")||(s=`./${s}`),s.endsWith("/")?s:`${s}/`):"./"}function N(t,e,i){let n=U(e,i);if(!n)return t;let s=t;for(let r of j){let o=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`(?:\\.{1,}/)+${o}`,"g"),a=new RegExp(`(?<!\\.)/${o}`,"g");s=s.replace(c,`${n}${r}`).replace(a,`${n}${r}`);let l=r.replace(/\//g,"\\/"),u=n.replace(/\//g,"\\/"),p=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),x=new RegExp(`(?:\\.{1,}\\\\/)+${p}`,"g"),T=new RegExp(`(?:\\.{1,}(?:\\\\/|\\\\))+${p}`,"g"),W=new RegExp(`(?<![\\.\\\\])\\/${p}`,"g");s=s.replace(x,`${u}${l}`).replace(T,`${u}${l}`).replace(W,`${u}${l}`);}return s}function R(t,e,i){if(t.urlRewriteMode==="absolute")return e;let n=(()=>{try{return new URL(e,t.targetOrigin==="."?"https://relative.invalid":t.targetOrigin)}catch{return null}})(),s=n?n.pathname:E(e,t.targetOrigin),r=n?`${n.search}${n.hash}`:"";return t.urlRewriteMode==="root-relative"?`${s}${r}`:`${y(t.outputDir,i,s)}${r}`}function b(t,e,i,n,s){m(t,i,R(e,n,s));}function q(t,e,i,n,s){if(!i||i===n)return;m(t,i,n);let r=R(e,i,s),o=R(e,n,s);m(t,r,o);}function v(t,e,i,n,s={}){let r=t,o={};b(o,e,e.sourceOrigin,e.targetOrigin,n);for(let[a,l]of Object.entries(e.extraReplacements))b(o,e,a,l,n);for(let[a,l]of Object.entries(i))b(o,e,a,l,n);for(let[a,l]of Object.entries(s)){let u=i[a];!u||u===l||q(o,e,l,u,n);}let c=Object.entries(o).sort((a,l)=>l[0].length-a[0].length);for(let[a,l]of c)r=r.split(a).join(l);return e.urlRewriteMode!=="absolute"&&(r=N(r,e,n)),r=L(r,c.map(([,a])=>a)),k(e,r,n)&&(r=H(r)),r}var{config:F,assetMap:J,previousAssetMap:V}=workerData;async function G(t){let e=f.join(F.outputDir,t),i=f.extname(e).toLowerCase(),n;try{n=await S.readFile(e,"utf8");}catch(o){if(o.code==="ENOENT")return false;throw o}let r=v(n,F,J,i===".js"||i===".mjs"?void 0:e,V);return r===n?false:(await S.writeFile(e,r,"utf8"),true)}if(!parentPort)throw new Error("rewrite worker requires a parent port");parentPort.on("message",async t=>{try{let e=await G(t.file);parentPort?.postMessage({changed:e});}catch(e){parentPort?.postMessage({changed:false,error:e instanceof Error?e.message:String(e)});}});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smart-cloud/publisher-exporter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Headless Playwright static publisher for WordPress/Elementor sites with sitemap-only page discovery, strict asset capture, escaped URL rewrite, structured logs, and targeted retry modes.",
|