mnfst 0.5.202 → 0.5.204
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.
- package/lib/manifest.appwrite.data.js +1 -1
- package/lib/manifest.data.js +1 -1
- package/lib/manifest.integrity.json +5 -5
- package/lib/manifest.js +19 -1
- package/lib/manifest.sw.js +1 -1
- package/lib/manifest.utilities.js +62 -25
- package/lib/manifest.utilities.node.mjs +192 -8
- package/package.json +4 -2
package/lib/manifest.data.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-HMJmRXnvdDBWyuteXL+DTxWM2llSCdjl4EDamEI7iHNAVlqeOCE4GDTm8ZHipPRj",
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-4mU2U/aADGu/axzp+8iGdn2Ckz0vpnPb6dLVkbkU+SN2MKE8Td8Ayj+jsIa4lnfg",
|
|
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-
|
|
14
|
+
"manifest.data.js": "sha384-xbpINo3TIpOj+PcdJ3bjNLFq+OFJWn7+F7RIRYOzrk9SJj9cmZpUfe5LLI+NS3j8",
|
|
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-
|
|
31
|
+
"manifest.sw.js": "sha384-8hvTjUEMILGzSsus1RfsHDgkpre+UFp7pr7vN0gCtw1fzTrvPauDokRuuoGur6pt",
|
|
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-
|
|
38
|
+
"manifest.utilities.js": "sha384-3PdKl/ARgpezheDE9thLyrN3sEuacROPmBALAuo/SKGHDHDBqQzXBD6ilvoMn95F",
|
|
39
39
|
"manifest.virtual.js": "sha384-YwwmAsZNddajnAkLhBWtrK8edHMJOhD7cJkQi3qmm5o1Thg0wbtDU0dsfrCHKTIQ",
|
|
40
|
-
"manifest.js": "sha384-
|
|
40
|
+
"manifest.js": "sha384-jH0veyUdnBMoGwHxgUQ9Yjs0UneDMI/fYIsg1U58YPZwriKJ6Rv/aoA7RbLepoGa"
|
|
41
41
|
}
|
package/lib/manifest.js
CHANGED
|
@@ -650,6 +650,24 @@
|
|
|
650
650
|
};
|
|
651
651
|
}
|
|
652
652
|
|
|
653
|
+
// A publish/render bake stamps `data-mnfst-utilities-complete` on its
|
|
654
|
+
// `<style data-mnfst-utilities>` sheet once it has verified every class
|
|
655
|
+
// scanned from the page's own HTML got a rule (Manifest's + the baked
|
|
656
|
+
// Tailwind pass — see compileUtilities in manifest.utilities.node.mjs).
|
|
657
|
+
// Only the inline `<style>` case is checked: it's synchronous, so this can
|
|
658
|
+
// run before deciding whether to fetch the Tailwind engine at all — a
|
|
659
|
+
// `<link>` sheet would need an async load first, so it's left alone
|
|
660
|
+
// (fail open: Tailwind still loads). No flag, no attribute, any read
|
|
661
|
+
// error → false, so this never skips loading the engine speculatively.
|
|
662
|
+
function staticUtilitiesFullyCovered() {
|
|
663
|
+
try {
|
|
664
|
+
const el = document.querySelector('style[data-mnfst-utilities][data-mnfst-utilities-complete]');
|
|
665
|
+
return !!el;
|
|
666
|
+
} catch (e) {
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
653
671
|
// Load custom Tailwind CDN script, falling through the CDN chain on error
|
|
654
672
|
async function loadTailwind(version = RESOLVED_VERSION) {
|
|
655
673
|
const urls = CDN_HOSTS.map(h => `${getBaseUrl(version, h)}/${hostFile(h, 'manifest.tailwind.min.js')}`);
|
|
@@ -906,7 +924,7 @@
|
|
|
906
924
|
console.warn(`[Manifest Loader] Failed to load plugin ${pluginName}:`, error);
|
|
907
925
|
});
|
|
908
926
|
});
|
|
909
|
-
if (config.tailwind) {
|
|
927
|
+
if (config.tailwind && !staticUtilitiesFullyCovered()) {
|
|
910
928
|
pluginPromises.push(loadTailwind(config.version).catch(() => { }));
|
|
911
929
|
}
|
|
912
930
|
await Promise.all(pluginPromises);
|
package/lib/manifest.sw.js
CHANGED
|
@@ -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.
|
|
19
|
+
const BUILD_VERSION = '0.5.204';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
const SWR_CAP = 200;
|
|
@@ -558,8 +558,10 @@ class TailwindCompiler {
|
|
|
558
558
|
|
|
559
559
|
// Read any publish/render-provided static utilities sheet before the
|
|
560
560
|
// first compile — its classes are skipped rather than regenerated.
|
|
561
|
+
// Fails open (never "everything covered") until this resolves —
|
|
562
|
+
// compile()'s first run awaits it, capped at 2s (see static.js).
|
|
561
563
|
this.staticUtilitiesCoveredClasses = null;
|
|
562
|
-
this.detectStaticUtilitiesSheet();
|
|
564
|
+
this.staticUtilitiesReady = this.detectStaticUtilitiesSheet();
|
|
563
565
|
|
|
564
566
|
// Add critical styles IMMEDIATELY - don't wait for anything
|
|
565
567
|
this.addCriticalBlockingStylesSync();
|
|
@@ -3182,6 +3184,11 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
3182
3184
|
if (!this.hasScannedStatic) {
|
|
3183
3185
|
await this.scanStaticClasses();
|
|
3184
3186
|
|
|
3187
|
+
// Wait for the static utilities sheet's covered-class read to
|
|
3188
|
+
// settle (capped at 2s in detectStaticUtilitiesSheet) so this
|
|
3189
|
+
// first compile decision isn't a guess — see static.js.
|
|
3190
|
+
if (this.staticUtilitiesReady) await this.staticUtilitiesReady;
|
|
3191
|
+
|
|
3185
3192
|
// Fetch CSS content once for initial compilation
|
|
3186
3193
|
const themeCss = await this.fetchThemeContent();
|
|
3187
3194
|
if (themeCss) {
|
|
@@ -3431,40 +3438,70 @@ TailwindCompiler.prototype.classNamesFromCssText = function (cssText) {
|
|
|
3431
3438
|
return classSet;
|
|
3432
3439
|
};
|
|
3433
3440
|
|
|
3434
|
-
//
|
|
3435
|
-
//
|
|
3436
|
-
// (cross-origin,
|
|
3437
|
-
//
|
|
3441
|
+
// Attempt a synchronous CSSOM read of the static link's rules. Returns a Set
|
|
3442
|
+
// of covered classes, or null when nothing could be read — a security error
|
|
3443
|
+
// (cross-origin), an exception, a missing sheet, or zero rules (the link
|
|
3444
|
+
// hasn't finished loading, or its sheet is genuinely empty). null is never
|
|
3445
|
+
// distinguished from "empty": both fail open in filterStaticallyCoveredClasses
|
|
3446
|
+
// / stripCoveredRulesFromCss, and neither is ever treated as "everything
|
|
3447
|
+
// covered".
|
|
3448
|
+
TailwindCompiler.prototype.readStaticUtilitiesRules = function (el) {
|
|
3449
|
+
try {
|
|
3450
|
+
const sheet = Array.from(document.styleSheets).find(s => s.ownerNode === el);
|
|
3451
|
+
const rules = sheet && sheet.cssRules;
|
|
3452
|
+
if (rules && rules.length > 0) {
|
|
3453
|
+
const cssText = Array.from(rules).map(r => r.cssText).join('\n');
|
|
3454
|
+
return this.classNamesFromCssText(cssText);
|
|
3455
|
+
}
|
|
3456
|
+
} catch (e) {
|
|
3457
|
+
// Cross-origin, or not yet parsed.
|
|
3458
|
+
}
|
|
3459
|
+
return null;
|
|
3460
|
+
};
|
|
3461
|
+
|
|
3462
|
+
// Read the static sheet's covered classes once per page load. `<style>` and
|
|
3463
|
+
// an already-loaded `<link>` resolve synchronously. A `<link>` that hasn't
|
|
3464
|
+
// finished loading (or whose sheet can't be read yet) is awaited via its
|
|
3465
|
+
// `load`/`error` event, capped at 2s, then re-read once more; the caller
|
|
3466
|
+
// (compile()'s first run) awaits the returned promise so the very first
|
|
3467
|
+
// compile decision sees an accurate covered set rather than a guess. Fails
|
|
3468
|
+
// open the whole time — staticUtilitiesCoveredClasses stays null (nothing
|
|
3469
|
+
// covered) until a read actually succeeds, never cached as "covered".
|
|
3438
3470
|
TailwindCompiler.prototype.detectStaticUtilitiesSheet = function () {
|
|
3439
3471
|
this.staticUtilitiesCoveredClasses = null;
|
|
3440
3472
|
const el = this.findStaticUtilitiesElement();
|
|
3441
|
-
if (!el) return;
|
|
3473
|
+
if (!el) return Promise.resolve();
|
|
3442
3474
|
|
|
3443
3475
|
if (el.tagName === 'STYLE') {
|
|
3444
3476
|
this.staticUtilitiesCoveredClasses = this.classNamesFromCssText(el.textContent || '');
|
|
3445
|
-
return;
|
|
3477
|
+
return Promise.resolve();
|
|
3446
3478
|
}
|
|
3447
3479
|
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
const cssText = Array.from(rules).map(r => r.cssText).join('\n');
|
|
3453
|
-
this.staticUtilitiesCoveredClasses = this.classNamesFromCssText(cssText);
|
|
3454
|
-
return;
|
|
3455
|
-
}
|
|
3456
|
-
} catch (e) {
|
|
3457
|
-
// Cross-origin (or not yet parsed) — fall through to fetch.
|
|
3480
|
+
const covered = this.readStaticUtilitiesRules(el);
|
|
3481
|
+
if (covered) {
|
|
3482
|
+
this.staticUtilitiesCoveredClasses = covered;
|
|
3483
|
+
return Promise.resolve();
|
|
3458
3484
|
}
|
|
3459
3485
|
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3486
|
+
return new Promise((resolve) => {
|
|
3487
|
+
let settled = false;
|
|
3488
|
+
const finish = () => {
|
|
3489
|
+
if (settled) return;
|
|
3490
|
+
settled = true;
|
|
3491
|
+
clearTimeout(timer);
|
|
3492
|
+
el.removeEventListener('load', onLoad);
|
|
3493
|
+
el.removeEventListener('error', onError);
|
|
3494
|
+
// staticUtilitiesCoveredClasses stays null (fail open) if this
|
|
3495
|
+
// still can't be read — e.g. a cross-origin sheet without CORS.
|
|
3496
|
+
this.staticUtilitiesCoveredClasses = this.readStaticUtilitiesRules(el);
|
|
3497
|
+
resolve();
|
|
3498
|
+
};
|
|
3499
|
+
const onLoad = () => finish();
|
|
3500
|
+
const onError = () => finish();
|
|
3501
|
+
const timer = setTimeout(finish, 2000);
|
|
3502
|
+
el.addEventListener('load', onLoad, { once: true });
|
|
3503
|
+
el.addEventListener('error', onError, { once: true });
|
|
3504
|
+
});
|
|
3468
3505
|
};
|
|
3469
3506
|
|
|
3470
3507
|
// Drop classes already covered by the static sheet before generating rules
|
|
@@ -576,8 +576,10 @@ class TailwindCompiler {
|
|
|
576
576
|
|
|
577
577
|
// Read any publish/render-provided static utilities sheet before the
|
|
578
578
|
// first compile — its classes are skipped rather than regenerated.
|
|
579
|
+
// Fails open (never "everything covered") until this resolves —
|
|
580
|
+
// compile()'s first run awaits it, capped at 2s (see static.js).
|
|
579
581
|
this.staticUtilitiesCoveredClasses = null;
|
|
580
|
-
this.detectStaticUtilitiesSheet();
|
|
582
|
+
this.staticUtilitiesReady = this.detectStaticUtilitiesSheet();
|
|
581
583
|
|
|
582
584
|
// Add critical styles IMMEDIATELY - don't wait for anything
|
|
583
585
|
this.addCriticalBlockingStylesSync();
|
|
@@ -2616,6 +2618,11 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
2616
2618
|
if (!this.hasScannedStatic) {
|
|
2617
2619
|
await this.scanStaticClasses();
|
|
2618
2620
|
|
|
2621
|
+
// Wait for the static utilities sheet's covered-class read to
|
|
2622
|
+
// settle (capped at 2s in detectStaticUtilitiesSheet) so this
|
|
2623
|
+
// first compile decision isn't a guess — see static.js.
|
|
2624
|
+
if (this.staticUtilitiesReady) await this.staticUtilitiesReady;
|
|
2625
|
+
|
|
2619
2626
|
// Fetch CSS content once for initial compilation
|
|
2620
2627
|
const themeCss = await this.fetchThemeContent();
|
|
2621
2628
|
if (themeCss) {
|
|
@@ -2797,6 +2804,13 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
2797
2804
|
// buildUtilitiesNodeModule) with the DOM-free subset of the browser plugin's
|
|
2798
2805
|
// subscripts (generators, variants, main, helpers, compile) so this exports
|
|
2799
2806
|
// the exact same generation logic the browser JIT runs, with no document.
|
|
2807
|
+
//
|
|
2808
|
+
// compileUtilities() also runs the real `tailwindcss` engine (see the
|
|
2809
|
+
// "Tailwind engine pass" section below) — a real, lazily-imported dependency
|
|
2810
|
+
// used only there, via Node's fs/require by default, or via the `tailwind`
|
|
2811
|
+
// option for runtimes (e.g. Workers) that bundle the engine/CSS themselves
|
|
2812
|
+
// instead; every other export in this file stays dependency-free and
|
|
2813
|
+
// DOM-free as before.
|
|
2800
2814
|
|
|
2801
2815
|
/** A bare TailwindCompiler instance carrying only what the pure generation
|
|
2802
2816
|
* methods (generateUtilitiesFromVars, generateCustomUtilities, parseClassName,
|
|
@@ -2820,23 +2834,190 @@ function createNodeCompiler() {
|
|
|
2820
2834
|
return instance;
|
|
2821
2835
|
}
|
|
2822
2836
|
|
|
2837
|
+
// --- Tailwind engine pass -------------------------------------------------
|
|
2838
|
+
// Bakes the plain Tailwind-style utilities (flex, gap-2, rounded-full,
|
|
2839
|
+
// w-[37px], md:, hover:, …) that the runtime's bundled Tailwind engine
|
|
2840
|
+
// (lib/manifest.tailwind.js — a Tailwind v4 "Play CDN" browser build) would
|
|
2841
|
+
// otherwise generate live. Uses the real `tailwindcss` package's compile()/
|
|
2842
|
+
// build() — the same core compiler that browser build wraps, not a fork —
|
|
2843
|
+
// which is pure JS with no native binding and no DOM requirement.
|
|
2844
|
+
//
|
|
2845
|
+
// The browser engine reads only `<style type="text/tailwindcss">` tags
|
|
2846
|
+
// (default: `@import "tailwindcss";` plus whatever such tags are on the
|
|
2847
|
+
// page) and derives its candidates from `document.querySelectorAll("[class]")`
|
|
2848
|
+
// — it does not see Manifest's theme vars, so this mirrors that: no bridging
|
|
2849
|
+
// of `themeCss` into Tailwind's `@theme`. The custom variants below mirror
|
|
2850
|
+
// injectTailwindVariants() in manifest.utilities.init.js — keep both in sync.
|
|
2851
|
+
const TAILWIND_CUSTOM_VARIANTS = [
|
|
2852
|
+
'@custom-variant touch (@media (pointer: coarse));',
|
|
2853
|
+
'@custom-variant cursor (@media (pointer: fine) and (hover: hover));',
|
|
2854
|
+
'@custom-variant pointer (@media (any-pointer: fine));',
|
|
2855
|
+
'@custom-variant mac (&:where([data-os="macos"] *));',
|
|
2856
|
+
'@custom-variant windows (&:where([data-os="windows"] *));',
|
|
2857
|
+
'@custom-variant linux (&:where([data-os="linux"] *));',
|
|
2858
|
+
'@custom-variant ios (&:where([data-os="ios"] *));',
|
|
2859
|
+
'@custom-variant android (&:where([data-os="android"] *));',
|
|
2860
|
+
'@custom-variant apple (&:where([data-os="macos"] *, [data-os="ios"] *));',
|
|
2861
|
+
'@custom-variant online (&:where([data-online="true"] *));',
|
|
2862
|
+
'@custom-variant offline (&:where([data-online="false"] *));',
|
|
2863
|
+
'@custom-variant standalone (&:where([data-standalone] *));',
|
|
2864
|
+
'@custom-variant native (&:where([data-native] *));',
|
|
2865
|
+
'@custom-variant web (&:where(html:not([data-native]) *));'
|
|
2866
|
+
].join('\n');
|
|
2867
|
+
|
|
2868
|
+
/** Balanced-brace extraction of a top-level `@layer <name> { ... }` body —
|
|
2869
|
+
* the compiled CSS nests braces (media queries, `&:hover`), so a regex can't
|
|
2870
|
+
* safely find the matching close brace. Returns '' when the layer is absent. */
|
|
2871
|
+
function extractLayerBody(css, layerName) {
|
|
2872
|
+
const marker = `@layer ${layerName} {`;
|
|
2873
|
+
const start = css.indexOf(marker);
|
|
2874
|
+
if (start === -1) return '';
|
|
2875
|
+
let depth = 1;
|
|
2876
|
+
let i = start + marker.length;
|
|
2877
|
+
const bodyStart = i;
|
|
2878
|
+
for (; i < css.length && depth > 0; i++) {
|
|
2879
|
+
if (css[i] === '{') depth++;
|
|
2880
|
+
else if (css[i] === '}') depth--;
|
|
2881
|
+
}
|
|
2882
|
+
return css.slice(bodyStart, i - 1).trim();
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
let _tailwindEnginePromise = null;
|
|
2886
|
+
/** Lazily loads tailwindcss's compile() plus its theme.css/utilities.css text
|
|
2887
|
+
* — the expensive, reusable I/O (dynamic import, two fs reads). Cached
|
|
2888
|
+
* across calls; resolves to null (fail open) when the package or Node's
|
|
2889
|
+
* fs/require aren't available in this runtime (e.g. a bare Workers isolate),
|
|
2890
|
+
* so callers degrade to Manifest-only utilities rather than throwing.
|
|
2891
|
+
*
|
|
2892
|
+
* `injected`, when given, skips the fs/require path entirely: a caller that
|
|
2893
|
+
* already has the engine and CSS in hand (a bundler-built Workers isolate,
|
|
2894
|
+
* which has no `fs`/`require` — see the `tailwind` param on compileUtilities)
|
|
2895
|
+
* supplies `{ engine, themeCss, utilitiesCss }`, where `engine` is the
|
|
2896
|
+
* imported `tailwindcss` module namespace (its `compile` export is used).
|
|
2897
|
+
* Not cached on `_tailwindEnginePromise`: cheap (no I/O, just wrapping
|
|
2898
|
+
* already-resident values) and the caller owns the instance's lifetime.
|
|
2899
|
+
*
|
|
2900
|
+
* Deliberately skips tailwindcss/preflight.css: the browser engine's own
|
|
2901
|
+
* default `@import "tailwindcss"` — see `jo`/`Io` in lib/manifest.tailwind.js
|
|
2902
|
+
* — wires up only theme.css and utilities.css and leaves preflight empty, so
|
|
2903
|
+
* matching it means never importing preflight here either (Manifest ships
|
|
2904
|
+
* its own reset; the runtime never asks Tailwind for one). */
|
|
2905
|
+
function loadTailwindEngine(injected) {
|
|
2906
|
+
if (injected) {
|
|
2907
|
+
const { engine, themeCss, utilitiesCss } = injected;
|
|
2908
|
+
if (!engine || typeof engine.compile !== 'function' || !themeCss || !utilitiesCss) {
|
|
2909
|
+
return Promise.resolve(null);
|
|
2910
|
+
}
|
|
2911
|
+
return Promise.resolve({ compile: engine.compile, base: '/', themeCss, utilitiesCss });
|
|
2912
|
+
}
|
|
2913
|
+
if (_tailwindEnginePromise) return _tailwindEnginePromise;
|
|
2914
|
+
_tailwindEnginePromise = (async () => {
|
|
2915
|
+
try {
|
|
2916
|
+
const { compile } = await import('tailwindcss');
|
|
2917
|
+
const fs = await import('node:fs');
|
|
2918
|
+
const path = await import('node:path');
|
|
2919
|
+
const { createRequire } = await import('node:module');
|
|
2920
|
+
const req = createRequire(import.meta.url);
|
|
2921
|
+
const themePath = req.resolve('tailwindcss/theme.css');
|
|
2922
|
+
const utilitiesPath = req.resolve('tailwindcss/utilities.css');
|
|
2923
|
+
const themeCss = fs.readFileSync(themePath, 'utf8');
|
|
2924
|
+
const utilitiesCss = fs.readFileSync(utilitiesPath, 'utf8');
|
|
2925
|
+
const base = path.dirname(themePath);
|
|
2926
|
+
return { compile, base, themeCss, utilitiesCss };
|
|
2927
|
+
} catch (e) {
|
|
2928
|
+
return null;
|
|
2929
|
+
}
|
|
2930
|
+
})();
|
|
2931
|
+
return _tailwindEnginePromise;
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
/** Runs the real Tailwind engine over exactly `classes`, returning its
|
|
2935
|
+
* (tree-shaken, used-only) `theme` and `utilities` layer bodies as a single
|
|
2936
|
+
* CSS chunk. Returns '' when Tailwind can't be loaded here, or produced no
|
|
2937
|
+
* utility rules for these classes (the default theme's font/spacing tokens
|
|
2938
|
+
* would otherwise show up even for a class list with no real Tailwind match
|
|
2939
|
+
* — e.g. Manifest's own `.row`/`.col` — since they're always defined; only
|
|
2940
|
+
* emit the theme chunk alongside actual utility output).
|
|
2941
|
+
*
|
|
2942
|
+
* `injected` is passed straight through to loadTailwindEngine — see there.
|
|
2943
|
+
*
|
|
2944
|
+
* A fresh compiler is built per call (~a few ms — see loadTailwindEngine for
|
|
2945
|
+
* the cached, reusable part): tailwindcss's compiler.build() is an
|
|
2946
|
+
* incremental/watch-mode API that accumulates every candidate it has ever
|
|
2947
|
+
* seen, so reusing one compiler across calls with different class lists
|
|
2948
|
+
* would leak earlier calls' classes into later output — the same reason the
|
|
2949
|
+
* browser engine tracks its own "already seen" set (see the header comment)
|
|
2950
|
+
* before calling build(). */
|
|
2951
|
+
async function compileTailwindPass(classes, injected) {
|
|
2952
|
+
if (!classes.length) return '';
|
|
2953
|
+
const engine = await loadTailwindEngine(injected);
|
|
2954
|
+
if (!engine) return '';
|
|
2955
|
+
try {
|
|
2956
|
+
const { compile, base, themeCss, utilitiesCss } = engine;
|
|
2957
|
+
const input = `@layer theme, base, components, utilities;\n@import "tailwindcss/theme" layer(theme);\n@import "tailwindcss/utilities" layer(utilities);\n${TAILWIND_CUSTOM_VARIANTS}\n`;
|
|
2958
|
+
const compiler = await compile(input, {
|
|
2959
|
+
base,
|
|
2960
|
+
loadStylesheet: async (id) => {
|
|
2961
|
+
if (id === 'tailwindcss/theme') return { base, content: themeCss };
|
|
2962
|
+
if (id === 'tailwindcss/utilities') return { base, content: utilitiesCss };
|
|
2963
|
+
throw new Error(`manifest utilities: cannot load "${id}" for Tailwind bake`);
|
|
2964
|
+
},
|
|
2965
|
+
loadModule: async () => { throw new Error('manifest utilities: Tailwind plugins unsupported in bake'); }
|
|
2966
|
+
});
|
|
2967
|
+
const css = compiler.build(classes);
|
|
2968
|
+
const utilities = extractLayerBody(css, 'utilities');
|
|
2969
|
+
if (!utilities) return '';
|
|
2970
|
+
const theme = extractLayerBody(css, 'theme');
|
|
2971
|
+
const parts = [];
|
|
2972
|
+
if (theme) parts.push(`@layer theme {\n${theme}\n}`);
|
|
2973
|
+
parts.push(`@layer utilities {\n${utilities}\n}`);
|
|
2974
|
+
return parts.join('\n\n');
|
|
2975
|
+
} catch (e) {
|
|
2976
|
+
return '';
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2823
2980
|
/**
|
|
2824
|
-
* Compile the utility CSS the browser plugin
|
|
2825
|
-
*
|
|
2826
|
-
*
|
|
2981
|
+
* Compile the utility CSS the browser plugin (Manifest's own generators) plus
|
|
2982
|
+
* the framework's bundled Tailwind engine would together produce for exactly
|
|
2983
|
+
* `classes`. Manifest side: variants, theme-variable-driven utilities
|
|
2984
|
+
* (generateUtilitiesFromVars) and custom utilities (generateCustomUtilities)
|
|
2985
|
+
* discovered in `themeCss`/`baseCss`. Tailwind side: whatever real Tailwind
|
|
2986
|
+
* utilities (`flex`, `gap-2`, `rounded-full`, arbitrary values like
|
|
2987
|
+
* `w-[37px]`, and their variants) the class list resolves to, via the actual
|
|
2988
|
+
* `tailwindcss` compiler (see compileTailwindPass above) — not a fork.
|
|
2827
2989
|
* Deterministic for a given (classes, themeCss, baseCss) triple.
|
|
2828
2990
|
*
|
|
2829
|
-
*
|
|
2991
|
+
* `baseCss` should include the framework's own utility CSS (lib/manifest.css)
|
|
2992
|
+
* whenever the caller isn't already loading it: the browser plugin's compile()
|
|
2993
|
+
* finds it for free via discoverCssFiles() scanning the page's own
|
|
2994
|
+
* stylesheets, so generateCustomUtilities() recognises Manifest's semantic
|
|
2995
|
+
* utilities (.row, .col, .center, …) and bakes variants like `md:row` or
|
|
2996
|
+
* `hover:col-wrap`. Without it those variants are silently skipped here —
|
|
2997
|
+
* scripts/utilities-static.mjs loads it automatically for this reason.
|
|
2998
|
+
*
|
|
2999
|
+
* `tailwind`, when given, is passed to the Tailwind engine pass instead of
|
|
3000
|
+
* its default lazy `fs`/`require` load — `{ engine, themeCss, utilitiesCss }`
|
|
3001
|
+
* where `engine` is the imported `tailwindcss` module namespace and the two
|
|
3002
|
+
* CSS strings are the contents of `tailwindcss/theme.css` and
|
|
3003
|
+
* `tailwindcss/utilities.css`. For runtimes that can statically import
|
|
3004
|
+
* `tailwindcss` and inline its CSS at bundle time but have no `fs`/`require`
|
|
3005
|
+
* to read them from node_modules at runtime (e.g. a Cloudflare Workers
|
|
3006
|
+
* isolate) — see loadTailwindEngine. Omit it (the default) to keep using the
|
|
3007
|
+
* Node/CLI fs-based load.
|
|
3008
|
+
*
|
|
3009
|
+
* @param {{classes?: string[], themeCss?: string, baseCss?: string, tailwind?: {engine: object, themeCss: string, utilitiesCss: string}}} options
|
|
2830
3010
|
* @returns {Promise<string>}
|
|
2831
3011
|
*/
|
|
2832
|
-
export async function compileUtilities({ classes = [], themeCss = '', baseCss = '' } = {}) {
|
|
3012
|
+
export async function compileUtilities({ classes = [], themeCss = '', baseCss = '', tailwind = null } = {}) {
|
|
2833
3013
|
const compiler = createNodeCompiler();
|
|
2834
3014
|
const cssText = [baseCss, themeCss].filter(Boolean).join('\n');
|
|
3015
|
+
const uniqueClasses = Array.from(new Set(classes));
|
|
2835
3016
|
|
|
2836
3017
|
const discovered = compiler.extractCustomUtilities(cssText);
|
|
2837
3018
|
for (const [name, value] of discovered) compiler.customUtilities.set(name, value);
|
|
2838
3019
|
|
|
2839
|
-
const usedData = { classes:
|
|
3020
|
+
const usedData = { classes: uniqueClasses, variableSuffixes: [] };
|
|
2840
3021
|
|
|
2841
3022
|
const varUtilities = compiler.generateUtilitiesFromVars(cssText, usedData);
|
|
2842
3023
|
const customUtilities = compiler.generateCustomUtilities(usedData);
|
|
@@ -2844,7 +3025,10 @@ export async function compileUtilities({ classes = [], themeCss = '', baseCss =
|
|
|
2844
3025
|
let allUtilities = [varUtilities, customUtilities].filter(Boolean).join('\n\n');
|
|
2845
3026
|
allUtilities = compiler.sortUtilities(allUtilities);
|
|
2846
3027
|
|
|
2847
|
-
|
|
3028
|
+
const manifestLayer = allUtilities ? `@layer utilities {\n${allUtilities}\n}` : '';
|
|
3029
|
+
const tailwindLayer = await compileTailwindPass(uniqueClasses, tailwind);
|
|
3030
|
+
|
|
3031
|
+
return [manifestLayer, tailwindLayer].filter(Boolean).join('\n\n');
|
|
2848
3032
|
}
|
|
2849
3033
|
|
|
2850
3034
|
// `class:token=` (per-class conditional binding) and the `:class="..."`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnfst",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.204",
|
|
4
4
|
"private": false,
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"templates/starter",
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
"README.md",
|
|
21
21
|
"LICENSE"
|
|
22
22
|
],
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"tailwindcss": "^4.2.4"
|
|
25
|
+
},
|
|
23
26
|
"scripts": {
|
|
24
27
|
"clean": "rimraf src/styles/manifest.css src/styles/manifest.min.css src/styles/manifest.theme.css src/styles/manifest.code.css src/styles/manifest.code.min.css lib",
|
|
25
28
|
"build": "cd src && node scripts/build.mjs",
|
|
@@ -58,7 +61,6 @@
|
|
|
58
61
|
"puppeteer": "^24.15.0",
|
|
59
62
|
"rimraf": "^5.0.0",
|
|
60
63
|
"rollup": "^4.24.2",
|
|
61
|
-
"tailwindcss": "^4.2.4",
|
|
62
64
|
"vitest": "^4.1.2"
|
|
63
65
|
},
|
|
64
66
|
"keywords": [
|