mnfst-render 0.2.6 → 0.2.7
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/manifest.render.mjs +90 -0
- package/package.json +1 -1
package/manifest.render.mjs
CHANGED
|
@@ -39,6 +39,7 @@ function parseArgs() {
|
|
|
39
39
|
if (args[i] === '--wait-after-idle' && args[i + 1]) { out.waitAfterIdle = parseInt(args[++i], 10); continue; }
|
|
40
40
|
if (args[i] === '--concurrency' && args[i + 1]) { out.concurrency = parseInt(args[++i], 10); continue; }
|
|
41
41
|
if (args[i] === '--dry-run') { out.dryRun = true; continue; }
|
|
42
|
+
if (args[i] === '--debug-prerender') { out.debugPrerender = true; continue; }
|
|
42
43
|
}
|
|
43
44
|
return out;
|
|
44
45
|
}
|
|
@@ -86,6 +87,7 @@ function resolveConfig() {
|
|
|
86
87
|
waitAfterIdle: Math.max(0, cli.waitAfterIdle ?? pre.waitAfterIdle ?? 0),
|
|
87
88
|
concurrency: Math.max(1, cli.concurrency ?? pre.concurrency ?? 6),
|
|
88
89
|
dryRun: !!cli.dryRun,
|
|
90
|
+
debugPrerender: !!(cli.debugPrerender ?? pre.debugPrerender),
|
|
89
91
|
};
|
|
90
92
|
}
|
|
91
93
|
|
|
@@ -729,6 +731,29 @@ function stripPrerenderDynamicBindings(html) {
|
|
|
729
731
|
});
|
|
730
732
|
}
|
|
731
733
|
|
|
734
|
+
// Remove empty inline mask-image styles emitted before data resolves
|
|
735
|
+
// (e.g. style="mask-image: url()"), while keeping any :style/x-bind:style bindings.
|
|
736
|
+
function stripEmptyInlineMaskStyles(html) {
|
|
737
|
+
return html.replace(/<(\w+)([^>]*)>/g, (full, tag, attrs) => {
|
|
738
|
+
const styleMatch = attrs.match(/\sstyle=(["'])([\s\S]*?)\1/i);
|
|
739
|
+
if (!styleMatch) return full;
|
|
740
|
+
const quote = styleMatch[1];
|
|
741
|
+
const rawStyle = styleMatch[2] || '';
|
|
742
|
+
const cleaned = rawStyle
|
|
743
|
+
.replace(/\bmask-image\s*:\s*url\(\s*(?:''|""|)\s*\)\s*;?/gi, '')
|
|
744
|
+
.replace(/\b-webkit-mask-image\s*:\s*url\(\s*(?:''|""|)\s*\)\s*;?/gi, '')
|
|
745
|
+
.trim()
|
|
746
|
+
.replace(/^\s*;\s*|\s*;\s*$/g, '');
|
|
747
|
+
|
|
748
|
+
if (!cleaned) {
|
|
749
|
+
const newAttrs = attrs.replace(/\sstyle=(["'])[\s\S]*?\1/i, '');
|
|
750
|
+
return `<${tag}${newAttrs}>`;
|
|
751
|
+
}
|
|
752
|
+
const rebuilt = attrs.replace(/\sstyle=(["'])[\s\S]*?\1/i, ` style=${quote}${cleaned}${quote}`);
|
|
753
|
+
return `<${tag}${rebuilt}>`;
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
|
|
732
757
|
// --- Rewrite asset URLs: depth = segments from this HTML file up to output root (website). ----
|
|
733
758
|
// All project assets are copied into output, so root-relative paths become relative within output.
|
|
734
759
|
// Do NOT rewrite href on <a> tags (navigation links); only rewrite link/script/img so router gets clean paths.
|
|
@@ -1222,8 +1247,14 @@ async function runPrerender(config) {
|
|
|
1222
1247
|
const concurrency = config.concurrency;
|
|
1223
1248
|
const pathTotal = pathList.length;
|
|
1224
1249
|
const failedPaths = [];
|
|
1250
|
+
const debugRows = [];
|
|
1225
1251
|
process.stdout.write(`Prerendering ${pathTotal} path(s)...\n`);
|
|
1226
1252
|
|
|
1253
|
+
function pushDebug(row) {
|
|
1254
|
+
if (!config.debugPrerender) return;
|
|
1255
|
+
debugRows.push(row);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1227
1258
|
async function processPath(pathSeg, pathIndex) {
|
|
1228
1259
|
const is404 = pathSeg === NOT_FOUND_PATH;
|
|
1229
1260
|
const pathname = is404 ? `/${NOT_FOUND_PATH}` : (pathSeg ? `/${pathSeg}` : '/');
|
|
@@ -1242,6 +1273,7 @@ async function runPrerender(config) {
|
|
|
1242
1273
|
|
|
1243
1274
|
const page = await browser.newPage();
|
|
1244
1275
|
try {
|
|
1276
|
+
pushDebug({ path: displayPath, stage: 'start' });
|
|
1245
1277
|
await page.goto(url, {
|
|
1246
1278
|
waitUntil: 'domcontentloaded',
|
|
1247
1279
|
timeout: Math.min(timeout, 30000),
|
|
@@ -1281,6 +1313,36 @@ async function runPrerender(config) {
|
|
|
1281
1313
|
});
|
|
1282
1314
|
}).catch(() => { });
|
|
1283
1315
|
|
|
1316
|
+
if (config.debugPrerender) {
|
|
1317
|
+
const before = await page.evaluate(() => {
|
|
1318
|
+
const templates = Array.from(document.querySelectorAll('template[x-for]'));
|
|
1319
|
+
const entries = templates.slice(0, 60).map((tpl) => {
|
|
1320
|
+
const first = tpl.content?.firstElementChild;
|
|
1321
|
+
const tag = first ? first.tagName : null;
|
|
1322
|
+
const cls = first ? (first.getAttribute('class') || '') : '';
|
|
1323
|
+
let cloneCount = 0;
|
|
1324
|
+
let next = tpl.nextElementSibling;
|
|
1325
|
+
while (next && (!tag || next.tagName === tag)) {
|
|
1326
|
+
if (tag && (next.getAttribute('class') || '') !== cls) break;
|
|
1327
|
+
cloneCount++;
|
|
1328
|
+
next = next.nextElementSibling;
|
|
1329
|
+
}
|
|
1330
|
+
return {
|
|
1331
|
+
xFor: (tpl.getAttribute('x-for') || '').slice(0, 140),
|
|
1332
|
+
collapsed: tpl.getAttribute('data-prerender-collapsed') === '1',
|
|
1333
|
+
staticGenerated: tpl.getAttribute('data-prerender-static-generated') === '1',
|
|
1334
|
+
cloneCount,
|
|
1335
|
+
};
|
|
1336
|
+
});
|
|
1337
|
+
return {
|
|
1338
|
+
templateCount: templates.length,
|
|
1339
|
+
nonCollapsedTemplateCount: templates.filter((t) => t.getAttribute('data-prerender-collapsed') !== '1').length,
|
|
1340
|
+
entries,
|
|
1341
|
+
};
|
|
1342
|
+
}).catch(() => null);
|
|
1343
|
+
pushDebug({ path: displayPath, stage: 'post-dom-settle', metrics: before });
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1284
1346
|
await page.waitForNetworkIdle({ idleTime: 1500, timeout: 10000 }).catch(() => { });
|
|
1285
1347
|
|
|
1286
1348
|
await page.evaluate(() => {
|
|
@@ -1568,6 +1630,15 @@ async function runPrerender(config) {
|
|
|
1568
1630
|
});
|
|
1569
1631
|
|
|
1570
1632
|
let html = await page.evaluate(() => document.documentElement.outerHTML);
|
|
1633
|
+
if (config.debugPrerender) {
|
|
1634
|
+
const post = await page.evaluate(() => {
|
|
1635
|
+
const templates = document.querySelectorAll('template[x-for]').length;
|
|
1636
|
+
const links = document.querySelectorAll('a[href="#"]').length;
|
|
1637
|
+
const hidden = document.querySelectorAll('[style*="display: none"]').length;
|
|
1638
|
+
return { templateCountAfterCleanup: templates, hashHrefCount: links, displayNoneCount: hidden };
|
|
1639
|
+
}).catch(() => null);
|
|
1640
|
+
pushDebug({ path: displayPath, stage: 'pre-serialize', metrics: post });
|
|
1641
|
+
}
|
|
1571
1642
|
html = stripDevOnlyContent(html);
|
|
1572
1643
|
html = stripInjectedPluginScripts(html);
|
|
1573
1644
|
if (tailwindBuilt) {
|
|
@@ -1587,6 +1658,7 @@ async function runPrerender(config) {
|
|
|
1587
1658
|
const xData = { manifest, content };
|
|
1588
1659
|
html = resolveHeadXBindings(html, xData);
|
|
1589
1660
|
html = stripPrerenderDynamicBindings(html);
|
|
1661
|
+
html = stripEmptyInlineMaskStyles(html);
|
|
1590
1662
|
html = rewriteHtmlAssetPaths(html, fileSegments.length);
|
|
1591
1663
|
const liveBase = config.liveUrl.replace(/\/$/, '');
|
|
1592
1664
|
const canonicalHreflang = buildCanonicalAndHreflang(is404 ? '' : pathSeg, locales, defaultLocale, liveBase);
|
|
@@ -1599,6 +1671,13 @@ async function runPrerender(config) {
|
|
|
1599
1671
|
html = html.replace('</head>', `${canonicalHreflang}${injectOgLocale ? ogLocale : ''}${baseMeta}${prerenderedMeta}<meta name="manifest:router-base-depth" content="${routeDepth}">\n</head>`);
|
|
1600
1672
|
mkdirSync(outDir, { recursive: true });
|
|
1601
1673
|
writeFileSync(outFile, html, 'utf8');
|
|
1674
|
+
pushDebug({
|
|
1675
|
+
path: displayPath,
|
|
1676
|
+
stage: 'wrote',
|
|
1677
|
+
outFile,
|
|
1678
|
+
htmlBytes: Buffer.byteLength(html, 'utf8'),
|
|
1679
|
+
hasXForTemplate: html.includes('template x-for') || html.includes('template[x-for]'),
|
|
1680
|
+
});
|
|
1602
1681
|
} catch (err) {
|
|
1603
1682
|
failedPaths.push({
|
|
1604
1683
|
path: displayPath,
|
|
@@ -1633,6 +1712,17 @@ async function runPrerender(config) {
|
|
|
1633
1712
|
throw new Error(`prerender failed for ${failedPaths.length}/${pathTotal} paths. Sample: ${sample}`);
|
|
1634
1713
|
}
|
|
1635
1714
|
|
|
1715
|
+
if (config.debugPrerender) {
|
|
1716
|
+
const reportPath = join(outputResolved, 'prerender.debug.json');
|
|
1717
|
+
writeFileSync(reportPath, JSON.stringify({
|
|
1718
|
+
generatedAt: new Date().toISOString(),
|
|
1719
|
+
totalPaths: pathTotal,
|
|
1720
|
+
failedPaths,
|
|
1721
|
+
rows: debugRows,
|
|
1722
|
+
}, null, 2), 'utf8');
|
|
1723
|
+
process.stdout.write(`prerender: debug report ${reportPath}\n`);
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1636
1726
|
if (bundleUtilities) {
|
|
1637
1727
|
const utilMerged = mergeUtilityCssBlocks(utilityBlocks);
|
|
1638
1728
|
if (utilMerged.trim()) {
|