mnfst-render 0.4.4 → 0.4.6

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.
@@ -2153,6 +2153,48 @@ async function runPrerender(config) {
2153
2153
  pushDebug({ path: displayPath, stage: 'post-xfor-mark', metrics: afterMark });
2154
2154
  }
2155
2155
 
2156
+ // For static x-for clones that contain data-hydrate elements, inject the loop-scope
2157
+ // variable as x-data on the clone element itself. This ensures that after the loop
2158
+ // template is removed, data-hydrate bindings referencing loop variables (e.g.
2159
+ // plan?.price?.[currency]?.[frequency]) continue to work at runtime via the injected scope.
2160
+ // The parent Alpine scope (e.g. <main x-data="{ currency, frequency }") remains accessible.
2161
+ await page.evaluate(() => {
2162
+ const loopVarRx = /^\s*(?:\(\s*([A-Za-z_$][\w$]*)(?:\s*,\s*([A-Za-z_$][\w$]*))?\s*\)|([A-Za-z_$][\w$]*))\s+in\s+/;
2163
+ document.querySelectorAll('template[x-for][data-prerender-static-generated="1"]').forEach((tpl) => {
2164
+ if (tpl.hasAttribute('data-prerender-hydrate') || tpl.closest('[data-prerender-hydrate]')) return;
2165
+ const xFor = (tpl.getAttribute('x-for') || '').trim();
2166
+ const m = xFor.match(loopVarRx);
2167
+ const itemVar = m ? (m[1] || m[3] || '') : '';
2168
+ if (!itemVar) return;
2169
+ const first = tpl.content && tpl.content.firstElementChild;
2170
+ if (!first) return;
2171
+ const tag = first.tagName;
2172
+ const cls = first.getAttribute('class') || '';
2173
+ let n = tpl.nextElementSibling;
2174
+ while (n && n.tagName === tag && (n.getAttribute('class') || '') === cls) {
2175
+ // Only process clones that contain data-hydrate descendants
2176
+ if (
2177
+ !n.hasAttribute('x-data') &&
2178
+ (n.hasAttribute('data-prerender-hydrate') || n.querySelector('[data-prerender-hydrate]'))
2179
+ ) {
2180
+ try {
2181
+ const A = window.Alpine;
2182
+ if (A && typeof A.$data === 'function') {
2183
+ const scope = A.$data(n);
2184
+ if (scope && Object.prototype.hasOwnProperty.call(scope, itemVar)) {
2185
+ const raw = scope[itemVar];
2186
+ // Serialize only own-enumerable properties to avoid circular refs / proxies
2187
+ const snapshot = JSON.parse(JSON.stringify(raw));
2188
+ n.setAttribute('x-data', JSON.stringify({ [itemVar]: snapshot }));
2189
+ }
2190
+ }
2191
+ } catch { /* serialisation failed — leave binding as-is */ }
2192
+ }
2193
+ n = n.nextElementSibling;
2194
+ }
2195
+ });
2196
+ });
2197
+
2156
2198
  // Strip loop-scope bindings from x-for clones while <template> nodes still exist.
2157
2199
  // (If we remove static templates first, querySelectorAll('template[x-for]') misses them and clones
2158
2200
  // keep x-text/x-bind referencing card/item — Alpine then mutates or errors on the static HTML.)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst-render",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "Render Manifest sites to static HTML for SEO",
5
5
  "type": "module",
6
6
  "bin": {