mnfst 0.5.199-next.4 → 0.5.199
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 +6 -6
- package/lib/manifest.js +11 -1
- package/lib/manifest.localization.js +11 -7
- package/lib/manifest.sw.js +1 -1
- package/lib/manifest.utilities.js +204 -7
- package/lib/manifest.utilities.node.mjs +2870 -0
- package/package.json +1 -1
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-ETPZTFqMOrmrriXrTAZqJljFmwfs316c4C2GEqNs295HdyYu7oZN8BDTLG7Bmotj",
|
|
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-AApJ6UR3+3DpNbMaMmIBL7BpT/HwIEJaY3yYWLo19ToT20QnhgImWBLLMaCgd4hU",
|
|
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",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"manifest.edit.js": "sha384-oLsrH7/UkJ/KEl3UO77hexcf2rYCGgzXZd0fe2EMq3hKRE7aUqLiEnLJhSV7zTaY",
|
|
20
20
|
"manifest.export.js": "sha384-HCy3n6ifrcAGIyzTRgZ5JIRvSX9q9/8ykMKRSbt1QTnhXz6PgYlV0AE2N2Yi2re+",
|
|
21
21
|
"manifest.icons.js": "sha384-kKOINpX70YzNO3FvkV6umrmO3f0KIu0DNbwB+ej55a7y/lhU7v/myQtXL0bwCTbt",
|
|
22
|
-
"manifest.localization.js": "sha384-
|
|
22
|
+
"manifest.localization.js": "sha384-EImsIw8Z3l13V5eH9ZJF/yfsOfIvR1oPRNSArANkPji7V8O3IRf6zMwsNiAGj3Hk",
|
|
23
23
|
"manifest.markdown.js": "sha384-HFE2VwBRX5vhDGQ3c8XgZ10Y5ENkXxHzgX9DjmIEffqLoUDbnJYNk3TFWT9k3e+f",
|
|
24
24
|
"manifest.native.js": "sha384-g+txmrEszYtuOvRelTp/c1wSNR2AtllVI9rx5NPPD7DzhVUnMNughonZykv2xlBW",
|
|
25
25
|
"manifest.payments.js": "sha384-8pofk2zhxtapPMpwnFyTelPMrYhShNhDCE722uQh/EYFvZFuPLmSdgunqsarVQjv",
|
|
@@ -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-ogkuzlKwgmBIH08csCz37WQdUMUeTwrOJcGTVNXw0aPzubapYLMMOYT2XHlvXMAh",
|
|
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-frvYhLP8Arx+smhzQr1nCvxuVfnjRhoG+ce8pI0H0iYqJwO7km1/3QLdBYt3uKol",
|
|
39
39
|
"manifest.virtual.js": "sha384-YwwmAsZNddajnAkLhBWtrK8edHMJOhD7cJkQi3qmm5o1Thg0wbtDU0dsfrCHKTIQ",
|
|
40
|
-
"manifest.js": "sha384
|
|
40
|
+
"manifest.js": "sha384-z6bjoNHfkJwD3bRcjChzuzM3y/3LrWVfc8nsApLtSXcshgJc8L4+Vz7XaV3MN6N8"
|
|
41
41
|
}
|
package/lib/manifest.js
CHANGED
|
@@ -388,8 +388,14 @@
|
|
|
388
388
|
return false;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
+
// One fetch per URL: concurrent callers share the first call's promise
|
|
392
|
+
const inflightScripts = new Map();
|
|
393
|
+
|
|
391
394
|
function injectScript(url) {
|
|
392
|
-
|
|
395
|
+
const shared = inflightScripts.get(url);
|
|
396
|
+
if (shared) return shared;
|
|
397
|
+
|
|
398
|
+
const promise = new Promise((resolve, reject) => {
|
|
393
399
|
// Same src already in the DOM (author tag, prerendered HTML, second loader run)
|
|
394
400
|
const existing = document.querySelector(`script[src="${url}"]`);
|
|
395
401
|
if (existing) {
|
|
@@ -412,6 +418,10 @@
|
|
|
412
418
|
script.onerror = () => { script.removeAttribute('data-mnfst-loading'); script.remove(); reject(new Error(`Failed to load ${url}`)); };
|
|
413
419
|
document.head.appendChild(script);
|
|
414
420
|
});
|
|
421
|
+
|
|
422
|
+
inflightScripts.set(url, promise);
|
|
423
|
+
promise.then(() => inflightScripts.delete(url), () => inflightScripts.delete(url)); // dedupe only while in flight
|
|
424
|
+
return promise;
|
|
415
425
|
}
|
|
416
426
|
|
|
417
427
|
// Load a plugin, falling through the CDN chain on error. A fallback insert
|
|
@@ -260,15 +260,19 @@ function initializeLocalizationPlugin() {
|
|
|
260
260
|
|
|
261
261
|
try {
|
|
262
262
|
let manifest = window.__manifestLoaded || window.ManifestComponentsRegistry?.manifest;
|
|
263
|
-
// A partially-seeded global can be truthy yet lack `data` —
|
|
264
|
-
//
|
|
263
|
+
// A partially-seeded global can be truthy yet lack `data` — await the
|
|
264
|
+
// shared in-flight fetch (or start one, one request per boot) so locale
|
|
265
|
+
// detection sees every source.
|
|
265
266
|
if (!manifest || !manifest.data) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
267
|
+
if (window.__manifestPromise) manifest = await window.__manifestPromise.catch(() => null);
|
|
268
|
+
if (!manifest || !manifest.data) {
|
|
269
|
+
const manifestUrl = (document.querySelector('link[rel="manifest"]')?.getAttribute('href')) || '/manifest.json';
|
|
270
|
+
window.__manifestPromise = fetch(manifestUrl).then(r => {
|
|
271
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}: ${r.statusText}`);
|
|
272
|
+
return r.json();
|
|
273
|
+
}).then(m => { window.ManifestDataConfig?.interpolateManifest?.(m); return m; });
|
|
274
|
+
manifest = await window.__manifestPromise;
|
|
270
275
|
}
|
|
271
|
-
manifest = await response.json();
|
|
272
276
|
}
|
|
273
277
|
|
|
274
278
|
if (!manifest || typeof manifest !== 'object') {
|
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.199
|
|
19
|
+
const BUILD_VERSION = '0.5.199';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
const SWR_CAP = 200;
|
|
@@ -471,6 +471,7 @@ class TailwindCompiler {
|
|
|
471
471
|
this.compileTimeout = null;
|
|
472
472
|
this.cache = new Map();
|
|
473
473
|
this.hasInitialized = true;
|
|
474
|
+
this.staticUtilitiesCoveredClasses = null;
|
|
474
475
|
// manifest.code.js (and others) may still register ignore rules; mirror full constructor defaults.
|
|
475
476
|
this.ignoredClassPatterns = [
|
|
476
477
|
/^hljs/, /^language-/, /^copy$/, /^copied$/, /^lines$/, /^selected$/
|
|
@@ -555,6 +556,11 @@ class TailwindCompiler {
|
|
|
555
556
|
// Cache for parsed class names (must be before addCriticalBlockingStylesSync)
|
|
556
557
|
this.classCache = new Map();
|
|
557
558
|
|
|
559
|
+
// Read any publish/render-provided static utilities sheet before the
|
|
560
|
+
// first compile — its classes are skipped rather than regenerated.
|
|
561
|
+
this.staticUtilitiesCoveredClasses = null;
|
|
562
|
+
this.detectStaticUtilitiesSheet();
|
|
563
|
+
|
|
558
564
|
// Add critical styles IMMEDIATELY - don't wait for anything
|
|
559
565
|
this.addCriticalBlockingStylesSync();
|
|
560
566
|
|
|
@@ -1194,7 +1200,11 @@ TailwindCompiler.prototype.loadAndApplyCache = function () {
|
|
|
1194
1200
|
|
|
1195
1201
|
if (cacheToUse && cacheToUse.css) {
|
|
1196
1202
|
const applyCacheStart = performance.now();
|
|
1197
|
-
|
|
1203
|
+
// The cached CSS may predate the static utilities sheet (or come
|
|
1204
|
+
// from a visitor without one) — strip anything it already covers
|
|
1205
|
+
// so we never re-emit those rules.
|
|
1206
|
+
const cachedCss = this.stripCoveredRulesFromCss(cacheToUse.css);
|
|
1207
|
+
this.styleElement.textContent = cachedCss;
|
|
1198
1208
|
this.ensureUtilityStylesLast();
|
|
1199
1209
|
this.scheduleEnsureUtilityStylesLast();
|
|
1200
1210
|
this.lastThemeHash = cacheToUse.themeHash;
|
|
@@ -1202,7 +1212,7 @@ TailwindCompiler.prototype.loadAndApplyCache = function () {
|
|
|
1202
1212
|
// Also apply cache to critical style element
|
|
1203
1213
|
// Extract utilities from @layer utilities block and apply directly (no @layer)
|
|
1204
1214
|
if (this.criticalStyleElement && !this.criticalStyleElement.textContent) {
|
|
1205
|
-
let criticalCss =
|
|
1215
|
+
let criticalCss = cachedCss;
|
|
1206
1216
|
// Remove @layer utilities wrapper if present
|
|
1207
1217
|
criticalCss = criticalCss.replace(/@layer\s+utilities\s*\{/g, '').replace(/\}\s*$/, '').trim();
|
|
1208
1218
|
if (criticalCss) {
|
|
@@ -1478,8 +1488,9 @@ TailwindCompiler.prototype.scanStaticClasses = async function () {
|
|
|
1478
1488
|
|
|
1479
1489
|
// Extract classes from HTML content
|
|
1480
1490
|
TailwindCompiler.prototype.extractClassesFromHTML = function (html, classSet) {
|
|
1481
|
-
//
|
|
1482
|
-
|
|
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;
|
|
1483
1494
|
let match;
|
|
1484
1495
|
|
|
1485
1496
|
while ((match = classRegex.exec(html)) !== null) {
|
|
@@ -1590,7 +1601,7 @@ TailwindCompiler.prototype.getUsedClasses = function () {
|
|
|
1590
1601
|
}
|
|
1591
1602
|
|
|
1592
1603
|
const result = {
|
|
1593
|
-
classes: Array.from(allClasses),
|
|
1604
|
+
classes: this.filterStaticallyCoveredClasses(Array.from(allClasses)),
|
|
1594
1605
|
variableSuffixes: Array.from(usedVariableSuffixes)
|
|
1595
1606
|
};
|
|
1596
1607
|
|
|
@@ -3185,9 +3196,10 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
3185
3196
|
this.currentThemeVars.set(name, value);
|
|
3186
3197
|
}
|
|
3187
3198
|
|
|
3188
|
-
// Generate utilities for all static classes
|
|
3199
|
+
// Generate utilities for all static classes (minus anything the
|
|
3200
|
+
// static utilities sheet already covers).
|
|
3189
3201
|
const staticUsedData = {
|
|
3190
|
-
classes: Array.from(this.staticClassCache),
|
|
3202
|
+
classes: this.filterStaticallyCoveredClasses(Array.from(this.staticClassCache)),
|
|
3191
3203
|
variableSuffixes: []
|
|
3192
3204
|
};
|
|
3193
3205
|
// Process static classes for variable suffixes
|
|
@@ -3345,6 +3357,191 @@ TailwindCompiler.prototype.compile = async function () {
|
|
|
3345
3357
|
|
|
3346
3358
|
|
|
3347
3359
|
|
|
3360
|
+
// Static utilities sheet detection
|
|
3361
|
+
// Publish/render may ship a precompiled utilities sheet — `<link rel="stylesheet"
|
|
3362
|
+
// data-mnfst-utilities>` or `<style data-mnfst-utilities>`. Read the classes it
|
|
3363
|
+
// already covers once so compile() only generates/patches what's left.
|
|
3364
|
+
|
|
3365
|
+
TailwindCompiler.prototype.findStaticUtilitiesElement = function () {
|
|
3366
|
+
try {
|
|
3367
|
+
return document.querySelector('link[rel="stylesheet"][data-mnfst-utilities], style[data-mnfst-utilities]');
|
|
3368
|
+
} catch (e) {
|
|
3369
|
+
return null;
|
|
3370
|
+
}
|
|
3371
|
+
};
|
|
3372
|
+
|
|
3373
|
+
// Top-level selector text only (skips declaration bodies, so values like
|
|
3374
|
+
// `margin: .5rem` can't be mistaken for a `.5` class selector).
|
|
3375
|
+
TailwindCompiler.prototype.extractSelectorsFromCssText = function (cssText) {
|
|
3376
|
+
const selectors = [];
|
|
3377
|
+
const len = cssText.length;
|
|
3378
|
+
let i = 0;
|
|
3379
|
+
while (i < len) {
|
|
3380
|
+
if (cssText[i] === '/' && cssText[i + 1] === '*') {
|
|
3381
|
+
const end = cssText.indexOf('*/', i + 2);
|
|
3382
|
+
i = end === -1 ? len : end + 2;
|
|
3383
|
+
continue;
|
|
3384
|
+
}
|
|
3385
|
+
if (cssText[i] === '@') {
|
|
3386
|
+
let j = i;
|
|
3387
|
+
while (j < len && cssText[j] !== '{' && cssText[j] !== ';') j++;
|
|
3388
|
+
if (j >= len || cssText[j] === ';') { i = j + 1; continue; }
|
|
3389
|
+
i = j + 1;
|
|
3390
|
+
let depth = 1;
|
|
3391
|
+
const start = i;
|
|
3392
|
+
while (i < len && depth > 0) {
|
|
3393
|
+
if (cssText[i] === '{') depth++;
|
|
3394
|
+
else if (cssText[i] === '}') depth--;
|
|
3395
|
+
i++;
|
|
3396
|
+
}
|
|
3397
|
+
selectors.push(...this.extractSelectorsFromCssText(cssText.slice(start, i - 1)));
|
|
3398
|
+
continue;
|
|
3399
|
+
}
|
|
3400
|
+
const selStart = i;
|
|
3401
|
+
while (i < len && cssText[i] !== '{' && cssText[i] !== '}') i++;
|
|
3402
|
+
if (i >= len || cssText[i] === '}') { i++; continue; }
|
|
3403
|
+
const selector = cssText.slice(selStart, i).trim();
|
|
3404
|
+
i++;
|
|
3405
|
+
let depth = 1;
|
|
3406
|
+
while (i < len && depth > 0) {
|
|
3407
|
+
if (cssText[i] === '{') depth++;
|
|
3408
|
+
else if (cssText[i] === '}') depth--;
|
|
3409
|
+
i++;
|
|
3410
|
+
}
|
|
3411
|
+
if (selector) selectors.push(selector);
|
|
3412
|
+
}
|
|
3413
|
+
return selectors;
|
|
3414
|
+
};
|
|
3415
|
+
|
|
3416
|
+
// Selectors escape every non-alphanumeric/hyphen char (see escapeClassName),
|
|
3417
|
+
// so `.hover\:bg-brand` unescapes back to the `hover:bg-brand` token form
|
|
3418
|
+
// used everywhere else (class attributes, usedClasses, parseClassName).
|
|
3419
|
+
TailwindCompiler.prototype.classNamesFromCssText = function (cssText) {
|
|
3420
|
+
const classSet = new Set();
|
|
3421
|
+
const classRe = /\.((?:\\.|[a-zA-Z0-9_-])+)/g;
|
|
3422
|
+
for (const selector of this.extractSelectorsFromCssText(cssText)) {
|
|
3423
|
+
let m;
|
|
3424
|
+
classRe.lastIndex = 0;
|
|
3425
|
+
while ((m = classRe.exec(selector)) !== null) {
|
|
3426
|
+
classSet.add(m[1].replace(/\\(.)/g, '$1'));
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
return classSet;
|
|
3430
|
+
};
|
|
3431
|
+
|
|
3432
|
+
// Read the static sheet's covered classes once. Same-origin `<link>`/`<style>`
|
|
3433
|
+
// rules are read synchronously via CSSOM; if the sheet isn't accessible yet
|
|
3434
|
+
// (cross-origin, or not finished loading) this falls back to fetching the
|
|
3435
|
+
// `href` as text and re-populating the covered set when it resolves.
|
|
3436
|
+
TailwindCompiler.prototype.detectStaticUtilitiesSheet = function () {
|
|
3437
|
+
this.staticUtilitiesCoveredClasses = null;
|
|
3438
|
+
const el = this.findStaticUtilitiesElement();
|
|
3439
|
+
if (!el) return;
|
|
3440
|
+
|
|
3441
|
+
if (el.tagName === 'STYLE') {
|
|
3442
|
+
this.staticUtilitiesCoveredClasses = this.classNamesFromCssText(el.textContent || '');
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
try {
|
|
3447
|
+
const sheet = Array.from(document.styleSheets).find(s => s.ownerNode === el);
|
|
3448
|
+
const rules = sheet && sheet.cssRules;
|
|
3449
|
+
if (rules && rules.length > 0) {
|
|
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.
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
// Placeholder so callers treat "not yet known" as "nothing covered" rather
|
|
3459
|
+
// than null, until the fetch below resolves and replaces it.
|
|
3460
|
+
this.staticUtilitiesCoveredClasses = new Set();
|
|
3461
|
+
const href = el.getAttribute('href');
|
|
3462
|
+
if (!href || typeof fetch !== 'function') return;
|
|
3463
|
+
fetch(href).then(r => (r.ok ? r.text() : '')).then(text => {
|
|
3464
|
+
if (text) this.staticUtilitiesCoveredClasses = this.classNamesFromCssText(text);
|
|
3465
|
+
}).catch(() => {});
|
|
3466
|
+
};
|
|
3467
|
+
|
|
3468
|
+
// Drop classes already covered by the static sheet before generating rules
|
|
3469
|
+
// for them again — the JIT should only ever patch what's left uncovered.
|
|
3470
|
+
TailwindCompiler.prototype.filterStaticallyCoveredClasses = function (classes) {
|
|
3471
|
+
const covered = this.staticUtilitiesCoveredClasses;
|
|
3472
|
+
if (!covered || covered.size === 0) return classes;
|
|
3473
|
+
return classes.filter(c => !covered.has(c));
|
|
3474
|
+
};
|
|
3475
|
+
|
|
3476
|
+
// The localStorage cache (manifest.utilities.cache.js) stores a full compiled
|
|
3477
|
+
// stylesheet from a previous visit — one that may predate the static sheet, or
|
|
3478
|
+
// come from a visitor without one. Re-applying it verbatim would re-emit every
|
|
3479
|
+
// rule the static sheet already covers, so strip those rules out first.
|
|
3480
|
+
TailwindCompiler.prototype.stripCoveredRulesFromCss = function (cssText) {
|
|
3481
|
+
const covered = this.staticUtilitiesCoveredClasses;
|
|
3482
|
+
if (!covered || covered.size === 0 || !cssText) return cssText;
|
|
3483
|
+
|
|
3484
|
+
const strip = (text) => {
|
|
3485
|
+
const out = [];
|
|
3486
|
+
const len = text.length;
|
|
3487
|
+
let i = 0;
|
|
3488
|
+
while (i < len) {
|
|
3489
|
+
if (text[i] === '/' && text[i + 1] === '*') {
|
|
3490
|
+
const end = text.indexOf('*/', i + 2);
|
|
3491
|
+
const stop = end === -1 ? len : end + 2;
|
|
3492
|
+
out.push(text.slice(i, stop));
|
|
3493
|
+
i = stop;
|
|
3494
|
+
continue;
|
|
3495
|
+
}
|
|
3496
|
+
if (text[i] === '@') {
|
|
3497
|
+
let j = i;
|
|
3498
|
+
while (j < len && text[j] !== '{' && text[j] !== ';') j++;
|
|
3499
|
+
if (j >= len || text[j] === ';') { out.push(text.slice(i, j + 1)); i = j + 1; continue; }
|
|
3500
|
+
const atHead = text.slice(i, j + 1);
|
|
3501
|
+
i = j + 1;
|
|
3502
|
+
let depth = 1;
|
|
3503
|
+
const start = i;
|
|
3504
|
+
while (i < len && depth > 0) {
|
|
3505
|
+
if (text[i] === '{') depth++;
|
|
3506
|
+
else if (text[i] === '}') depth--;
|
|
3507
|
+
i++;
|
|
3508
|
+
}
|
|
3509
|
+
out.push(`${atHead}${strip(text.slice(start, i - 1))}}`);
|
|
3510
|
+
continue;
|
|
3511
|
+
}
|
|
3512
|
+
const selStart = i;
|
|
3513
|
+
while (i < len && text[i] !== '{' && text[i] !== '}') i++;
|
|
3514
|
+
if (i >= len || text[i] === '}') { i++; continue; }
|
|
3515
|
+
const selector = text.slice(selStart, i).trim();
|
|
3516
|
+
const bodyStart = i;
|
|
3517
|
+
i++;
|
|
3518
|
+
let depth = 1;
|
|
3519
|
+
while (i < len && depth > 0) {
|
|
3520
|
+
if (text[i] === '{') depth++;
|
|
3521
|
+
else if (text[i] === '}') depth--;
|
|
3522
|
+
i++;
|
|
3523
|
+
}
|
|
3524
|
+
const fullRule = selector + text.slice(bodyStart, i);
|
|
3525
|
+
// Match tokens directly against the bare selector text — it has no
|
|
3526
|
+
// rule body for classNamesFromCssText's selector-then-`{` scan to key off.
|
|
3527
|
+
const classes = [];
|
|
3528
|
+
const classRe = /\.((?:\\.|[a-zA-Z0-9_-])+)/g;
|
|
3529
|
+
let cm;
|
|
3530
|
+
while ((cm = classRe.exec(selector)) !== null) {
|
|
3531
|
+
classes.push(cm[1].replace(/\\(.)/g, '$1'));
|
|
3532
|
+
}
|
|
3533
|
+
// Only drop a rule once every class it references is covered — a
|
|
3534
|
+
// mixed selector (`:where(.row, .col)`) stays if either is new.
|
|
3535
|
+
const isFullyCovered = classes.length > 0 && classes.every(c => covered.has(c));
|
|
3536
|
+
if (!isFullyCovered) out.push(fullRule);
|
|
3537
|
+
}
|
|
3538
|
+
return out.join('\n');
|
|
3539
|
+
};
|
|
3540
|
+
|
|
3541
|
+
return strip(cssText);
|
|
3542
|
+
};
|
|
3543
|
+
|
|
3544
|
+
|
|
3348
3545
|
// DOM observation: watch for changes and trigger recompilation
|
|
3349
3546
|
|
|
3350
3547
|
// Setup component load listener and MutationObserver
|