mnfst-render 0.4.1 → 0.4.2

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.
@@ -1683,16 +1683,39 @@ async function runPrerender(config) {
1683
1683
  const puppeteerPaths = [];
1684
1684
  const localeVariantPaths = []; // { pathSeg, basePathSeg, targetLocale }
1685
1685
 
1686
+ // Two-pass categorisation: locale substitution only applies when the locale-neutral base path
1687
+ // (e.g. 'about' for 'fr/about') is itself in the path list and will be Puppeteer-rendered.
1688
+ //
1689
+ // Paths whose data is inherently locale-specific (e.g. 'en/articles/slug', 'fr/articles/slug'
1690
+ // discovered from per-locale data sources) have no locale-neutral counterpart and must be
1691
+ // rendered by Puppeteer directly — their content differs per locale and substitution cannot
1692
+ // produce correct output. This mirrors the framework's own data model: locale-neutral paths
1693
+ // use a shared structure with CSV text overlay; locale-prefixed paths carry per-locale content.
1694
+
1695
+ // Pass 1: collect all locale-neutral path segments (no locale prefix in the first segment).
1696
+ const localeNeutralPathSet = new Set();
1697
+ for (const seg of pathList) {
1698
+ if (!seg || seg === NOT_FOUND_PATH) continue;
1699
+ if (!localeSet.has(seg.split('/')[0])) localeNeutralPathSet.add(seg);
1700
+ }
1701
+
1702
+ // Pass 2: categorise.
1686
1703
  for (const seg of pathList) {
1687
1704
  if (!localeSubstEnabled || seg === NOT_FOUND_PATH || !seg) {
1688
1705
  puppeteerPaths.push(seg);
1689
1706
  continue;
1690
1707
  }
1691
- const firstPart = seg.split('/')[0];
1692
- if (localeSet.has(firstPart) && !localeSubstExclude.has(firstPart)) {
1693
- const basePathSeg = seg.slice(firstPart.length + 1); // strip 'fr/'
1694
- localeVariantPaths.push({ pathSeg: seg, basePathSeg: basePathSeg || '', targetLocale: firstPart });
1708
+ const fp = seg.split('/')[0];
1709
+ if (!localeSet.has(fp) || localeSubstExclude.has(fp)) {
1710
+ puppeteerPaths.push(seg);
1711
+ continue;
1712
+ }
1713
+ const basePathSeg = seg.slice(fp.length + 1) || '';
1714
+ if (localeNeutralPathSet.has(basePathSeg)) {
1715
+ // Locale-neutral base exists and will be Puppeteer-rendered → safe to substitute.
1716
+ localeVariantPaths.push({ pathSeg: seg, basePathSeg, targetLocale: fp });
1695
1717
  } else {
1718
+ // No locale-neutral base — this path has per-locale content; Puppeteer required.
1696
1719
  puppeteerPaths.push(seg);
1697
1720
  }
1698
1721
  }
@@ -2344,9 +2367,9 @@ async function runPrerender(config) {
2344
2367
  substIndex++;
2345
2368
  const rawHtml = baseHtmlCache.get(basePathSeg);
2346
2369
  if (!rawHtml) {
2347
- // Base path wasn't rendered log and skip (shouldn't happen in normal builds)
2348
- failedPaths.push({ path: '/' + pathSeg, message: `substitution skipped: base path "${basePathSeg || '/'}" not in cache` });
2349
- process.stderr.write(`prerender: substitution skipped /${pathSeg} (base not found)\n`);
2370
+ // Base path was expected to be Puppeteer-rendered but is absent its render likely failed.
2371
+ failedPaths.push({ path: '/' + pathSeg, message: `base path "${basePathSeg || '/'}" missing from cache (did its Puppeteer render fail?)` });
2372
+ process.stderr.write(`prerender: skipped /${pathSeg} base "${basePathSeg || '/'}" not in cache\n`);
2350
2373
  continue;
2351
2374
  }
2352
2375
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst-render",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Render Manifest sites to static HTML for SEO",
5
5
  "type": "module",
6
6
  "bin": {