mnfst-render 0.5.35 → 0.5.36

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.
@@ -1814,6 +1814,20 @@ function computeGlobalAssetSignature(rootDir) {
1814
1814
  async function waitForVisualSettle(page, { settleMs = 300, mdWaitMs = 5000, capMs = 8000 } = {}) {
1815
1815
  try {
1816
1816
  await page.evaluate(async ({ settleMs, mdWaitMs, capMs }) => {
1817
+ // Preferred: the framework's own settled signal (loader ≥0.5.190).
1818
+ if (window.__manifestReadyCoordinator) {
1819
+ const start = Date.now();
1820
+ while (!window.__manifestReady && Date.now() - start < capMs + 8000) {
1821
+ await new Promise((r) => setTimeout(r, 100));
1822
+ }
1823
+ if (document.fonts?.ready) { try { await document.fonts.ready; } catch { /* best-effort */ } }
1824
+ await new Promise((r) => {
1825
+ const t = setTimeout(r, 250);
1826
+ requestAnimationFrame(() => requestAnimationFrame(() => { clearTimeout(t); r(); }));
1827
+ });
1828
+ return;
1829
+ }
1830
+ // Fallback heuristic for older framework builds:
1817
1831
  const state = () => {
1818
1832
  let styleLen = 0;
1819
1833
  for (const s of document.querySelectorAll('style')) styleLen += (s.textContent || '').length;
@@ -4352,6 +4366,62 @@ async function runPrerender(config) {
4352
4366
  if (tpl.hasAttribute('data-hydrate') || tpl.closest('[data-hydrate]')) return;
4353
4367
  tag(tpl._x_currentIfEl);
4354
4368
  });
4369
+
4370
+ // Clones inside CLOSED popovers carry no crawler value and are wiped
4371
+ // at boot anyway (Alpine re-renders from the template) — drop them from
4372
+ // the output entirely.
4373
+ document.querySelectorAll('[data-mnfst-prerender-clone]').forEach((el) => {
4374
+ if (!document.contains(el)) return;
4375
+ const pop = el.closest('[popover]');
4376
+ if (pop && !pop.matches(':popover-open')) el.remove();
4377
+ });
4378
+
4379
+ // Containers stamped data-mnfst-generated are fully rebuilt by their
4380
+ // plugin at boot (e.g. a colorpicker's palette library — thousands of
4381
+ // swatch nodes with full palette JSON in x-data). Serialize them empty.
4382
+ document.querySelectorAll('[data-mnfst-generated]').forEach((el) => {
4383
+ if (document.contains(el)) el.innerHTML = '';
4384
+ });
4385
+
4386
+ // Legacy bridge for colorpickers older than the stamp (<0.5.190): the
4387
+ // palette library wrapper is rebuilt from scratch at boot regardless,
4388
+ // so drop it from the output. Remove once sites pin a stamped build.
4389
+ document.querySelectorAll('.library-wrapper').forEach((el) => {
4390
+ if (el.querySelector('.library-palette, [data-cp-library-group]')) el.remove();
4391
+ });
4392
+ });
4393
+
4394
+ // Deterministic output: randomized CSS anchor-positioning names
4395
+ // (--dropdown-x7f2, --popover-…, --anchor-…) are regenerated per run and
4396
+ // made every render a phantom diff. Renumber them sequentially in DOM
4397
+ // order so identical content serializes identically.
4398
+ await page.evaluate(() => {
4399
+ const RE = /--(dropdown|popover|anchor)-[a-z0-9]+/g;
4400
+ const map = new Map();
4401
+ const counters = { dropdown: 0, popover: 0, anchor: 0 };
4402
+ const rename = (m, kind) => {
4403
+ if (!map.has(m)) map.set(m, `--${kind}-p${++counters[kind]}`);
4404
+ return map.get(m);
4405
+ };
4406
+ for (const el of document.querySelectorAll('*')) {
4407
+ for (const attr of el.attributes) {
4408
+ if (!attr.value || attr.value.indexOf('--') === -1) continue;
4409
+ const next = attr.value.replace(RE, (m, kind) => rename(m, kind));
4410
+ if (next !== attr.value) el.setAttribute(attr.name, next);
4411
+ }
4412
+ }
4413
+
4414
+ // Component bookkeeping attrs land in whichever order the swap raced —
4415
+ // re-set the pair canonically so it can't flip between runs. (They are
4416
+ // not Alpine directives; position carries no behavior.)
4417
+ for (const el of document.querySelectorAll('[data-component][data-order]')) {
4418
+ const c = el.getAttribute('data-component');
4419
+ const o = el.getAttribute('data-order');
4420
+ el.removeAttribute('data-component');
4421
+ el.removeAttribute('data-order');
4422
+ el.setAttribute('data-component', c);
4423
+ el.setAttribute('data-order', o);
4424
+ }
4355
4425
  });
4356
4426
 
4357
4427
  // SEO / AEO meta injection — see resolveConfig().seo for precedence layers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst-render",
3
- "version": "0.5.35",
3
+ "version": "0.5.36",
4
4
  "description": "Render Manifest sites to static HTML for SEO",
5
5
  "type": "module",
6
6
  "bin": {