mnfst 0.5.203 → 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 +51 -17
- package/lib/manifest.sw.js +1 -1
- package/lib/manifest.utilities.js +84 -37
- package/lib/manifest.utilities.node.mjs +219 -13
- 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
|
@@ -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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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 = [];
|
|
@@ -635,8 +650,26 @@
|
|
|
635
650
|
};
|
|
636
651
|
}
|
|
637
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
|
+
|
|
638
671
|
// Load custom Tailwind CDN script, falling through the CDN chain on error
|
|
639
|
-
async function loadTailwind(version =
|
|
672
|
+
async function loadTailwind(version = RESOLVED_VERSION) {
|
|
640
673
|
const urls = CDN_HOSTS.map(h => `${getBaseUrl(version, h)}/${hostFile(h, 'manifest.tailwind.min.js')}`);
|
|
641
674
|
let lastErr = null;
|
|
642
675
|
for (const url of urls) {
|
|
@@ -652,7 +685,7 @@
|
|
|
652
685
|
|
|
653
686
|
// Expose API
|
|
654
687
|
window.Manifest = {
|
|
655
|
-
loadPlugin: function (pluginName, version =
|
|
688
|
+
loadPlugin: function (pluginName, version = RESOLVED_VERSION) {
|
|
656
689
|
const allPlugins = [...AVAILABLE_PLUGINS, ...APPWRITE_PLUGINS, ...AUTHORING_PLUGINS, 'payments', 'chat', 'device'];
|
|
657
690
|
if (!allPlugins.includes(pluginName)) {
|
|
658
691
|
console.warn(`[Manifest Loader] Unknown plugin: ${pluginName}`);
|
|
@@ -780,6 +813,7 @@
|
|
|
780
813
|
|
|
781
814
|
// Parse config and load plugins
|
|
782
815
|
const config = parseDataAttributes();
|
|
816
|
+
if (config && config.version) RESOLVED_VERSION = config.version;
|
|
783
817
|
if (config && config.pluginBase) setPluginBase(config.pluginBase);
|
|
784
818
|
if (config && config.cdn) setCdnHosts(config.cdn);
|
|
785
819
|
armServiceWorker(config);
|
|
@@ -890,7 +924,7 @@
|
|
|
890
924
|
console.warn(`[Manifest Loader] Failed to load plugin ${pluginName}:`, error);
|
|
891
925
|
});
|
|
892
926
|
});
|
|
893
|
-
if (config.tailwind) {
|
|
927
|
+
if (config.tailwind && !staticUtilitiesFullyCovered()) {
|
|
894
928
|
pluginPromises.push(loadTailwind(config.version).catch(() => { }));
|
|
895
929
|
}
|
|
896
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();
|
|
@@ -1488,9 +1490,8 @@ TailwindCompiler.prototype.scanStaticClasses = async function () {
|
|
|
1488
1490
|
|
|
1489
1491
|
// Extract classes from HTML content
|
|
1490
1492
|
TailwindCompiler.prototype.extractClassesFromHTML = function (html, classSet) {
|
|
1491
|
-
//
|
|
1492
|
-
|
|
1493
|
-
const classRegex = /(?:^|[\s"'`>/])(?:[a-zA-Z][\w.-]*-)?class=["']([^"']+)["']/g;
|
|
1493
|
+
// Match class attributes: class="..." or class='...'
|
|
1494
|
+
const classRegex = /class=["']([^"']+)["']/g;
|
|
1494
1495
|
let match;
|
|
1495
1496
|
|
|
1496
1497
|
while ((match = classRegex.exec(html)) !== null) {
|
|
@@ -1701,8 +1702,11 @@ TailwindCompiler.prototype.fetchThemeContent = async function () {
|
|
|
1701
1702
|
TailwindCompiler.prototype.extractThemeVariables = function (cssText) {
|
|
1702
1703
|
const variables = new Map();
|
|
1703
1704
|
|
|
1704
|
-
// Extract ALL CSS custom properties from ANY declaration block
|
|
1705
|
-
|
|
1705
|
+
// Extract ALL CSS custom properties from ANY declaration block. Terminator
|
|
1706
|
+
// is a lookahead (`;` or `}`) rather than a consumed `;` so the last
|
|
1707
|
+
// declaration in a block still matches when the author omits the
|
|
1708
|
+
// trailing semicolon (valid CSS, e.g. `:root{--x:1rem}`).
|
|
1709
|
+
const varRegex = /--([\w-]+):\s*([^;}]+)(?=[;}])/g;
|
|
1706
1710
|
|
|
1707
1711
|
let varMatch;
|
|
1708
1712
|
while ((varMatch = varRegex.exec(cssText)) !== null) {
|
|
@@ -3180,6 +3184,11 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
3180
3184
|
if (!this.hasScannedStatic) {
|
|
3181
3185
|
await this.scanStaticClasses();
|
|
3182
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
|
+
|
|
3183
3192
|
// Fetch CSS content once for initial compilation
|
|
3184
3193
|
const themeCss = await this.fetchThemeContent();
|
|
3185
3194
|
if (themeCss) {
|
|
@@ -3429,40 +3438,70 @@ TailwindCompiler.prototype.classNamesFromCssText = function (cssText) {
|
|
|
3429
3438
|
return classSet;
|
|
3430
3439
|
};
|
|
3431
3440
|
|
|
3432
|
-
//
|
|
3433
|
-
//
|
|
3434
|
-
// (cross-origin,
|
|
3435
|
-
//
|
|
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".
|
|
3436
3470
|
TailwindCompiler.prototype.detectStaticUtilitiesSheet = function () {
|
|
3437
3471
|
this.staticUtilitiesCoveredClasses = null;
|
|
3438
3472
|
const el = this.findStaticUtilitiesElement();
|
|
3439
|
-
if (!el) return;
|
|
3473
|
+
if (!el) return Promise.resolve();
|
|
3440
3474
|
|
|
3441
3475
|
if (el.tagName === 'STYLE') {
|
|
3442
3476
|
this.staticUtilitiesCoveredClasses = this.classNamesFromCssText(el.textContent || '');
|
|
3443
|
-
return;
|
|
3477
|
+
return Promise.resolve();
|
|
3444
3478
|
}
|
|
3445
3479
|
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
const cssText = Array.from(rules).map(r => r.cssText).join('\n');
|
|
3451
|
-
this.staticUtilitiesCoveredClasses = this.classNamesFromCssText(cssText);
|
|
3452
|
-
return;
|
|
3453
|
-
}
|
|
3454
|
-
} catch (e) {
|
|
3455
|
-
// 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();
|
|
3456
3484
|
}
|
|
3457
3485
|
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
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
|
+
});
|
|
3466
3505
|
};
|
|
3467
3506
|
|
|
3468
3507
|
// Drop classes already covered by the static sheet before generating rules
|
|
@@ -3831,8 +3870,13 @@ function injectTailwindVariants() {
|
|
|
3831
3870
|
}
|
|
3832
3871
|
injectTailwindVariants();
|
|
3833
3872
|
|
|
3834
|
-
//
|
|
3835
|
-
|
|
3873
|
+
// One compiler per page: a second copy would own a rival #manifest-styles and
|
|
3874
|
+
// the two order observers would re-append their own style to <head> forever.
|
|
3875
|
+
// A compiler whose style element left the document is stale, so it is rebuilt.
|
|
3876
|
+
const existingCompiler = window.ManifestUtilities;
|
|
3877
|
+
const compiler = (existingCompiler && existingCompiler.styleElement && existingCompiler.styleElement.isConnected)
|
|
3878
|
+
? existingCompiler
|
|
3879
|
+
: new TailwindCompiler();
|
|
3836
3880
|
|
|
3837
3881
|
// Expose utilities compiler for optional integration
|
|
3838
3882
|
window.ManifestUtilities = compiler;
|
|
@@ -3856,11 +3900,14 @@ if ('PerformanceObserver' in window) {
|
|
|
3856
3900
|
}
|
|
3857
3901
|
|
|
3858
3902
|
// Recompile on DOMContentLoaded for late-added elements
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3903
|
+
if (!compiler.__mnfstDomReadyBound) {
|
|
3904
|
+
compiler.__mnfstDomReadyBound = true;
|
|
3905
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
3906
|
+
if (!compiler.usesStaticPrerenderUtilities && !compiler.isCompiling) {
|
|
3907
|
+
compiler.compile();
|
|
3908
|
+
}
|
|
3909
|
+
});
|
|
3910
|
+
}
|
|
3864
3911
|
|
|
3865
3912
|
|
|
3866
3913
|
|
|
@@ -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
|
|
|
@@ -556,8 +576,10 @@ class TailwindCompiler {
|
|
|
556
576
|
|
|
557
577
|
// Read any publish/render-provided static utilities sheet before the
|
|
558
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).
|
|
559
581
|
this.staticUtilitiesCoveredClasses = null;
|
|
560
|
-
this.detectStaticUtilitiesSheet();
|
|
582
|
+
this.staticUtilitiesReady = this.detectStaticUtilitiesSheet();
|
|
561
583
|
|
|
562
584
|
// Add critical styles IMMEDIATELY - don't wait for anything
|
|
563
585
|
this.addCriticalBlockingStylesSync();
|
|
@@ -902,9 +924,8 @@ TailwindCompiler.prototype.scanStaticClasses = async function () {
|
|
|
902
924
|
|
|
903
925
|
// Extract classes from HTML content
|
|
904
926
|
TailwindCompiler.prototype.extractClassesFromHTML = function (html, classSet) {
|
|
905
|
-
//
|
|
906
|
-
|
|
907
|
-
const classRegex = /(?:^|[\s"'`>/])(?:[a-zA-Z][\w.-]*-)?class=["']([^"']+)["']/g;
|
|
927
|
+
// Match class attributes: class="..." or class='...'
|
|
928
|
+
const classRegex = /class=["']([^"']+)["']/g;
|
|
908
929
|
let match;
|
|
909
930
|
|
|
910
931
|
while ((match = classRegex.exec(html)) !== null) {
|
|
@@ -1115,8 +1136,11 @@ TailwindCompiler.prototype.fetchThemeContent = async function () {
|
|
|
1115
1136
|
TailwindCompiler.prototype.extractThemeVariables = function (cssText) {
|
|
1116
1137
|
const variables = new Map();
|
|
1117
1138
|
|
|
1118
|
-
// Extract ALL CSS custom properties from ANY declaration block
|
|
1119
|
-
|
|
1139
|
+
// Extract ALL CSS custom properties from ANY declaration block. Terminator
|
|
1140
|
+
// is a lookahead (`;` or `}`) rather than a consumed `;` so the last
|
|
1141
|
+
// declaration in a block still matches when the author omits the
|
|
1142
|
+
// trailing semicolon (valid CSS, e.g. `:root{--x:1rem}`).
|
|
1143
|
+
const varRegex = /--([\w-]+):\s*([^;}]+)(?=[;}])/g;
|
|
1120
1144
|
|
|
1121
1145
|
let varMatch;
|
|
1122
1146
|
while ((varMatch = varRegex.exec(cssText)) !== null) {
|
|
@@ -2594,6 +2618,11 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
2594
2618
|
if (!this.hasScannedStatic) {
|
|
2595
2619
|
await this.scanStaticClasses();
|
|
2596
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
|
+
|
|
2597
2626
|
// Fetch CSS content once for initial compilation
|
|
2598
2627
|
const themeCss = await this.fetchThemeContent();
|
|
2599
2628
|
if (themeCss) {
|
|
@@ -2775,6 +2804,13 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
2775
2804
|
// buildUtilitiesNodeModule) with the DOM-free subset of the browser plugin's
|
|
2776
2805
|
// subscripts (generators, variants, main, helpers, compile) so this exports
|
|
2777
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.
|
|
2778
2814
|
|
|
2779
2815
|
/** A bare TailwindCompiler instance carrying only what the pure generation
|
|
2780
2816
|
* methods (generateUtilitiesFromVars, generateCustomUtilities, parseClassName,
|
|
@@ -2798,23 +2834,190 @@ function createNodeCompiler() {
|
|
|
2798
2834
|
return instance;
|
|
2799
2835
|
}
|
|
2800
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
|
+
|
|
2801
2980
|
/**
|
|
2802
|
-
* Compile the utility CSS the browser plugin
|
|
2803
|
-
*
|
|
2804
|
-
*
|
|
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.
|
|
2805
2989
|
* Deterministic for a given (classes, themeCss, baseCss) triple.
|
|
2806
2990
|
*
|
|
2807
|
-
*
|
|
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
|
|
2808
3010
|
* @returns {Promise<string>}
|
|
2809
3011
|
*/
|
|
2810
|
-
export async function compileUtilities({ classes = [], themeCss = '', baseCss = '' } = {}) {
|
|
3012
|
+
export async function compileUtilities({ classes = [], themeCss = '', baseCss = '', tailwind = null } = {}) {
|
|
2811
3013
|
const compiler = createNodeCompiler();
|
|
2812
3014
|
const cssText = [baseCss, themeCss].filter(Boolean).join('\n');
|
|
3015
|
+
const uniqueClasses = Array.from(new Set(classes));
|
|
2813
3016
|
|
|
2814
3017
|
const discovered = compiler.extractCustomUtilities(cssText);
|
|
2815
3018
|
for (const [name, value] of discovered) compiler.customUtilities.set(name, value);
|
|
2816
3019
|
|
|
2817
|
-
const usedData = { classes:
|
|
3020
|
+
const usedData = { classes: uniqueClasses, variableSuffixes: [] };
|
|
2818
3021
|
|
|
2819
3022
|
const varUtilities = compiler.generateUtilitiesFromVars(cssText, usedData);
|
|
2820
3023
|
const customUtilities = compiler.generateCustomUtilities(usedData);
|
|
@@ -2822,7 +3025,10 @@ export async function compileUtilities({ classes = [], themeCss = '', baseCss =
|
|
|
2822
3025
|
let allUtilities = [varUtilities, customUtilities].filter(Boolean).join('\n\n');
|
|
2823
3026
|
allUtilities = compiler.sortUtilities(allUtilities);
|
|
2824
3027
|
|
|
2825
|
-
|
|
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');
|
|
2826
3032
|
}
|
|
2827
3033
|
|
|
2828
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": [
|