mnfst 0.5.252 → 0.5.253

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  (function () {
4
4
 
5
- const MANIFEST_BUILD_VERSION = '0.5.252';
5
+ const MANIFEST_BUILD_VERSION = '0.5.253';
6
6
 
7
7
  /* Manifest Data Sources - Appwrite Integration */
8
8
 
package/lib/manifest.d.ts CHANGED
@@ -657,6 +657,15 @@ declare global {
657
657
  };
658
658
  Alpine?: unknown;
659
659
  __manifestLoaded?: unknown;
660
+ /** Pending work that will still change the page; mnfst-render's auto settle won't snapshot early while count > 0. */
661
+ ManifestPending?: {
662
+ /** Hold until the work's DOM update lands; call the returned function to release. */
663
+ hold(label?: string): () => void;
664
+ readonly count: number;
665
+ labels(): string[];
666
+ /** Mark a timer callback as housekeeping that never changes the page (auto settle ignores it). */
667
+ background<T extends Function>(fn: T): T;
668
+ };
660
669
  /** Rich text engine (rich-text plugin). */
661
670
  ManifestRichText?: {
662
671
  attach(el: Element, options?: ManifestRichTextAttachOptions): ManifestRichTextHandle | null;
@@ -2,7 +2,7 @@
2
2
 
3
3
  (function () {
4
4
 
5
- const MANIFEST_BUILD_VERSION = '0.5.252';
5
+ const MANIFEST_BUILD_VERSION = '0.5.253';
6
6
 
7
7
  /* Manifest Data Sources - Configuration */
8
8
 
@@ -1134,10 +1134,11 @@ function setupTeamChangeListener() {
1134
1134
  lastTeamId = authStore.currentTeam?.$id || null;
1135
1135
  if (!teamCheckIntervalId) {
1136
1136
  // Poll every 2s to limit CPU wakeups; team changes are rare
1137
- teamCheckIntervalId = setInterval(checkTeamChange, 2000);
1137
+ teamCheckIntervalId = setInterval(window.ManifestPending?.background?.(checkTeamChange) ?? checkTeamChange, 2000);
1138
1138
  }
1139
1139
  } else {
1140
- setTimeout(startPolling, 100);
1140
+ // Waits for an auth plugin that may never load: housekeeping, not page work
1141
+ setTimeout(window.ManifestPending?.background?.(startPolling) ?? startPolling, 100);
1141
1142
  }
1142
1143
  };
1143
1144
 
@@ -9479,7 +9480,8 @@ function registerXMagicMethod(loadDataSource) {
9479
9480
  : (typeof Alpine !== 'undefined' && Alpine.store('locale')?.current) || 'en';
9480
9481
  pendingLoads.set(prop, Promise.resolve(loadDataSource(prop, locale)));
9481
9482
  pendingLoads.get(prop).finally(() => {
9482
- setTimeout(() => pendingLoads.delete(prop), 1000);
9483
+ const clear = () => pendingLoads.delete(prop);
9484
+ setTimeout(window.ManifestPending?.background?.(clear) ?? clear, 1000);
9483
9485
  });
9484
9486
  }
9485
9487
  track();
@@ -9904,9 +9906,8 @@ function registerXMagicMethod(loadDataSource) {
9904
9906
  }
9905
9907
  }
9906
9908
  // Only clear pendingLoads after a delay to prevent rapid retries
9907
- setTimeout(() => {
9908
- pendingLoads.delete(prop);
9909
- }, 1000);
9909
+ const clear = () => { pendingLoads.delete(prop); };
9910
+ setTimeout(window.ManifestPending?.background?.(clear) ?? clear, 1000);
9910
9911
  });
9911
9912
 
9912
9913
  activeProps.delete(propKey); // Remove from active set before returning
@@ -470,7 +470,9 @@ function markReady() {
470
470
  if (ready) return;
471
471
  ready = true;
472
472
  schedule();
473
- setTimeout(() => { bootDrained = true; }, 5000); // lazy components may keep the boot queue busy
473
+ // lazy components may keep the boot queue busy; only gates gesture promotion, so not page work
474
+ const drained = () => { bootDrained = true; };
475
+ setTimeout(window.ManifestPending?.background?.(drained) ?? drained, 5000);
474
476
  }
475
477
 
476
478
  function armReady() {
@@ -548,7 +550,8 @@ if (window.Alpine && typeof window.Alpine.interceptInit === 'function') {
548
550
  ensureDeferPluginInitialized();
549
551
  }
550
552
  }, 10);
551
- setTimeout(() => clearInterval(checkAlpine), 5000);
553
+ const giveUp = () => clearInterval(checkAlpine);
554
+ setTimeout(window.ManifestPending?.background?.(giveUp) ?? giveUp, 5000);
552
555
  }
553
556
 
554
557
  })();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "manifest.appwrite.auth.js": "sha384-dsIWnH0qCAGSzAXMGrd8fvOrVl4tOIE6j5tC35JPTrQXZ56qLD36ARyvhR7vi3Id",
3
- "manifest.appwrite.data.js": "sha384-ozJWOlJIK7LVTu2+Q7x3rj9vxLkLMv8UfYwyK0nXvcWNN/k4zfR1oZOGJtWqN8xh",
3
+ "manifest.appwrite.data.js": "sha384-xxVLbIAAzMs+ksXTzRGtu0GxALohKKkFRXsvLyp6BvZesTk/JsS0lscvkIcOyGO1",
4
4
  "manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
5
5
  "manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
6
6
  "manifest.charts.js": "sha384-G+huD7UvjF9zDovdVVlh4I5X1Mq4oNnJfoFg4NnGdP3R/4Skq9hy5cGuHNYLxDYm",
@@ -11,9 +11,9 @@
11
11
  "manifest.combobox.js": "sha384-MILTkrgsTzsYUjGo4ZuADqV85Xs4GmfB4xexfe9vbJMIoQTZ42W4zs+DTaVSPEsx",
12
12
  "manifest.components.js": "sha384-BUFA8h+G5Plr82sV7bKzO42pPoiRZwRQcKj1lt2ROFiKjjlkayU/vmkAFqEsdBA+",
13
13
  "manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
14
- "manifest.data.js": "sha384-Kf2waez743KjVRCA5fwEWeIONhH8nzLOmF4jeQcm1DXnAprPbDUq0kYETtq+aQ7e",
14
+ "manifest.data.js": "sha384-apX4l/k05t8snFyKYLbMbN+kG6xjHHI8gbs32376S3WruzynLOaF+uq43cCGfifp",
15
15
  "manifest.datepicker.js": "sha384-2XwFFnS4Bg5FDvG/v8x6KUvrjcBQEOYyTxynX2K/D/Qb3PI6+Y04lEwCnVDJLzwL",
16
- "manifest.defer.js": "sha384-pMRGqQKiEoJhpUcD40QeM4jEHau7sz9Xn/YCpiUamT1T4xJBZDSiYX+xnVrSWoq+",
16
+ "manifest.defer.js": "sha384-GK9qJkYtchtyzSQ+3zmDQUJE3+au4qthT2M8JnFjXxgfwCH5IVKc2r3tackgMryU",
17
17
  "manifest.device.js": "sha384-jY+Xjt/v4I7SWTFzIGdPRJRTl634i6pj5T6jQaEn9keNTccPGD9lAIbYWq4J8oc7",
18
18
  "manifest.dropdowns.js": "sha384-acufUps7R9WjqB4XXW5JLACqniuHJGM4CNTb2rF4B2Q/jv7ZRmsAwfr2McanOz3s",
19
19
  "manifest.edit.js": "sha384-MOgQNdNLeHijhR0u2W6ntoOulKFglsATCFDqkinesOU15tHoILk/JNzHKkGi5dUG",
@@ -24,17 +24,17 @@
24
24
  "manifest.native.js": "sha384-jY+Xjt/v4I7SWTFzIGdPRJRTl634i6pj5T6jQaEn9keNTccPGD9lAIbYWq4J8oc7",
25
25
  "manifest.payments.js": "sha384-8pofk2zhxtapPMpwnFyTelPMrYhShNhDCE722uQh/EYFvZFuPLmSdgunqsarVQjv",
26
26
  "manifest.rich.text.js": "sha384-ZBV9jXmu2nmprEHicddRE/m7nR4RPZtVc969Jte0+EJYBcVph7itkjcgN/61PyeC",
27
- "manifest.router.js": "sha384-JcKnEb0E9azl6DVSN1DQMysyZOpGkskSQREjD947sMEs87nFEeZpCigB0iq8psz5",
27
+ "manifest.router.js": "sha384-9LMIkwrgnxmmFDv70TND2MRJF1z6Nl4yqG7fH5DbJ8oUIhdu/u4yUPSime1/EYhP",
28
28
  "manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
29
29
  "manifest.status.js": "sha384-MBO345ab7H6Uq1X2dZLt4Ge1Gcra+Z2qYApvlAeIV8CJhDDJrz2FPXpp+Kcp8zcM",
30
30
  "manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
31
- "manifest.sw.js": "sha384-CMsL0155vAYPFcYs6V0VGt1nQgfCdN24ZC07uiS/t8rlUlFPXp8tkVkuFxMOpl4v",
32
- "manifest.tabs.js": "sha384-OIIcyaQnGS0eNYk4zgAFEDboNYect7THvUd9D0V6nqCeDOxQcoiqLrBEmmWVTTet",
31
+ "manifest.sw.js": "sha384-9Kcczuh7GSCImjjTu09aZ0C/EaVHItZ0McwTdNqv1ZCWZe0UfUn9+IYX3ISYE0kk",
32
+ "manifest.tabs.js": "sha384-otU09H7jnawVKQdLAYpMCd3jx00tgyPVr42D2hLIBzN5dG4se505YesavdnMqEi1",
33
33
  "manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
34
34
  "manifest.toasts.js": "sha384-3zkWxzw693pxg3QDFsoYCA3CqYaLKmBaMArULXODD66Utolpewl0OAeTB92aWUVv",
35
35
  "manifest.tooltips.js": "sha384-4b24PH5WsfFsewGea5SMWLwmrhC4kD6eDP/vvjNyjXYnQXXFGi4nLdojrIOwzG8M",
36
36
  "manifest.url.parameters.js": "sha384-J2aSVBOPsoqsbafHndrWLHEDpKb4AKJAoQnVmKA4gZh5P/8HHjFWHO/lkusmG84l",
37
- "manifest.utilities.js": "sha384-L5uXMLFBIF6LUM1haRjd4eGjHSWuqsCYSpPZRPYosNfJsMC5U5TnmjBxIhrZRe2d",
37
+ "manifest.utilities.js": "sha384-h17EquaRtNcEW0yfhk7R+a+2+CzTlBxPuFryO6i9NV/OiIRMihREoyzQ77QawoQ7",
38
38
  "manifest.virtual.js": "sha384-ZDNoF9QVhVcVpkjIK6NH15S6I5c6OBshiJpXSOYjNsIB+298I0a7g3aFO+jyq4Vb",
39
- "manifest.js": "sha384-lLuq+77pwlGNK01XTOSimDh8boFBUmKQA8rR53QudXl/Igiv8MU4w+wRCSHdc/mg"
39
+ "manifest.js": "sha384-OmHDWM4X9puYLwv9Y0Hqnymh80AESBTsXrMYcksqduBCCRkolnxjRlIbCOU5pjvk"
40
40
  }
package/lib/manifest.js CHANGED
@@ -11,6 +11,33 @@
11
11
 
12
12
  const loaderScript = document.currentScript;
13
13
 
14
+ // Pending work that will still change the page: plugins hold() until their DOM update lands; mnfst-render's auto settle won't snapshot early while count > 0
15
+ if (!window.ManifestPending) {
16
+ const holds = new Map();
17
+ let seq = 0;
18
+ window.ManifestPending = {
19
+ hold(label = 'work') {
20
+ const id = ++seq;
21
+ holds.set(id, label);
22
+ return () => { holds.delete(id); };
23
+ },
24
+ get count() {
25
+ return holds.size + (window.__manifestMarkdownPending || 0) + (window.__manifestUtilitiesPending || 0);
26
+ },
27
+ labels() {
28
+ const out = [...holds.values()];
29
+ if (window.__manifestMarkdownPending > 0) out.push('markdown');
30
+ if (window.__manifestUtilitiesPending > 0) out.push('utilities');
31
+ return out;
32
+ },
33
+ // Marks a timer callback as housekeeping that never changes the page; prerender doesn't wait for it
34
+ background(fn) {
35
+ if (typeof fn === 'function') fn.__manifestBackground = true;
36
+ return fn;
37
+ },
38
+ };
39
+ }
40
+
14
41
  /*
15
42
  * Hydration contract runtime: prerendered MPA pages carry a `#__manifest_hydrate__`
16
43
  * diff of source-authored attributes (and data-hydrate innerHTML). Applied once
@@ -1252,6 +1279,7 @@
1252
1279
  function startReadyCoordinator(plugins, tailwindEnabled) {
1253
1280
  if (window.__manifestReadyCoordinator) return;
1254
1281
  window.__manifestReadyCoordinator = true;
1282
+ const release = window.ManifestPending.hold('ready');
1255
1283
  const needData = plugins.some(p => p === 'data' || p === 'appwrite-data');
1256
1284
  const needUtilities = !!tailwindEnabled;
1257
1285
  const state = {
@@ -1265,6 +1293,7 @@
1265
1293
  const fire = () => {
1266
1294
  if (fired) return;
1267
1295
  fired = true;
1296
+ release();
1268
1297
  window.__manifestReady = true;
1269
1298
  window.dispatchEvent(new CustomEvent('manifest:ready'));
1270
1299
  };
@@ -1396,7 +1396,8 @@ function initializeAnchors() {
1396
1396
  if (anchors.length > 0) {
1397
1397
  updateAnchors(anchors);
1398
1398
  return true;
1399
- } else if (attempt < maxAttempts) {
1399
+ } else if (attempt < maxAttempts && window.__manifestRenderSettle !== 'auto') {
1400
+ // mnfst-render's auto settle re-extracts anchors once content settles; no need to poll for it
1400
1401
  setTimeout(() => {
1401
1402
  attemptExtraction(attempt + 1, maxAttempts);
1402
1403
  }, attempt * 200); // Progressive delay: 200ms, 400ms, 600ms, etc.
@@ -1465,7 +1466,8 @@ window.addEventListener('manifest:route-change', () => {
1465
1466
  t = setTimeout(finish, 50);
1466
1467
  });
1467
1468
  observer.observe(container, { childList: true, subtree: true });
1468
- const fallback = setTimeout(finish, 800);
1469
+ // Under mnfst-render's auto settle the engine re-extracts anchors from settled content: don't hold it
1470
+ const fallback = setTimeout(window.__manifestRenderSettle === 'auto' ? (window.ManifestPending?.background?.(finish) ?? finish) : finish, 800);
1469
1471
  };
1470
1472
 
1471
1473
  requestAnimationFrame(() => {
@@ -693,6 +693,12 @@
693
693
  "default": 0,
694
694
  "description": "Extra milliseconds after a page settles, before its og image and snapshot — for widgets that fill in late without network or DOM activity. --wait-after-idle overrides."
695
695
  },
696
+ "settle": {
697
+ "type": "string",
698
+ "enum": ["fixed", "auto"],
699
+ "default": "fixed",
700
+ "description": "How a page counts as settled before its snapshot. fixed (default): network idle, then DOM quiet (about 2 seconds per page). auto (opt-in, faster): snapshots early when no request, timer, interval, scheduled task, animation, idle callback, stream, socket, worker, service-worker install, cross-origin frame, recent message-channel activity, data load or framework hold is pending; otherwise it uses the fixed waits. Pages whose scripts use other schedulers should stay on fixed. Use waitAfterIdle for content a script adds after a longer timer. --settle overrides."
701
+ },
696
702
  "blockRequests": {
697
703
  "type": "array",
698
704
  "items": {
@@ -16,7 +16,7 @@
16
16
 
17
17
  // Build stamps the published version here; unstamped (dev) falls back to the
18
18
  // registration URL's `v`, then 'dev'.
19
- const BUILD_VERSION = '0.5.252';
19
+ const BUILD_VERSION = '0.5.253';
20
20
  const CACHE_PREFIX = 'mnfst-sw:';
21
21
  const META_CACHE = CACHE_PREFIX + 'meta';
22
22
  // Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
@@ -348,10 +348,10 @@ function initializeTabsPlugin() {
348
348
  }
349
349
  }
350
350
 
351
- // Add a fallback timer to catch cases where events don't fire
351
+ // Add a fallback timer to catch cases where events don't fire (mnfst-render auto settle: soon, so it waits for it)
352
352
  setTimeout(() => {
353
353
  processTabsWhenReady();
354
- }, 2000);
354
+ }, window.__manifestRenderSettle === 'auto' ? 200 : 2000);
355
355
  }
356
356
 
357
357
  // Track initialization to prevent duplicates
@@ -3226,7 +3226,7 @@ TailwindCompiler.prototype.compileDelta = function (themeCss) {
3226
3226
  // Coalesce cache writes: localStorage serialisation is too slow to run per compile
3227
3227
  TailwindCompiler.prototype.schedulePersistentSave = function (themeCss) {
3228
3228
  clearTimeout(this._persistTimer);
3229
- this._persistTimer = setTimeout(() => {
3229
+ const save = () => {
3230
3230
  if (!this._applied) return;
3231
3231
  const classesHash = Array.from(this.dynamicClassCache).sort().join(',');
3232
3232
  const themeHash = this.generateThemeHash(themeCss);
@@ -3236,7 +3236,8 @@ TailwindCompiler.prototype.schedulePersistentSave = function (themeCss) {
3236
3236
  themeHash
3237
3237
  });
3238
3238
  this.savePersistentCache();
3239
- }, 1000);
3239
+ };
3240
+ this._persistTimer = setTimeout(window.ManifestPending?.background?.(save) ?? save, 1000);
3240
3241
  };
3241
3242
 
3242
3243
  // Helper function to filter critical utilities that are already in layer utilities
@@ -2660,7 +2660,7 @@ TailwindCompiler.prototype.compileDelta = function (themeCss) {
2660
2660
  // Coalesce cache writes: localStorage serialisation is too slow to run per compile
2661
2661
  TailwindCompiler.prototype.schedulePersistentSave = function (themeCss) {
2662
2662
  clearTimeout(this._persistTimer);
2663
- this._persistTimer = setTimeout(() => {
2663
+ const save = () => {
2664
2664
  if (!this._applied) return;
2665
2665
  const classesHash = Array.from(this.dynamicClassCache).sort().join(',');
2666
2666
  const themeHash = this.generateThemeHash(themeCss);
@@ -2670,7 +2670,8 @@ TailwindCompiler.prototype.schedulePersistentSave = function (themeCss) {
2670
2670
  themeHash
2671
2671
  });
2672
2672
  this.savePersistentCache();
2673
- }, 1000);
2673
+ };
2674
+ this._persistTimer = setTimeout(window.ManifestPending?.background?.(save) ?? save, 1000);
2674
2675
  };
2675
2676
 
2676
2677
  // Helper function to filter critical utilities that are already in layer utilities
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst",
3
- "version": "0.5.252",
3
+ "version": "0.5.253",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "templates/starter",
@@ -46,6 +46,7 @@
46
46
  "test:e2e": "node tests/e2e/payments.e2e.mjs",
47
47
  "test:e2e:sdk": "node tests/e2e/payments.sdk.e2e.mjs",
48
48
  "test:e2e:sw": "node tests/e2e/sw.e2e.mjs",
49
+ "test:e2e:settle": "node tests/e2e/render-settle.e2e.mjs",
49
50
  "lint": "echo 'No linting configured'",
50
51
  "release:docs": "node scripts/release-bump.mjs packages/docs && cd packages/docs && npm publish --auth-type=web",
51
52
  "release:check": "node scripts/release-check.mjs"