@master/css-runtime 2.0.0-rc.63 → 2.0.0-rc.64
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/dist/core.d.ts +3 -3
- package/dist/global.min.js +1 -1
- package/dist/index.cjs +91 -125
- package/dist/index.development.cjs +119 -128
- package/dist/index.development.mjs +119 -128
- package/dist/index.mjs +91 -125
- package/package.json +1 -1
|
@@ -57,10 +57,36 @@ function registerClassCountDebugger() {
|
|
|
57
57
|
});
|
|
58
58
|
if (errored) {
|
|
59
59
|
log.debug('Records:', records);
|
|
60
|
+
log.debug('Serialized Records:', serializeMutations(records));
|
|
60
61
|
log.debug('Counts:', classCounts);
|
|
61
62
|
}
|
|
62
63
|
});
|
|
63
64
|
}
|
|
65
|
+
function serializeMutations(mutations) {
|
|
66
|
+
return mutations.map((m)=>{
|
|
67
|
+
const target = m.target;
|
|
68
|
+
return {
|
|
69
|
+
type: m.type,
|
|
70
|
+
attributeName: m.attributeName,
|
|
71
|
+
oldValue: m.oldValue,
|
|
72
|
+
target: {
|
|
73
|
+
tagName: target.tagName,
|
|
74
|
+
id: target.id,
|
|
75
|
+
classList: Array.from(target.classList)
|
|
76
|
+
},
|
|
77
|
+
added: Array.from(m.addedNodes).filter((n)=>n.nodeType === 1).map((el)=>({
|
|
78
|
+
tagName: el.tagName,
|
|
79
|
+
id: el.id,
|
|
80
|
+
classList: Array.from(el.classList)
|
|
81
|
+
})),
|
|
82
|
+
removed: Array.from(m.removedNodes).filter((n)=>n.nodeType === 1).map((el)=>({
|
|
83
|
+
tagName: el.tagName,
|
|
84
|
+
id: el.id,
|
|
85
|
+
classList: Array.from(el.classList)
|
|
86
|
+
}))
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
64
90
|
|
|
65
91
|
function registerLifecycleDebugger() {
|
|
66
92
|
const hook = globalThis.__MASTER_CSS_DEVTOOLS_HOOK__;
|
|
@@ -139,6 +165,10 @@ class RuntimeLayer extends Layer {
|
|
|
139
165
|
return this.native.cssRules.item(insertedIndex);
|
|
140
166
|
} catch (error) {
|
|
141
167
|
console.error(error, rule);
|
|
168
|
+
/**
|
|
169
|
+
* If the rule is invalid, remove it from the rules array.
|
|
170
|
+
* It's important to note that the rule may break the entire CSS runtime,
|
|
171
|
+
*/ this.rules.splice(insertedIndex, 1);
|
|
142
172
|
return;
|
|
143
173
|
}
|
|
144
174
|
};
|
|
@@ -204,20 +234,19 @@ class CSSRuntime extends MasterCSS {
|
|
|
204
234
|
customConfig;
|
|
205
235
|
static instances = new WeakMap();
|
|
206
236
|
host;
|
|
207
|
-
observing;
|
|
208
|
-
progressive;
|
|
209
237
|
container;
|
|
210
|
-
observer;
|
|
211
238
|
baseLayer;
|
|
212
239
|
themeLayer;
|
|
213
240
|
presetLayer;
|
|
214
241
|
componentsLayer;
|
|
215
242
|
generalLayer;
|
|
216
243
|
classCounts;
|
|
244
|
+
observer;
|
|
245
|
+
progressive;
|
|
246
|
+
observing;
|
|
217
247
|
constructor(root = document, customConfig = config){
|
|
218
|
-
super(customConfig), this.root = root, this.customConfig = customConfig, this.
|
|
219
|
-
|
|
220
|
-
if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
|
|
248
|
+
super(customConfig), this.root = root, this.customConfig = customConfig, this.baseLayer = new RuntimeSyntaxLayer('base', this), this.themeLayer = new RuntimeLayer('theme', this), this.presetLayer = new RuntimeSyntaxLayer('preset', this), this.componentsLayer = new RuntimeSyntaxLayer('components', this), this.generalLayer = new RuntimeSyntaxLayer('general', this), this.classCounts = new Map(), this.progressive = false, this.observing = false;
|
|
249
|
+
if (this.root instanceof Document || this.root instanceof HTMLDocument) {
|
|
221
250
|
this.root.defaultView.globalThis.cssRuntime = this;
|
|
222
251
|
this.container = this.root.head;
|
|
223
252
|
this.host = this.root.documentElement;
|
|
@@ -236,39 +265,46 @@ class CSSRuntime extends MasterCSS {
|
|
|
236
265
|
* @returns this
|
|
237
266
|
*/ observe() {
|
|
238
267
|
if (this.observing) return this;
|
|
239
|
-
//
|
|
240
|
-
if (this.root.styleSheets)
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
268
|
+
// Detect prerendered stylesheet
|
|
269
|
+
if (this.root.styleSheets) {
|
|
270
|
+
for (const sheet of this.root.styleSheets){
|
|
271
|
+
const { ownerNode } = sheet;
|
|
272
|
+
if (ownerNode instanceof HTMLStyleElement && ownerNode.id === 'master') {
|
|
273
|
+
this.style = ownerNode;
|
|
274
|
+
if (this.style.sheet?.cssRules.length) {
|
|
275
|
+
this.progressive = true;
|
|
276
|
+
}
|
|
277
|
+
break;
|
|
247
278
|
}
|
|
248
|
-
break;
|
|
249
279
|
}
|
|
250
280
|
}
|
|
251
|
-
//
|
|
281
|
+
// Prepare snapshot map
|
|
282
|
+
const elementClasses = new WeakMap();
|
|
283
|
+
// Initial scan and populate counts + snapshot
|
|
252
284
|
const connectedNames = new Set();
|
|
253
285
|
const increaseClassCount = (className)=>{
|
|
254
286
|
const count = this.classCounts.get(className) || 0;
|
|
255
|
-
if (!count)
|
|
256
|
-
connectedNames.add(className);
|
|
257
|
-
}
|
|
287
|
+
if (!count) connectedNames.add(className);
|
|
258
288
|
this.classCounts.set(className, count + 1);
|
|
259
289
|
};
|
|
260
|
-
this.
|
|
261
|
-
|
|
262
|
-
|
|
290
|
+
const rootEl = this.root instanceof Document || this.root instanceof HTMLDocument ? this.root : this.container;
|
|
291
|
+
const elementsWithClass = rootEl.querySelectorAll('[class]');
|
|
292
|
+
elementsWithClass.forEach((el)=>{
|
|
293
|
+
const clsList = el.classList;
|
|
294
|
+
if (clsList) {
|
|
295
|
+
el.classList.forEach(increaseClassCount);
|
|
296
|
+
}
|
|
297
|
+
elementClasses.set(el, new Set(clsList));
|
|
298
|
+
});
|
|
299
|
+
// Hydration or style creation
|
|
263
300
|
if (this.progressive) {
|
|
264
301
|
const hydrateResult = this.hydrate(this.style.sheet.cssRules);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
console.debug(`The class \`${eachConnectedName}\` was added via script before calling hydrate, or the corresponding CSS rule were not properly pre-rendered.`);
|
|
302
|
+
for (const cls of connectedNames){
|
|
303
|
+
if (!hydrateResult.allSyntaxRules.find((r)=>(r.fixedClass || r.name) === cls)) {
|
|
304
|
+
this.add(cls);
|
|
305
|
+
{
|
|
306
|
+
console.debug(`Missing prerendered rule for class \`${cls}\``);
|
|
307
|
+
}
|
|
272
308
|
}
|
|
273
309
|
}
|
|
274
310
|
} else {
|
|
@@ -277,125 +313,81 @@ class CSSRuntime extends MasterCSS {
|
|
|
277
313
|
this.container.append(this.style);
|
|
278
314
|
this.style.sheet.insertRule(this.layerStatementRule.text);
|
|
279
315
|
this.layerStatementRule.native = this.style.sheet.cssRules.item(0);
|
|
280
|
-
|
|
281
|
-
this.add(eachConnectedName);
|
|
282
|
-
}
|
|
316
|
+
connectedNames.forEach((cls)=>this.add(cls));
|
|
283
317
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
318
|
+
this.observer = new MutationObserver((records)=>{
|
|
319
|
+
const deltaCounts = new Map();
|
|
320
|
+
const nodeMap = new Map();
|
|
321
|
+
const attrRecords = new Set();
|
|
322
|
+
const visited = new WeakSet();
|
|
323
|
+
const updateDelta = (cls, delta)=>deltaCounts.set(cls, (deltaCounts.get(cls) || 0) + delta);
|
|
324
|
+
const diffAndSnapshot = (el)=>{
|
|
325
|
+
const prev = new Set(elementClasses.get(el) || []);
|
|
326
|
+
const next = new Set(el.classList);
|
|
327
|
+
for (const c of next)if (!prev.has(c)) updateDelta(c, 1);
|
|
328
|
+
for (const c of prev)if (!next.has(c)) updateDelta(c, -1);
|
|
329
|
+
elementClasses.set(el, next);
|
|
293
330
|
};
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const status = map.get(target);
|
|
298
|
-
if (status) {
|
|
299
|
-
status.change += adding ? 1 : -1;
|
|
300
|
-
status.mutationRecord = mutationRecord;
|
|
301
|
-
} else {
|
|
302
|
-
map.set(target, {
|
|
303
|
-
change: adding ? 1 : -1,
|
|
304
|
-
mutationRecord
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
for (const child of target.children){
|
|
308
|
-
if ('classList' in child) {
|
|
309
|
-
recordStatus(child, mutationRecord, map, adding);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
331
|
+
const removeSnapshot = (el)=>{
|
|
332
|
+
for (const c of elementClasses.get(el) || [])updateDelta(c, -1);
|
|
333
|
+
elementClasses.delete(el);
|
|
312
334
|
};
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
break;
|
|
321
|
-
case 'childList':
|
|
322
|
-
const targetStatusMap = target.isConnected ? connectedStatusMap : disconnectedStatusMap;
|
|
323
|
-
mutationRecord.addedNodes.forEach((node)=>'classList' in node && recordStatus(node, mutationRecord, targetStatusMap, true));
|
|
324
|
-
mutationRecord.removedNodes.forEach((node)=>'classList' in node && recordStatus(node, mutationRecord, targetStatusMap, false));
|
|
325
|
-
break;
|
|
335
|
+
for (const record of records){
|
|
336
|
+
if (record.type === 'childList') {
|
|
337
|
+
for (const node of record.addedNodes)if (node instanceof Element && node.isConnected) nodeMap.set(node, (nodeMap.get(node) || 0) + 1);
|
|
338
|
+
for (const node of record.removedNodes)if (node instanceof Element && !node.isConnected) nodeMap.set(node, (nodeMap.get(node) || 0) - 1);
|
|
339
|
+
} else if (record.type === 'attributes' && record.attributeName === 'class') {
|
|
340
|
+
attrRecords.add(record.target);
|
|
326
341
|
}
|
|
327
|
-
}
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
updateClassCount(target.classList, adding);
|
|
335
|
-
} else {
|
|
336
|
-
if (firstAttrMutationRecord) {
|
|
337
|
-
updateClassCount(firstAttrMutationRecord.oldValue ? firstAttrMutationRecord.oldValue.split(/\s+/) : [], adding);
|
|
338
|
-
} else {
|
|
339
|
-
updateClassCount(target.classList, adding);
|
|
342
|
+
}
|
|
343
|
+
const traverseIncludingSelf = (el, fn, visited)=>{
|
|
344
|
+
if (!visited.has(el)) {
|
|
345
|
+
visited.add(el);
|
|
346
|
+
fn(el);
|
|
347
|
+
for (const child of el.children){
|
|
348
|
+
traverseIncludingSelf(child, fn, visited);
|
|
340
349
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
updateTarget(disconnectedTarget, disconnectedTargetStatus.change > 0);
|
|
344
|
-
}
|
|
345
|
-
});
|
|
350
|
+
} else {
|
|
351
|
+
nodeMap.delete(el);
|
|
346
352
|
}
|
|
347
353
|
};
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const addedClasses = [];
|
|
354
|
-
newClassList.forEach((c)=>{
|
|
355
|
-
if (!oldClassList.includes(c)) addedClasses.push(c);
|
|
356
|
-
});
|
|
357
|
-
const removedClasses = oldClassList.filter((c)=>!newClassList.contains(c));
|
|
358
|
-
if (addedClasses.length) {
|
|
359
|
-
updateClassCount(addedClasses, true);
|
|
360
|
-
}
|
|
361
|
-
if (removedClasses.length) {
|
|
362
|
-
updateClassCount(removedClasses, false);
|
|
354
|
+
for (const [node, count] of nodeMap){
|
|
355
|
+
if (count > 0) {
|
|
356
|
+
traverseIncludingSelf(node, diffAndSnapshot, visited);
|
|
357
|
+
} else if (count < 0 && !node.isConnected) {
|
|
358
|
+
traverseIncludingSelf(node, removeSnapshot, visited);
|
|
363
359
|
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
360
|
+
}
|
|
361
|
+
for (const el of attrRecords){
|
|
362
|
+
if (!visited.has(el)) diffAndSnapshot(el);
|
|
363
|
+
}
|
|
364
|
+
for (const [cls, change] of deltaCounts){
|
|
365
|
+
const current = this.classCounts.get(cls) || 0;
|
|
366
|
+
const next = current + change;
|
|
367
|
+
if (next > 0) {
|
|
368
|
+
this.classCounts.set(cls, next);
|
|
369
|
+
if (current === 0) this.add(cls);
|
|
375
370
|
} else {
|
|
376
|
-
this.classCounts.delete(
|
|
377
|
-
this.remove(
|
|
371
|
+
this.classCounts.delete(cls);
|
|
372
|
+
this.remove(cls);
|
|
378
373
|
}
|
|
379
|
-
}
|
|
374
|
+
}
|
|
380
375
|
globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('runtime:mutated', {
|
|
381
|
-
records
|
|
382
|
-
classCounts:
|
|
376
|
+
records,
|
|
377
|
+
classCounts: deltaCounts,
|
|
383
378
|
cssRuntime: this
|
|
384
379
|
});
|
|
385
380
|
});
|
|
386
381
|
this.observer.observe(this.root, {
|
|
382
|
+
childList: true,
|
|
387
383
|
attributes: true,
|
|
388
|
-
attributeOldValue: true,
|
|
389
384
|
attributeFilter: [
|
|
390
385
|
'class'
|
|
391
386
|
],
|
|
392
|
-
|
|
387
|
+
attributeOldValue: true,
|
|
393
388
|
subtree: true
|
|
394
389
|
});
|
|
395
|
-
if (!this.progressive)
|
|
396
|
-
this.host.removeAttribute('hidden');
|
|
397
|
-
}
|
|
398
|
-
// @ts-ignore
|
|
390
|
+
if (!this.progressive) this.host.removeAttribute('hidden');
|
|
399
391
|
this.observing = true;
|
|
400
392
|
globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('runtime:observed', {
|
|
401
393
|
cssRuntime: this
|
|
@@ -541,7 +533,6 @@ class CSSRuntime extends MasterCSS {
|
|
|
541
533
|
if (!this.observing) return;
|
|
542
534
|
if (this.observer) {
|
|
543
535
|
this.observer.disconnect();
|
|
544
|
-
// @ts-expect-error readonly
|
|
545
536
|
this.observer = undefined;
|
|
546
537
|
}
|
|
547
538
|
// @ts-ignore
|
package/dist/index.mjs
CHANGED
|
@@ -41,6 +41,10 @@ class RuntimeLayer extends Layer {
|
|
|
41
41
|
return this.native.cssRules.item(insertedIndex);
|
|
42
42
|
} catch (error) {
|
|
43
43
|
console.error(error, rule);
|
|
44
|
+
/**
|
|
45
|
+
* If the rule is invalid, remove it from the rules array.
|
|
46
|
+
* It's important to note that the rule may break the entire CSS runtime,
|
|
47
|
+
*/ this.rules.splice(insertedIndex, 1);
|
|
44
48
|
return;
|
|
45
49
|
}
|
|
46
50
|
};
|
|
@@ -106,20 +110,19 @@ class CSSRuntime extends MasterCSS {
|
|
|
106
110
|
customConfig;
|
|
107
111
|
static instances = new WeakMap();
|
|
108
112
|
host;
|
|
109
|
-
observing;
|
|
110
|
-
progressive;
|
|
111
113
|
container;
|
|
112
|
-
observer;
|
|
113
114
|
baseLayer;
|
|
114
115
|
themeLayer;
|
|
115
116
|
presetLayer;
|
|
116
117
|
componentsLayer;
|
|
117
118
|
generalLayer;
|
|
118
119
|
classCounts;
|
|
120
|
+
observer;
|
|
121
|
+
progressive;
|
|
122
|
+
observing;
|
|
119
123
|
constructor(root = document, customConfig = config){
|
|
120
|
-
super(customConfig), this.root = root, this.customConfig = customConfig, this.
|
|
121
|
-
|
|
122
|
-
if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
|
|
124
|
+
super(customConfig), this.root = root, this.customConfig = customConfig, this.baseLayer = new RuntimeSyntaxLayer('base', this), this.themeLayer = new RuntimeLayer('theme', this), this.presetLayer = new RuntimeSyntaxLayer('preset', this), this.componentsLayer = new RuntimeSyntaxLayer('components', this), this.generalLayer = new RuntimeSyntaxLayer('general', this), this.classCounts = new Map(), this.progressive = false, this.observing = false;
|
|
125
|
+
if (this.root instanceof Document || this.root instanceof HTMLDocument) {
|
|
123
126
|
this.root.defaultView.globalThis.cssRuntime = this;
|
|
124
127
|
this.container = this.root.head;
|
|
125
128
|
this.host = this.root.documentElement;
|
|
@@ -138,36 +141,44 @@ class CSSRuntime extends MasterCSS {
|
|
|
138
141
|
* @returns this
|
|
139
142
|
*/ observe() {
|
|
140
143
|
if (this.observing) return this;
|
|
141
|
-
//
|
|
142
|
-
if (this.root.styleSheets)
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
144
|
+
// Detect prerendered stylesheet
|
|
145
|
+
if (this.root.styleSheets) {
|
|
146
|
+
for (const sheet of this.root.styleSheets){
|
|
147
|
+
const { ownerNode } = sheet;
|
|
148
|
+
if (ownerNode instanceof HTMLStyleElement && ownerNode.id === 'master') {
|
|
149
|
+
this.style = ownerNode;
|
|
150
|
+
if (this.style.sheet?.cssRules.length) {
|
|
151
|
+
this.progressive = true;
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
149
154
|
}
|
|
150
|
-
break;
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
|
-
//
|
|
157
|
+
// Prepare snapshot map
|
|
158
|
+
const elementClasses = new WeakMap();
|
|
159
|
+
// Initial scan and populate counts + snapshot
|
|
154
160
|
const connectedNames = new Set();
|
|
155
161
|
const increaseClassCount = (className)=>{
|
|
156
162
|
const count = this.classCounts.get(className) || 0;
|
|
157
|
-
if (!count)
|
|
158
|
-
connectedNames.add(className);
|
|
159
|
-
}
|
|
163
|
+
if (!count) connectedNames.add(className);
|
|
160
164
|
this.classCounts.set(className, count + 1);
|
|
161
165
|
};
|
|
162
|
-
this.
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
const rootEl = this.root instanceof Document || this.root instanceof HTMLDocument ? this.root : this.container;
|
|
167
|
+
const elementsWithClass = rootEl.querySelectorAll('[class]');
|
|
168
|
+
elementsWithClass.forEach((el)=>{
|
|
169
|
+
const clsList = el.classList;
|
|
170
|
+
if (clsList) {
|
|
171
|
+
el.classList.forEach(increaseClassCount);
|
|
172
|
+
}
|
|
173
|
+
elementClasses.set(el, new Set(clsList));
|
|
174
|
+
});
|
|
175
|
+
// Hydration or style creation
|
|
165
176
|
if (this.progressive) {
|
|
166
177
|
const hydrateResult = this.hydrate(this.style.sheet.cssRules);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
for (const cls of connectedNames){
|
|
179
|
+
if (!hydrateResult.allSyntaxRules.find((r)=>(r.fixedClass || r.name) === cls)) {
|
|
180
|
+
this.add(cls);
|
|
181
|
+
}
|
|
171
182
|
}
|
|
172
183
|
} else {
|
|
173
184
|
this.style = document.createElement('style');
|
|
@@ -175,125 +186,81 @@ class CSSRuntime extends MasterCSS {
|
|
|
175
186
|
this.container.append(this.style);
|
|
176
187
|
this.style.sheet.insertRule(this.layerStatementRule.text);
|
|
177
188
|
this.layerStatementRule.native = this.style.sheet.cssRules.item(0);
|
|
178
|
-
|
|
179
|
-
this.add(eachConnectedName);
|
|
180
|
-
}
|
|
189
|
+
connectedNames.forEach((cls)=>this.add(cls));
|
|
181
190
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
this.observer = new MutationObserver((records)=>{
|
|
192
|
+
const deltaCounts = new Map();
|
|
193
|
+
const nodeMap = new Map();
|
|
194
|
+
const attrRecords = new Set();
|
|
195
|
+
const visited = new WeakSet();
|
|
196
|
+
const updateDelta = (cls, delta)=>deltaCounts.set(cls, (deltaCounts.get(cls) || 0) + delta);
|
|
197
|
+
const diffAndSnapshot = (el)=>{
|
|
198
|
+
const prev = new Set(elementClasses.get(el) || []);
|
|
199
|
+
const next = new Set(el.classList);
|
|
200
|
+
for (const c of next)if (!prev.has(c)) updateDelta(c, 1);
|
|
201
|
+
for (const c of prev)if (!next.has(c)) updateDelta(c, -1);
|
|
202
|
+
elementClasses.set(el, next);
|
|
191
203
|
};
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const status = map.get(target);
|
|
196
|
-
if (status) {
|
|
197
|
-
status.change += adding ? 1 : -1;
|
|
198
|
-
status.mutationRecord = mutationRecord;
|
|
199
|
-
} else {
|
|
200
|
-
map.set(target, {
|
|
201
|
-
change: adding ? 1 : -1,
|
|
202
|
-
mutationRecord
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
for (const child of target.children){
|
|
206
|
-
if ('classList' in child) {
|
|
207
|
-
recordStatus(child, mutationRecord, map, adding);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
204
|
+
const removeSnapshot = (el)=>{
|
|
205
|
+
for (const c of elementClasses.get(el) || [])updateDelta(c, -1);
|
|
206
|
+
elementClasses.delete(el);
|
|
210
207
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
break;
|
|
219
|
-
case 'childList':
|
|
220
|
-
const targetStatusMap = target.isConnected ? connectedStatusMap : disconnectedStatusMap;
|
|
221
|
-
mutationRecord.addedNodes.forEach((node)=>'classList' in node && recordStatus(node, mutationRecord, targetStatusMap, true));
|
|
222
|
-
mutationRecord.removedNodes.forEach((node)=>'classList' in node && recordStatus(node, mutationRecord, targetStatusMap, false));
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
const updateTarget = (target, adding)=>{
|
|
227
|
-
const firstAttrMutationRecord = targetFirstAttrMutationRecord.get(target);
|
|
228
|
-
if (firstAttrMutationRecord) {
|
|
229
|
-
targetFirstAttrMutationRecord.delete(target);
|
|
208
|
+
for (const record of records){
|
|
209
|
+
if (record.type === 'childList') {
|
|
210
|
+
for (const node of record.addedNodes)if (node instanceof Element && node.isConnected) nodeMap.set(node, (nodeMap.get(node) || 0) + 1);
|
|
211
|
+
for (const node of record.removedNodes)if (node instanceof Element && !node.isConnected) nodeMap.set(node, (nodeMap.get(node) || 0) - 1);
|
|
212
|
+
} else if (record.type === 'attributes' && record.attributeName === 'class') {
|
|
213
|
+
attrRecords.add(record.target);
|
|
230
214
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
215
|
+
}
|
|
216
|
+
const traverseIncludingSelf = (el, fn, visited)=>{
|
|
217
|
+
if (!visited.has(el)) {
|
|
218
|
+
visited.add(el);
|
|
219
|
+
fn(el);
|
|
220
|
+
for (const child of el.children){
|
|
221
|
+
traverseIncludingSelf(child, fn, visited);
|
|
238
222
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
updateTarget(disconnectedTarget, disconnectedTargetStatus.change > 0);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
223
|
+
} else {
|
|
224
|
+
nodeMap.delete(el);
|
|
244
225
|
}
|
|
245
226
|
};
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const addedClasses = [];
|
|
252
|
-
newClassList.forEach((c)=>{
|
|
253
|
-
if (!oldClassList.includes(c)) addedClasses.push(c);
|
|
254
|
-
});
|
|
255
|
-
const removedClasses = oldClassList.filter((c)=>!newClassList.contains(c));
|
|
256
|
-
if (addedClasses.length) {
|
|
257
|
-
updateClassCount(addedClasses, true);
|
|
227
|
+
for (const [node, count] of nodeMap){
|
|
228
|
+
if (count > 0) {
|
|
229
|
+
traverseIncludingSelf(node, diffAndSnapshot, visited);
|
|
230
|
+
} else if (count < 0 && !node.isConnected) {
|
|
231
|
+
traverseIncludingSelf(node, removeSnapshot, visited);
|
|
258
232
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
this.classCounts.set(className, newCount);
|
|
270
|
-
if (currentCount === 0) {
|
|
271
|
-
this.add(className);
|
|
272
|
-
}
|
|
233
|
+
}
|
|
234
|
+
for (const el of attrRecords){
|
|
235
|
+
if (!visited.has(el)) diffAndSnapshot(el);
|
|
236
|
+
}
|
|
237
|
+
for (const [cls, change] of deltaCounts){
|
|
238
|
+
const current = this.classCounts.get(cls) || 0;
|
|
239
|
+
const next = current + change;
|
|
240
|
+
if (next > 0) {
|
|
241
|
+
this.classCounts.set(cls, next);
|
|
242
|
+
if (current === 0) this.add(cls);
|
|
273
243
|
} else {
|
|
274
|
-
this.classCounts.delete(
|
|
275
|
-
this.remove(
|
|
244
|
+
this.classCounts.delete(cls);
|
|
245
|
+
this.remove(cls);
|
|
276
246
|
}
|
|
277
|
-
}
|
|
247
|
+
}
|
|
278
248
|
globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('runtime:mutated', {
|
|
279
|
-
records
|
|
280
|
-
classCounts:
|
|
249
|
+
records,
|
|
250
|
+
classCounts: deltaCounts,
|
|
281
251
|
cssRuntime: this
|
|
282
252
|
});
|
|
283
253
|
});
|
|
284
254
|
this.observer.observe(this.root, {
|
|
255
|
+
childList: true,
|
|
285
256
|
attributes: true,
|
|
286
|
-
attributeOldValue: true,
|
|
287
257
|
attributeFilter: [
|
|
288
258
|
'class'
|
|
289
259
|
],
|
|
290
|
-
|
|
260
|
+
attributeOldValue: true,
|
|
291
261
|
subtree: true
|
|
292
262
|
});
|
|
293
|
-
if (!this.progressive)
|
|
294
|
-
this.host.removeAttribute('hidden');
|
|
295
|
-
}
|
|
296
|
-
// @ts-ignore
|
|
263
|
+
if (!this.progressive) this.host.removeAttribute('hidden');
|
|
297
264
|
this.observing = true;
|
|
298
265
|
globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('runtime:observed', {
|
|
299
266
|
cssRuntime: this
|
|
@@ -436,7 +403,6 @@ class CSSRuntime extends MasterCSS {
|
|
|
436
403
|
if (!this.observing) return;
|
|
437
404
|
if (this.observer) {
|
|
438
405
|
this.observer.disconnect();
|
|
439
|
-
// @ts-expect-error readonly
|
|
440
406
|
this.observer = undefined;
|
|
441
407
|
}
|
|
442
408
|
// @ts-ignore
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@master/css-runtime","type":"module","scripts":{"build":"techor build","dev":"pnpm build --watch","e2e":"playwright test","e2e:watch":"nodemon -e js,mjs,ts,html,css --watch dist --watch e2e --exec playwright test","type-check":"tsc --noEmit","lint":"eslint"},"license":"MIT","description":"Run Master CSS right in the browser","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/runtime"},"keywords":["utility","css","lightweight","mastercss","master","runtime","cdn"],"sideEffects":false,"main":"./dist/index.cjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","module":"./dist/index.mjs","browser":"./dist/global.min.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","require":{"development":"./dist/index.development.cjs","default":"./dist/index.cjs"},"import":{"development":"./dist/index.development.mjs","default":"./dist/index.mjs"}}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.
|
|
1
|
+
{"name":"@master/css-runtime","type":"module","scripts":{"build":"techor build","dev":"pnpm build --watch","e2e":"playwright test","e2e:watch":"nodemon -e js,mjs,ts,html,css --watch dist --watch e2e --exec playwright test","type-check":"tsc --noEmit","lint":"eslint"},"license":"MIT","description":"Run Master CSS right in the browser","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/runtime"},"keywords":["utility","css","lightweight","mastercss","master","runtime","cdn"],"sideEffects":false,"main":"./dist/index.cjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","module":"./dist/index.mjs","browser":"./dist/global.min.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","require":{"development":"./dist/index.development.cjs","default":"./dist/index.cjs"},"import":{"development":"./dist/index.development.mjs","default":"./dist/index.mjs"}}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.64","@master/css-devtools-hook":"^2.0.0-rc.64"},"devDependencies":{"@playwright/test":"^1.49.1","shared":"^2.0.0-rc.64"},"version":"2.0.0-rc.64"}
|