mnfst 0.5.200 → 0.5.202

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.200';
5
+ const MANIFEST_BUILD_VERSION = '0.5.202';
6
6
 
7
7
  /* Manifest Data Sources - Appwrite Integration */
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  (function () {
4
4
 
5
- const MANIFEST_BUILD_VERSION = '0.5.200';
5
+ const MANIFEST_BUILD_VERSION = '0.5.202';
6
6
 
7
7
  /* Manifest Data Sources - Configuration */
8
8
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "manifest.appwrite.auth.js": "sha384-HMJmRXnvdDBWyuteXL+DTxWM2llSCdjl4EDamEI7iHNAVlqeOCE4GDTm8ZHipPRj",
3
- "manifest.appwrite.data.js": "sha384-UsRs96qc2+XlwkS1c9L4zvMdPILS+lMJkor1GKFa6JF/cnmDtV4mNROgC2ij5b8K",
3
+ "manifest.appwrite.data.js": "sha384-RVDH7r+lH+uw6OnE5kvgszmjJdlZjtbpYXc5+CZMtzo1gWViE0AG9AlpE+N3NvtH",
4
4
  "manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
5
5
  "manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
6
6
  "manifest.charts.js": "sha384-qQrjhWkIDi4oU5uQrpy8DdlMjY+gfiivBuX6mssNiFdkawgkVBvKneGgp+nd3PYJ",
@@ -11,7 +11,7 @@
11
11
  "manifest.combobox.js": "sha384-SN3XHumoebxcduFQqx5zt65/Cd10y8nuf9Gkco6UnsZ42sadRd+gvVLfWPdkkuPH",
12
12
  "manifest.components.js": "sha384-DLGSqCbnGkS87AWJ8GpKoAFP4nCosgC5SFSg6C10hH/nWu/MxI+0ntHlnFEfs++u",
13
13
  "manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
14
- "manifest.data.js": "sha384-4TOJw3VtnQBf+/jSw2bv6ol04jC0EeuuFSUec3XlqjYD8Mq6p+v4EXQkP1bqNYRs",
14
+ "manifest.data.js": "sha384-WNojlmE9Z0vDcw+MgVQdUhQKdSjbz6ghJlHoQaJcGdaK1XCNmvx8G7kvEfozpaVl",
15
15
  "manifest.datepicker.js": "sha384-8vTJYkLqqvgXgm1w1becuaRR/jUEpiLBjBJ6RsRbUr+ZkypvspD6EsssuDrX4SQq",
16
16
  "manifest.defer.js": "sha384-wXa60M2OHigi5rBurXQ7Oa8eyr5WTKs7EUn2GOru62KMdfs/LDyNegxCc9MNJFSe",
17
17
  "manifest.device.js": "sha384-g+txmrEszYtuOvRelTp/c1wSNR2AtllVI9rx5NPPD7DzhVUnMNughonZykv2xlBW",
@@ -28,14 +28,14 @@
28
28
  "manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
29
29
  "manifest.status.js": "sha384-nwvUSbT+gpRMqhYx6MeBYswUMH72rY92mjgxv0vrSG7Ht7l83XYpEB6fCTbXjjfK",
30
30
  "manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
31
- "manifest.sw.js": "sha384-SEt2P8mI4qgtddDmBD1d1RK963MsfwsSBU2bNIcobIqwqJp+G0IQXvDSPoM5VJvU",
31
+ "manifest.sw.js": "sha384-zUBmvVs8MVFHnt/sNWQJ16vWTaLZUJc6egsmhU4EVpvYLvOqWo28KmusamAO/rfi",
32
32
  "manifest.tabs.js": "sha384-OIIcyaQnGS0eNYk4zgAFEDboNYect7THvUd9D0V6nqCeDOxQcoiqLrBEmmWVTTet",
33
33
  "manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
34
34
  "manifest.text.edit.js": "sha384-pfhc4IPKNJokj6ldlgD+KwGLN4UoM21CNeVf2sVq/34X1Un2PUhEuyTg5itmtsXS",
35
35
  "manifest.toasts.js": "sha384-/OV32LLMJl0Iw8NoNQJ+5lgntLxjIJq/YNj5JAKS/+nUhVx4MMB9h1FOqP7zuj2M",
36
36
  "manifest.tooltips.js": "sha384-uXVVQADl6pY2Pj9i/UaSclZN7dzbKhLkmevv7Ad0+wXR8LgqodALNFrc5jZJjlwm",
37
37
  "manifest.url.parameters.js": "sha384-J2aSVBOPsoqsbafHndrWLHEDpKb4AKJAoQnVmKA4gZh5P/8HHjFWHO/lkusmG84l",
38
- "manifest.utilities.js": "sha384-frvYhLP8Arx+smhzQr1nCvxuVfnjRhoG+ce8pI0H0iYqJwO7km1/3QLdBYt3uKol",
38
+ "manifest.utilities.js": "sha384-u8wB+Jf6SMVFSZs/Bbf15h4HpkKqWyqeri/xCCMgHbMqRu595Gu9wUBY5wafiJ87",
39
39
  "manifest.virtual.js": "sha384-YwwmAsZNddajnAkLhBWtrK8edHMJOhD7cJkQi3qmm5o1Thg0wbtDU0dsfrCHKTIQ",
40
- "manifest.js": "sha384-z6bjoNHfkJwD3bRcjChzuzM3y/3LrWVfc8nsApLtSXcshgJc8L4+Vz7XaV3MN6N8"
40
+ "manifest.js": "sha384-AmLBpm1v/K9B93ZBGNTje0ceJHA4qnlciTrPms0zjcGGRJV8f8wQ7Pcr+sOLO38w"
41
41
  }
package/lib/manifest.js CHANGED
@@ -187,6 +187,11 @@
187
187
  // Configuration
188
188
  const DEFAULT_VERSION = 'latest';
189
189
 
190
+ // The version the page booted with (data-version). Every later load —
191
+ // Manifest.loadPlugin(), usage sniffing — resolves against it, so a runtime
192
+ // load can't pull a second copy of the framework at another version.
193
+ let RESOLVED_VERSION = DEFAULT_VERSION;
194
+
190
195
  // CDN fallback chain (first-party first). Each origin serves the npm scheme
191
196
  // `<origin>/<pkg>@<version>/<path>`. Override order with `data-cdn`
192
197
  // (comma-separated origins).
@@ -298,7 +303,7 @@
298
303
  // candidate per CDN host, tried in order.
299
304
  let _pluginBase = null;
300
305
  function setPluginBase(b) { _pluginBase = b || null; }
301
- function getPluginUrlCandidates(pluginName, version = DEFAULT_VERSION) {
306
+ function getPluginUrlCandidates(pluginName, version = RESOLVED_VERSION) {
302
307
  // Hyphenated API name → dotted file name (`appwrite-auth` → appwrite.auth).
303
308
  const fileName = pluginName.replace(/-/g, '.');
304
309
  if (_pluginBase) {
@@ -307,7 +312,7 @@
307
312
  }
308
313
  return CDN_HOSTS.map(h => `${getBaseUrl(version, h)}/${hostFile(h, `manifest.${fileName}.min.js`)}`);
309
314
  }
310
- function getPluginUrl(pluginName, version = DEFAULT_VERSION) {
315
+ function getPluginUrl(pluginName, version = RESOLVED_VERSION) {
311
316
  return getPluginUrlCandidates(pluginName, version)[0];
312
317
  }
313
318
 
@@ -388,14 +393,8 @@
388
393
  return false;
389
394
  }
390
395
 
391
- // One fetch per URL: concurrent callers share the first call's promise
392
- const inflightScripts = new Map();
393
-
394
396
  function injectScript(url) {
395
- const shared = inflightScripts.get(url);
396
- if (shared) return shared;
397
-
398
- const promise = new Promise((resolve, reject) => {
397
+ return new Promise((resolve, reject) => {
399
398
  // Same src already in the DOM (author tag, prerendered HTML, second loader run)
400
399
  const existing = document.querySelector(`script[src="${url}"]`);
401
400
  if (existing) {
@@ -418,16 +417,12 @@
418
417
  script.onerror = () => { script.removeAttribute('data-mnfst-loading'); script.remove(); reject(new Error(`Failed to load ${url}`)); };
419
418
  document.head.appendChild(script);
420
419
  });
421
-
422
- inflightScripts.set(url, promise);
423
- promise.then(() => inflightScripts.delete(url), () => inflightScripts.delete(url)); // dedupe only while in flight
424
- return promise;
425
420
  }
426
421
 
427
422
  // Load a plugin, falling through the CDN chain on error. A fallback insert
428
423
  // lands after already-inserted scripts, so strict cross-plugin execution
429
424
  // order is traded for availability in the (already degraded) fallback case.
430
- async function addScript(pluginName, version = DEFAULT_VERSION) {
425
+ async function fetchPluginScript(pluginName, version) {
431
426
  const urls = getPluginUrlCandidates(pluginName, version);
432
427
  let lastErr = null;
433
428
  for (const url of urls) {
@@ -441,6 +436,26 @@
441
436
  throw lastErr || new Error(`Failed to load ${pluginName}`);
442
437
  }
443
438
 
439
+ // One execution per plugin per page. injectScript dedupes by URL, which two
440
+ // versions of the same plugin slip past — and a second copy of a plugin that
441
+ // owns page-level state (utilities' style element and its order observer)
442
+ // fights the first. A failed load is forgotten so a retry can still run.
443
+ const pluginLoads = new Map();
444
+
445
+ async function addScript(pluginName, version = RESOLVED_VERSION) {
446
+ const prior = pluginLoads.get(pluginName);
447
+ if (prior) {
448
+ if (prior.version !== version) {
449
+ console.warn(`[Manifest Loader] ${pluginName} already loaded at ${prior.version} — ignoring request for ${version}`);
450
+ }
451
+ return prior.promise;
452
+ }
453
+ const promise = fetchPluginScript(pluginName, version);
454
+ pluginLoads.set(pluginName, { version, promise });
455
+ promise.catch(() => pluginLoads.delete(pluginName));
456
+ return promise;
457
+ }
458
+
444
459
  // Resolve plugin dependencies (auto-inject required dependencies)
445
460
  function resolveDependencies(pluginList) {
446
461
  const resolved = [];
@@ -636,7 +651,7 @@
636
651
  }
637
652
 
638
653
  // Load custom Tailwind CDN script, falling through the CDN chain on error
639
- async function loadTailwind(version = DEFAULT_VERSION) {
654
+ async function loadTailwind(version = RESOLVED_VERSION) {
640
655
  const urls = CDN_HOSTS.map(h => `${getBaseUrl(version, h)}/${hostFile(h, 'manifest.tailwind.min.js')}`);
641
656
  let lastErr = null;
642
657
  for (const url of urls) {
@@ -652,7 +667,7 @@
652
667
 
653
668
  // Expose API
654
669
  window.Manifest = {
655
- loadPlugin: function (pluginName, version = DEFAULT_VERSION) {
670
+ loadPlugin: function (pluginName, version = RESOLVED_VERSION) {
656
671
  const allPlugins = [...AVAILABLE_PLUGINS, ...APPWRITE_PLUGINS, ...AUTHORING_PLUGINS, 'payments', 'chat', 'device'];
657
672
  if (!allPlugins.includes(pluginName)) {
658
673
  console.warn(`[Manifest Loader] Unknown plugin: ${pluginName}`);
@@ -780,6 +795,7 @@
780
795
 
781
796
  // Parse config and load plugins
782
797
  const config = parseDataAttributes();
798
+ if (config && config.version) RESOLVED_VERSION = config.version;
783
799
  if (config && config.pluginBase) setPluginBase(config.pluginBase);
784
800
  if (config && config.cdn) setCdnHosts(config.cdn);
785
801
  armServiceWorker(config);
@@ -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.200';
19
+ const BUILD_VERSION = '0.5.202';
20
20
  const CACHE_PREFIX = 'mnfst-sw:';
21
21
  const META_CACHE = CACHE_PREFIX + 'meta';
22
22
  const SWR_CAP = 200;
@@ -1488,9 +1488,8 @@ TailwindCompiler.prototype.scanStaticClasses = async function () {
1488
1488
 
1489
1489
  // Extract classes from HTML content
1490
1490
  TailwindCompiler.prototype.extractClassesFromHTML = function (html, classSet) {
1491
- // Plain class attributes only — the leading boundary excludes Alpine's
1492
- // :class / x-bind:class bindings (JS expressions, not token lists)
1493
- const classRegex = /(?:^|[\s"'`>/])(?:[a-zA-Z][\w.-]*-)?class=["']([^"']+)["']/g;
1491
+ // Match class attributes: class="..." or class='...'
1492
+ const classRegex = /class=["']([^"']+)["']/g;
1494
1493
  let match;
1495
1494
 
1496
1495
  while ((match = classRegex.exec(html)) !== null) {
@@ -1701,8 +1700,11 @@ TailwindCompiler.prototype.fetchThemeContent = async function () {
1701
1700
  TailwindCompiler.prototype.extractThemeVariables = function (cssText) {
1702
1701
  const variables = new Map();
1703
1702
 
1704
- // Extract ALL CSS custom properties from ANY declaration block
1705
- const varRegex = /--([\w-]+):\s*([^;]+);/g;
1703
+ // Extract ALL CSS custom properties from ANY declaration block. Terminator
1704
+ // is a lookahead (`;` or `}`) rather than a consumed `;` so the last
1705
+ // declaration in a block still matches when the author omits the
1706
+ // trailing semicolon (valid CSS, e.g. `:root{--x:1rem}`).
1707
+ const varRegex = /--([\w-]+):\s*([^;}]+)(?=[;}])/g;
1706
1708
 
1707
1709
  let varMatch;
1708
1710
  while ((varMatch = varRegex.exec(cssText)) !== null) {
@@ -3831,8 +3833,13 @@ function injectTailwindVariants() {
3831
3833
  }
3832
3834
  injectTailwindVariants();
3833
3835
 
3834
- // Initialize immediately without waiting for DOMContentLoaded
3835
- const compiler = new TailwindCompiler();
3836
+ // One compiler per page: a second copy would own a rival #manifest-styles and
3837
+ // the two order observers would re-append their own style to <head> forever.
3838
+ // A compiler whose style element left the document is stale, so it is rebuilt.
3839
+ const existingCompiler = window.ManifestUtilities;
3840
+ const compiler = (existingCompiler && existingCompiler.styleElement && existingCompiler.styleElement.isConnected)
3841
+ ? existingCompiler
3842
+ : new TailwindCompiler();
3836
3843
 
3837
3844
  // Expose utilities compiler for optional integration
3838
3845
  window.ManifestUtilities = compiler;
@@ -3856,11 +3863,14 @@ if ('PerformanceObserver' in window) {
3856
3863
  }
3857
3864
 
3858
3865
  // Recompile on DOMContentLoaded for late-added elements
3859
- document.addEventListener('DOMContentLoaded', () => {
3860
- if (!compiler.usesStaticPrerenderUtilities && !compiler.isCompiling) {
3861
- compiler.compile();
3862
- }
3863
- });
3866
+ if (!compiler.__mnfstDomReadyBound) {
3867
+ compiler.__mnfstDomReadyBound = true;
3868
+ document.addEventListener('DOMContentLoaded', () => {
3869
+ if (!compiler.usesStaticPrerenderUtilities && !compiler.isCompiling) {
3870
+ compiler.compile();
3871
+ }
3872
+ });
3873
+ }
3864
3874
 
3865
3875
 
3866
3876
 
@@ -1,5 +1,25 @@
1
1
  /* manifest.utilities.node.mjs — built from scripts/utilities/ (DOM-free) */
2
2
 
3
+ if (typeof globalThis.window === 'undefined') globalThis.window = globalThis;
4
+ if (typeof globalThis.document === 'undefined') {
5
+ const inertElement = () => ({ style: {}, textContent: '', classList: { add(){}, remove(){}, contains: () => false }, setAttribute(){}, appendChild(){}, insertBefore(){} });
6
+ globalThis.document = {
7
+ documentElement: { outerHTML: '' },
8
+ head: { firstChild: null, lastElementChild: null, innerHTML: '', appendChild(){}, insertBefore(){} },
9
+ querySelectorAll: () => [],
10
+ querySelector: () => null,
11
+ getElementById: () => null,
12
+ getElementsByTagName: () => [],
13
+ createElement: inertElement,
14
+ addEventListener(){},
15
+ styleSheets: []
16
+ };
17
+ }
18
+ if (typeof globalThis.getComputedStyle === 'undefined') globalThis.getComputedStyle = () => ({ getPropertyValue: () => '' });
19
+ if (typeof globalThis.localStorage === 'undefined') globalThis.localStorage = { getItem: () => null, setItem(){}, removeItem(){} };
20
+ if (typeof globalThis.performance === 'undefined') globalThis.performance = { now: () => Date.now() };
21
+ if (typeof globalThis.requestAnimationFrame === 'undefined') globalThis.requestAnimationFrame = (cb) => setTimeout(cb, 0);
22
+
3
23
  // Utility generators
4
24
  // Functions that generate CSS utilities from CSS variable suffixes
5
25
 
@@ -902,9 +922,8 @@ TailwindCompiler.prototype.scanStaticClasses = async function () {
902
922
 
903
923
  // Extract classes from HTML content
904
924
  TailwindCompiler.prototype.extractClassesFromHTML = function (html, classSet) {
905
- // Plain class attributes only — the leading boundary excludes Alpine's
906
- // :class / x-bind:class bindings (JS expressions, not token lists)
907
- const classRegex = /(?:^|[\s"'`>/])(?:[a-zA-Z][\w.-]*-)?class=["']([^"']+)["']/g;
925
+ // Match class attributes: class="..." or class='...'
926
+ const classRegex = /class=["']([^"']+)["']/g;
908
927
  let match;
909
928
 
910
929
  while ((match = classRegex.exec(html)) !== null) {
@@ -1115,8 +1134,11 @@ TailwindCompiler.prototype.fetchThemeContent = async function () {
1115
1134
  TailwindCompiler.prototype.extractThemeVariables = function (cssText) {
1116
1135
  const variables = new Map();
1117
1136
 
1118
- // Extract ALL CSS custom properties from ANY declaration block
1119
- const varRegex = /--([\w-]+):\s*([^;]+);/g;
1137
+ // Extract ALL CSS custom properties from ANY declaration block. Terminator
1138
+ // is a lookahead (`;` or `}`) rather than a consumed `;` so the last
1139
+ // declaration in a block still matches when the author omits the
1140
+ // trailing semicolon (valid CSS, e.g. `:root{--x:1rem}`).
1141
+ const varRegex = /--([\w-]+):\s*([^;}]+)(?=[;}])/g;
1120
1142
 
1121
1143
  let varMatch;
1122
1144
  while ((varMatch = varRegex.exec(cssText)) !== null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst",
3
- "version": "0.5.200",
3
+ "version": "0.5.202",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "templates/starter",