mnfst-render 0.5.16 → 0.5.17

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.
@@ -1474,6 +1474,26 @@ function loadContentForPrerender(manifest, rootDir, locale) {
1474
1474
  content = parseCsvToKeyValue(join(rootDir, data.slice(1)), loc);
1475
1475
  } else if (data && typeof data === 'object' && data.locales && typeof data.locales === 'string') {
1476
1476
  content = parseCsvToKeyValue(join(rootDir, data.locales.slice(1)), loc);
1477
+ } else if (data && typeof data === 'object' && !Array.isArray(data)) {
1478
+ // Per-locale files: { "en": "/data/content.en.yaml", "fr": "/data/content.fr.yaml", ... }
1479
+ const filePath = data[loc] || data[Object.keys(data)[0]];
1480
+ if (typeof filePath === 'string') {
1481
+ const fullPath = join(rootDir, filePath.startsWith('/') ? filePath.slice(1) : filePath);
1482
+ if (existsSync(fullPath)) {
1483
+ try {
1484
+ const raw = readFileSync(fullPath, 'utf8');
1485
+ if (filePath.endsWith('.yaml') || filePath.endsWith('.yml')) {
1486
+ let jsYaml = null;
1487
+ try { jsYaml = require('js-yaml'); } catch { /* skip */ }
1488
+ if (jsYaml) content = jsYaml.load(raw) || {};
1489
+ } else if (filePath.endsWith('.json')) {
1490
+ content = JSON.parse(raw);
1491
+ } else if (filePath.endsWith('.csv')) {
1492
+ content = parseCsvToKeyValue(fullPath, loc);
1493
+ }
1494
+ } catch { /* ignore parse errors */ }
1495
+ }
1496
+ }
1477
1497
  }
1478
1498
  if (manifest.description !== undefined && content.description === undefined) {
1479
1499
  content.description = manifest.description;
@@ -1546,15 +1566,27 @@ function resolveHeadXBindings(html, xData) {
1546
1566
  .replace(/>/g, '>')
1547
1567
  .replace(/"/g, '"');
1548
1568
  return html.replace(/<head>([\s\S]*?)<\/head>/i, (_, headContent) => {
1549
- let out = headContent.replace(
1550
- /(\s)(?::|x-bind:)(\w+)=["'](\$x\.[^"']+)["']/g,
1551
- (_, space, attr, expr) => {
1569
+ // Process each tag in <head> that has a :attr or x-bind:attr binding
1570
+ const out = headContent.replace(/<[^>]+>/g, (tag) => {
1571
+ // Find all :attr="$x...." or x-bind:attr="$x...." bindings in this tag
1572
+ const bindingRe = /\s(?::|x-bind:)(\w+)=["'](\$x\.[^"']+)["']/g;
1573
+ let m;
1574
+ let newTag = tag;
1575
+ while ((m = bindingRe.exec(tag)) !== null) {
1576
+ const attr = m[1];
1577
+ const expr = m[2];
1552
1578
  const path = expr.replace(/^\$x\./, '').trim();
1553
1579
  const value = getXPath(xData, path);
1554
- if (value === undefined) return _;
1555
- return `${space}${attr}="${esc(value)}"`;
1580
+ if (value === undefined) continue;
1581
+ // Remove the binding
1582
+ newTag = newTag.replace(m[0], '');
1583
+ // Remove existing static fallback for this attr
1584
+ newTag = newTag.replace(new RegExp(`\\s${attr}=["'][^"']*["']`), '');
1585
+ // Insert the resolved attr before the closing >
1586
+ newTag = newTag.replace(/>$/, ` ${attr}="${esc(value)}">`);
1556
1587
  }
1557
- );
1588
+ return newTag;
1589
+ });
1558
1590
  return `<head>${out}</head>`;
1559
1591
  });
1560
1592
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst-render",
3
- "version": "0.5.16",
3
+ "version": "0.5.17",
4
4
  "description": "Render Manifest sites to static HTML for SEO",
5
5
  "type": "module",
6
6
  "bin": {