const ORIGIN_HOSTNAME = "proxy.thechurchinternational.online";
export default {
async fetch(request) {
const response = await fetchFromOrigin(request);
if (!(response.headers.get("content-type") || "").includes("text/html")) return response;
let found = false;
return new HTMLRewriter()
.on("h1", {
element(el) {
if (!found) {
found = true;
el.setInnerContent("This Is A Test");
}
},
})
.transform(response);
},
};
async function fetchFromOrigin(request) {
const url = new URL(request.url);
url.hostname = ORIGIN_HOSTNAME;
const headers = new Headers(request.headers);
headers.delete("accept-encoding");
headers.set("host", ORIGIN_HOSTNAME);
return fetch(url, { method: request.method, headers, body: request.body, redirect: "follow" });
}
Give collection wrapper an attribute of data-cms-render-all=”true”
Enable pagination and Show page count
const ORIGIN_HOSTNAME = "proxy.thechurchinternational.online";
export default {
async fetch(request) {
const response = await fetchFromOrigin(request);
if (!(response.headers.get("content-type") || "").includes("text/html")) return response;
const html = await response.text();
const responseInit = { status: response.status, statusText: response.statusText, headers: response.headers };
if (!html.includes('data-cms-render-all="true"')) return new Response(html, responseInit);
return renderCmsCollections(html, request, responseInit);
},
};
async function fetchFromOrigin(request) {
const url = new URL(request.url); url.hostname = ORIGIN_HOSTNAME;
const headers = new Headers(request.headers); headers.delete("accept-encoding"); headers.set("host", ORIGIN_HOSTNAME);
return fetch(new Request(url.toString(), { method: request.method, headers, body: request.body, redirect: "follow" }));
}
async function renderCmsCollections(html, request, responseInit) {
const collections = await discoverCollections(html);
if (!collections.length) return new Response(html, responseInit);
const extra = await fetchAllPaginatedItems(new URL(request.url), collections);
let result = html;
for (const { pageParam } of collections) if (extra[pageParam]) result = injectItems(result, pageParam, extra[pageParam]);
return new Response(result, responseInit);
}
function injectItems(html, pageParam, extraItems) {
const paramIdx = html.indexOf(pageParam + "="); if (paramIdx === -1) return html;
const wrapperOpenIdx = html.substring(0, paramIdx).lastIndexOf("w-pagination-wrapper"); if (wrapperOpenIdx === -1) return html;
const wrapperDivIdx = html.lastIndexOf("<div", wrapperOpenIdx); if (wrapperDivIdx === -1) return html;
const wrapperEnd = findClosingDiv(html, wrapperDivIdx); if (wrapperEnd === -1) return html;
const dynItemsCloseIdx = html.substring(0, wrapperDivIdx).lastIndexOf("</div>"); if (dynItemsCloseIdx === -1) return html;
return html.substring(0, dynItemsCloseIdx) + extraItems + html.substring(dynItemsCloseIdx, wrapperDivIdx) + html.substring(wrapperEnd);
}
function findClosingDiv(html, openIdx) {
let depth = 0, i = openIdx;
while (i < html.length) {
const nextOpen = html.indexOf("<div", i + 1), nextClose = html.indexOf("</div>", i + 1);
if (nextClose === -1) return -1;
if (nextOpen !== -1 && nextOpen < nextClose) { depth++; i = nextOpen; }
else if (depth === 0) return nextClose + 6;
else { depth--; i = nextClose; }
}
return -1;
}
async function discoverCollections(html) {
const collections = []; let textBuffer = "", inside = false;
await new HTMLRewriter()
.on('[data-cms-render-all="true"].w-dyn-list', { element() { inside = true; } })
.on('[data-cms-render-all="true"].w-dyn-list .w-pagination-wrapper', { element() { if (inside) collections.push({ pageParam: null, totalPages: null }); } })
.on('[data-cms-render-all="true"].w-dyn-list .w-pagination-next', { element(el) {
if (!inside) return; const param = extractPageParam(el.getAttribute("href"));
if (param && collections.length) collections.at(-1).pageParam = param;
} })
.on('[data-cms-render-all="true"].w-dyn-list .w-page-count', { element() { if (inside) textBuffer = ""; }, text(chunk) {
if (!inside) return; textBuffer += chunk.text;
if (chunk.lastInTextNode) { const match = textBuffer.match(/\\d+\\s*\\/\\s*(\\d+)/); if (match && collections.length) collections.at(-1).totalPages = parseInt(match[1], 10); textBuffer = ""; }
} })
.transform(new Response(html)).text();
return collections.filter((c) => c.pageParam && c.totalPages > 1);
}
async function fetchAllPaginatedItems(baseUrl, collections) {
const headers = new Headers(); headers.set("host", ORIGIN_HOSTNAME); headers.set("accept", "text/html");
const jobs = collections.flatMap(({ pageParam, totalPages }) => Array.from({ length: totalPages - 1 }, (_, i) => {
const u = new URL(baseUrl); u.hostname = ORIGIN_HOSTNAME; u.searchParams.set(pageParam, i + 2); return { pageParam, url: u.toString() };
}));
const results = await Promise.all(jobs.map(async ({ pageParam, url }) => ({ pageParam, html: await (await fetch(url, { headers, redirect: "follow" })).text() })));
const itemsByParam = {};
for (const { pageParam, html } of results) itemsByParam[pageParam] = (itemsByParam[pageParam] || "") + extractListItems(html, pageParam);
return itemsByParam;
}
function extractPageParam(href) { const m = (href || "").match(/[?&]([^=]+)=\\d+/); return m ? m[1] : null; }
function extractListItems(html, pageParam) {
const paramIdx = html.indexOf(pageParam + "="); if (paramIdx === -1) return "";
const dynIdx = html.substring(0, paramIdx).lastIndexOf("w-dyn-items"); if (dynIdx === -1) return "";
const tagEnd = html.indexOf(">", dynIdx); if (tagEnd === -1) return "";
const wrapperClassIdx = html.indexOf("w-pagination-wrapper", tagEnd); if (wrapperClassIdx === -1) return "";
const wrapperDivIdx = html.lastIndexOf("<div", wrapperClassIdx); if (wrapperDivIdx === -1) return "";
const slice = html.substring(tagEnd + 1, wrapperDivIdx);
const lastClose = slice.lastIndexOf("</div>");
return lastClose === -1 ? slice.trim() : slice.substring(0, lastClose).trim();
}
Give each style or script tag on the page an attribute of data-code-move
const ORIGIN_HOSTNAME = "proxy.thechurchinternational.online";
export default {
async fetch(request) {
const response = await fetchFromOrigin(request);
if (!(response.headers.get("content-type") || "").includes("text/html")) return response;
let html = await response.text();
const seenStyles = new Set();
const seenScripts = new Set();
const stylesToInject = [];
const scriptsToInject = [];
// Extract style[data-code-move]
html = html.replace(/<style[^>]*data-code-move[^>]*>([\\s\\S]*?)<\\/style>/gi, (_, content) => {
const trimmed = content.trim();
if (trimmed && !seenStyles.has(trimmed)) {
seenStyles.add(trimmed);
stylesToInject.push(trimmed);
}
return '';
});
// Extract script[data-code-move]
html = html.replace(/<script[^>]*data-code-move[^>]*>([\\s\\S]*?)<\\/script>/gi, (_, content) => {
const trimmed = content.trim();
if (trimmed && !seenScripts.has(trimmed)) {
seenScripts.add(trimmed);
scriptsToInject.push(trimmed);
}
return '';
});
// Inject styles before </head>
if (stylesToInject.length) {
const styleHtml = stylesToInject.map(s => `<style>${s}</style>`).join('\\n');
html = html.replace('</head>', `${styleHtml}\\n</head>`);
}
// Inject scripts before </body>
if (scriptsToInject.length) {
const scriptHtml = scriptsToInject.map(s => `<script>${s}</script>`).join('\\n');
html = html.replace('</body>', `${scriptHtml}\\n</body>`);
}
return new Response(html, {
status: response.status,
headers: response.headers,
});
},
};
async function fetchFromOrigin(request) {
const url = new URL(request.url);
url.hostname = ORIGIN_HOSTNAME;
const headers = new Headers(request.headers);
headers.delete("accept-encoding");
headers.set("host", ORIGIN_HOSTNAME);
return fetch(url, { method: request.method, headers, body: request.body, redirect: "follow" });
}