mnfst 0.5.38 → 0.5.40

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.
@@ -91,6 +91,12 @@ function initializeIconPlugin() {
91
91
  const iconValue = expression;
92
92
  if (!iconValue) return;
93
93
 
94
+ // Prerender (or static HTML) already inlined an Iconify SVG; leave it alone. Otherwise Alpine
95
+ // evaluates stale expressions like `module.icon` from templating and throws ReferenceError.
96
+ if (el.querySelector('svg[data-icon]')) {
97
+ return;
98
+ }
99
+
94
100
  // Check if it's a raw icon name (should contain a colon for icon format like 'lucide:house')
95
101
  const isRawIconName = iconValue.includes(':') &&
96
102
  !iconValue.includes("'") &&
@@ -394,8 +394,20 @@ window.ManifestRoutingNavigation = {
394
394
 
395
395
  // Router visibility
396
396
 
397
+ function isPrerenderedStaticMPA() {
398
+ try {
399
+ return document.querySelector('meta[name="manifest:prerendered"][content="1"]') !== null;
400
+ } catch (e) {
401
+ return false;
402
+ }
403
+ }
404
+
397
405
  // Process visibility for all elements with x-route
398
406
  function processRouteVisibility(normalizedPath) {
407
+ // Static prerender output already contains only this route's sections; x-cloak + toggling here
408
+ // causes a visible flash (content → hidden via x-cloak → shown when Alpine boots).
409
+ if (isPrerenderedStaticMPA()) return;
410
+
399
411
  const routeElements = document.querySelectorAll('[x-route]');
400
412
 
401
413
  // First pass: collect all defined routes (excluding !* and other negative conditions)
@@ -511,6 +523,7 @@ function processRouteVisibility(normalizedPath) {
511
523
 
512
524
  // Add x-cloak to route elements that don't have it
513
525
  function addXCloakToRouteElements() {
526
+ if (isPrerenderedStaticMPA()) return;
514
527
  const routeElements = document.querySelectorAll('[x-route]:not([x-cloak])');
515
528
  routeElements.forEach(element => {
516
529
  element.setAttribute('x-cloak', '');
@@ -529,11 +542,13 @@ function initializeVisibility() {
529
542
 
530
543
  // Listen for route changes
531
544
  window.addEventListener('manifest:route-change', (event) => {
545
+ if (isPrerenderedStaticMPA()) return;
532
546
  processRouteVisibility(event.detail.normalizedPath);
533
547
  });
534
548
 
535
549
  // Listen for component processing to ensure visibility is applied after components load
536
550
  window.addEventListener('manifest:components-processed', () => {
551
+ if (isPrerenderedStaticMPA()) return;
537
552
  // Add x-cloak to any new route elements
538
553
  addXCloakToRouteElements();
539
554
 
@@ -559,11 +574,23 @@ if (document.readyState === 'loading') {
559
574
  // Export visibility interface
560
575
  window.ManifestRoutingVisibility = {
561
576
  initialize: initializeVisibility,
562
- processRouteVisibility
577
+ processRouteVisibility,
578
+ isPrerenderedStaticMPA
563
579
  };
564
580
 
565
581
  // Router head
566
582
 
583
+ function isPrerenderedStaticMPA() {
584
+ try {
585
+ if (window.ManifestRoutingVisibility && typeof window.ManifestRoutingVisibility.isPrerenderedStaticMPA === 'function') {
586
+ return window.ManifestRoutingVisibility.isPrerenderedStaticMPA();
587
+ }
588
+ return document.querySelector('meta[name="manifest:prerendered"][content="1"]') !== null;
589
+ } catch (e) {
590
+ return false;
591
+ }
592
+ }
593
+
567
594
  // Track injected head content to prevent duplicates
568
595
  const injectedHeadContent = new Set();
569
596
 
@@ -713,6 +740,7 @@ function processElementHeadContent(element, normalizedPath) {
713
740
 
714
741
  // Process all head content in the DOM
715
742
  function processAllHeadContent(normalizedPath) {
743
+ if (isPrerenderedStaticMPA()) return;
716
744
 
717
745
  // Find all elements with head templates
718
746
  const elementsWithHead = document.querySelectorAll('template[data-head]');
@@ -791,6 +819,7 @@ function initializeHeadContent() {
791
819
  function processHeadContentAfterComponentsReady() {
792
820
  // Process initial head content after a longer delay to let components settle
793
821
  setTimeout(() => {
822
+ if (isPrerenderedStaticMPA()) return;
794
823
  const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
795
824
  const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
796
825
 
@@ -810,6 +839,7 @@ function initializeHeadContent() {
810
839
 
811
840
  // Function to process head content immediately (for projects without components)
812
841
  function processHeadContentImmediately() {
842
+ if (isPrerenderedStaticMPA()) return;
813
843
  const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
814
844
  const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
815
845
  processAllHeadContent(normalizedPath);
@@ -843,6 +873,7 @@ function initializeHeadContent() {
843
873
 
844
874
  // Wait a bit for components to settle after route change
845
875
  setTimeout(() => {
876
+ if (isPrerenderedStaticMPA()) return;
846
877
  // Process head content immediately to catch components before they're reverted
847
878
  const currentPath = window.ManifestRoutingNavigation?.getCurrentRoute() ?? window.location.pathname;
848
879
  const normalizedPath = currentPath === '/' ? '/' : currentPath.replace(/^\/|\/$/g, '');
@@ -411,9 +411,60 @@ function createVariantGroups() {
411
411
 
412
412
  /* Manifest Utilities */
413
413
 
414
+ /** True when prerender wrote utilities to prerender.utilities.css — skip runtime #utility-styles generation. */
415
+ function manifestPageUsesStaticPrerenderUtilities() {
416
+ if (typeof document === 'undefined') return false;
417
+ try {
418
+ if (!document.querySelector('meta[name="manifest:prerendered"][content="1"]')) return false;
419
+ for (const link of document.querySelectorAll('link[rel="stylesheet"][href]')) {
420
+ if ((link.getAttribute('href') || '').toLowerCase().includes('prerender.utilities.css')) {
421
+ return true;
422
+ }
423
+ }
424
+ } catch (e) {
425
+ return false;
426
+ }
427
+ return false;
428
+ }
429
+
414
430
  // Browser runtime compiler
415
431
  class TailwindCompiler {
416
432
  constructor(options = {}) {
433
+ this.usesStaticPrerenderUtilities = manifestPageUsesStaticPrerenderUtilities();
434
+
435
+ // Prerender already emitted utility CSS; do not inject duplicate #utility-styles / observers.
436
+ if (this.usesStaticPrerenderUtilities) {
437
+ this.debug = options.debug === true;
438
+ this.startTime = performance.now();
439
+ this.options = {
440
+ rootSelector: options.rootSelector || ':root',
441
+ themeSelector: options.themeSelector || '@theme',
442
+ debounceTime: options.debounceTime || 50,
443
+ maxCacheAge: options.maxCacheAge || 24 * 60 * 60 * 1000,
444
+ debug: options.debug !== false,
445
+ ...options
446
+ };
447
+ this.criticalStyleElement = null;
448
+ this.styleElement = null;
449
+ this.tailwindLink = null;
450
+ this.observer = null;
451
+ this.isCompiling = false;
452
+ this.compileTimeout = null;
453
+ this.cache = new Map();
454
+ this.hasInitialized = true;
455
+ // manifest.code.js (and others) may still register ignore rules; mirror full constructor defaults.
456
+ this.ignoredClassPatterns = [
457
+ /^hljs/, /^language-/, /^copy$/, /^copied$/, /^lines$/, /^selected$/
458
+ ];
459
+ this.ignoredElementSelectors = [
460
+ 'pre', 'code', 'x-code', 'x-code-group'
461
+ ];
462
+ this.significantChangeSelectors = [
463
+ '[data-component]', '[x-data]'
464
+ ];
465
+ return;
466
+ }
467
+
417
468
  this.debug = options.debug === true;
418
469
  this.startTime = performance.now();
419
470
 
@@ -559,6 +610,9 @@ class TailwindCompiler {
559
610
 
560
611
  // Public API for other plugins to configure behavior
561
612
  addIgnoredClassPattern(pattern) {
613
+ if (!Array.isArray(this.ignoredClassPatterns)) {
614
+ this.ignoredClassPatterns = [];
615
+ }
562
616
  if (pattern instanceof RegExp) {
563
617
  this.ignoredClassPatterns.push(pattern);
564
618
  } else if (typeof pattern === 'string') {
@@ -567,12 +621,18 @@ class TailwindCompiler {
567
621
  }
568
622
 
569
623
  addIgnoredElementSelector(selector) {
624
+ if (!Array.isArray(this.ignoredElementSelectors)) {
625
+ this.ignoredElementSelectors = [];
626
+ }
570
627
  if (typeof selector === 'string') {
571
628
  this.ignoredElementSelectors.push(selector);
572
629
  }
573
630
  }
574
631
 
575
632
  addSignificantChangeSelector(selector) {
633
+ if (!Array.isArray(this.significantChangeSelectors)) {
634
+ this.significantChangeSelectors = [];
635
+ }
576
636
  if (typeof selector === 'string') {
577
637
  this.significantChangeSelectors.push(selector);
578
638
  }
@@ -924,6 +984,7 @@ TailwindCompiler.prototype.addCriticalBlockingStylesSync = function () {
924
984
 
925
985
  // Generate synchronous utilities (fallback method)
926
986
  TailwindCompiler.prototype.generateSynchronousUtilities = function () {
987
+ if (this.usesStaticPrerenderUtilities) return;
927
988
  try {
928
989
  // Always try to generate, even if cache exists, to catch any new classes
929
990
  const hasExistingStyles = this.styleElement.textContent && this.styleElement.textContent.trim();
@@ -2975,6 +3036,8 @@ TailwindCompiler.prototype.filterCriticalUtilities = function(criticalText, laye
2975
3036
 
2976
3037
  // Main compilation method
2977
3038
  TailwindCompiler.prototype.compile = async function () {
3039
+ if (this.usesStaticPrerenderUtilities) return;
3040
+
2978
3041
  const compileStart = performance.now();
2979
3042
 
2980
3043
  try {
@@ -3311,6 +3374,7 @@ TailwindCompiler.prototype.setupComponentLoadListener = function () {
3311
3374
 
3312
3375
  // Start processing with initial compilation and observer setup
3313
3376
  TailwindCompiler.prototype.startProcessing = async function () {
3377
+ if (this.usesStaticPrerenderUtilities) return;
3314
3378
  try {
3315
3379
  // Start initial compilation immediately
3316
3380
  const initialCompilation = this.compile();
@@ -3397,7 +3461,7 @@ if ('PerformanceObserver' in window) {
3397
3461
 
3398
3462
  // Also handle DOMContentLoaded for any elements that might be added later
3399
3463
  document.addEventListener('DOMContentLoaded', () => {
3400
- if (!compiler.isCompiling) {
3464
+ if (!compiler.usesStaticPrerenderUtilities && !compiler.isCompiling) {
3401
3465
  compiler.compile();
3402
3466
  }
3403
3467
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst",
3
- "version": "0.5.38",
3
+ "version": "0.5.40",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "templates/starter",
@@ -62,4 +62,4 @@
62
62
  "bugs": {
63
63
  "url": "https://github.com/andrewmatlock/manifest/issues"
64
64
  }
65
- }
65
+ }