@master/css-runtime 2.0.0-rc.63 → 2.0.0-rc.65
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 +103 -132
- package/dist/index.development.cjs +131 -135
- package/dist/index.development.mjs +131 -135
- package/dist/index.mjs +103 -132
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -36,12 +36,21 @@ class RuntimeLayer extends Layer {
|
|
|
36
36
|
const insertedIndex = super.insert(rule, index);
|
|
37
37
|
if (insertedIndex === undefined || !this.native) return;
|
|
38
38
|
const insertRuleSafely = (text, position)=>{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return this.native.cssRules.item(
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
// Checks if the rule is inserted in a native CSS rule with this.attach()
|
|
40
|
+
if (this.rules.length === 1) {
|
|
41
|
+
return this.native.cssRules.item(position);
|
|
42
|
+
} else {
|
|
43
|
+
try {
|
|
44
|
+
const insertedIndex = this.native.insertRule(text, position);
|
|
45
|
+
return this.native.cssRules.item(insertedIndex);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(error, rule);
|
|
48
|
+
/**
|
|
49
|
+
* If the rule is invalid, remove it from the rules array.
|
|
50
|
+
* It's important to note that the rule may break the entire CSS runtime,
|
|
51
|
+
*/ this.rules.splice(insertedIndex, 1);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
45
54
|
}
|
|
46
55
|
};
|
|
47
56
|
if ('nodes' in rule) {
|
|
@@ -51,7 +60,7 @@ class RuntimeLayer extends Layer {
|
|
|
51
60
|
if (node.native) currentIndex++;
|
|
52
61
|
});
|
|
53
62
|
} else {
|
|
54
|
-
rule.native = insertRuleSafely(rule.text,
|
|
63
|
+
rule.native = insertRuleSafely(rule.text, insertedIndex);
|
|
55
64
|
}
|
|
56
65
|
return insertedIndex;
|
|
57
66
|
}
|
|
@@ -106,20 +115,19 @@ class CSSRuntime extends MasterCSS {
|
|
|
106
115
|
customConfig;
|
|
107
116
|
static instances = new WeakMap();
|
|
108
117
|
host;
|
|
109
|
-
observing;
|
|
110
|
-
progressive;
|
|
111
118
|
container;
|
|
112
|
-
observer;
|
|
113
119
|
baseLayer;
|
|
114
120
|
themeLayer;
|
|
115
121
|
presetLayer;
|
|
116
122
|
componentsLayer;
|
|
117
123
|
generalLayer;
|
|
118
124
|
classCounts;
|
|
125
|
+
observer;
|
|
126
|
+
progressive;
|
|
127
|
+
observing;
|
|
119
128
|
constructor(root = document, customConfig = config){
|
|
120
|
-
super(customConfig), this.root = root, this.customConfig = customConfig, this.
|
|
121
|
-
|
|
122
|
-
if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
|
|
129
|
+
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;
|
|
130
|
+
if (this.root instanceof Document || this.root instanceof HTMLDocument) {
|
|
123
131
|
this.root.defaultView.globalThis.cssRuntime = this;
|
|
124
132
|
this.container = this.root.head;
|
|
125
133
|
this.host = this.root.documentElement;
|
|
@@ -138,36 +146,44 @@ class CSSRuntime extends MasterCSS {
|
|
|
138
146
|
* @returns this
|
|
139
147
|
*/ observe() {
|
|
140
148
|
if (this.observing) return this;
|
|
141
|
-
//
|
|
142
|
-
if (this.root.styleSheets)
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
// Detect prerendered stylesheet
|
|
150
|
+
if (this.root.styleSheets) {
|
|
151
|
+
for (const sheet of this.root.styleSheets){
|
|
152
|
+
const { ownerNode } = sheet;
|
|
153
|
+
if (ownerNode instanceof HTMLStyleElement && ownerNode.id === 'master') {
|
|
154
|
+
this.style = ownerNode;
|
|
155
|
+
if (this.style.sheet?.cssRules.length) {
|
|
156
|
+
this.progressive = true;
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
149
159
|
}
|
|
150
|
-
break;
|
|
151
160
|
}
|
|
152
161
|
}
|
|
153
|
-
//
|
|
162
|
+
// Prepare snapshot map
|
|
163
|
+
const elementClasses = new WeakMap();
|
|
164
|
+
// Initial scan and populate counts + snapshot
|
|
154
165
|
const connectedNames = new Set();
|
|
155
166
|
const increaseClassCount = (className)=>{
|
|
156
167
|
const count = this.classCounts.get(className) || 0;
|
|
157
|
-
if (!count)
|
|
158
|
-
connectedNames.add(className);
|
|
159
|
-
}
|
|
168
|
+
if (!count) connectedNames.add(className);
|
|
160
169
|
this.classCounts.set(className, count + 1);
|
|
161
170
|
};
|
|
162
|
-
this.
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
const rootEl = this.root instanceof Document || this.root instanceof HTMLDocument ? this.root : this.container;
|
|
172
|
+
const elementsWithClass = rootEl.querySelectorAll('[class]');
|
|
173
|
+
elementsWithClass.forEach((el)=>{
|
|
174
|
+
const clsList = el.classList;
|
|
175
|
+
if (clsList) {
|
|
176
|
+
el.classList.forEach(increaseClassCount);
|
|
177
|
+
}
|
|
178
|
+
elementClasses.set(el, new Set(clsList));
|
|
179
|
+
});
|
|
180
|
+
// Hydration or style creation
|
|
165
181
|
if (this.progressive) {
|
|
166
182
|
const hydrateResult = this.hydrate(this.style.sheet.cssRules);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
183
|
+
for (const cls of connectedNames){
|
|
184
|
+
if (!hydrateResult.allSyntaxRules.find((r)=>(r.fixedClass || r.name) === cls)) {
|
|
185
|
+
this.add(cls);
|
|
186
|
+
}
|
|
171
187
|
}
|
|
172
188
|
} else {
|
|
173
189
|
this.style = document.createElement('style');
|
|
@@ -175,125 +191,81 @@ class CSSRuntime extends MasterCSS {
|
|
|
175
191
|
this.container.append(this.style);
|
|
176
192
|
this.style.sheet.insertRule(this.layerStatementRule.text);
|
|
177
193
|
this.layerStatementRule.native = this.style.sheet.cssRules.item(0);
|
|
178
|
-
|
|
179
|
-
this.add(eachConnectedName);
|
|
180
|
-
}
|
|
194
|
+
connectedNames.forEach((cls)=>this.add(cls));
|
|
181
195
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
this.observer = new MutationObserver((records)=>{
|
|
197
|
+
const deltaCounts = new Map();
|
|
198
|
+
const nodeMap = new Map();
|
|
199
|
+
const attrRecords = new Set();
|
|
200
|
+
const visited = new WeakSet();
|
|
201
|
+
const updateDelta = (cls, delta)=>deltaCounts.set(cls, (deltaCounts.get(cls) || 0) + delta);
|
|
202
|
+
const diffAndSnapshot = (el)=>{
|
|
203
|
+
const prev = new Set(elementClasses.get(el) || []);
|
|
204
|
+
const next = new Set(el.classList);
|
|
205
|
+
for (const c of next)if (!prev.has(c)) updateDelta(c, 1);
|
|
206
|
+
for (const c of prev)if (!next.has(c)) updateDelta(c, -1);
|
|
207
|
+
elementClasses.set(el, next);
|
|
191
208
|
};
|
|
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
|
-
}
|
|
209
|
+
const removeSnapshot = (el)=>{
|
|
210
|
+
for (const c of elementClasses.get(el) || [])updateDelta(c, -1);
|
|
211
|
+
elementClasses.delete(el);
|
|
210
212
|
};
|
|
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);
|
|
213
|
+
for (const record of records){
|
|
214
|
+
if (record.type === 'childList') {
|
|
215
|
+
for (const node of record.addedNodes)if (node instanceof Element && node.isConnected) nodeMap.set(node, (nodeMap.get(node) || 0) + 1);
|
|
216
|
+
for (const node of record.removedNodes)if (node instanceof Element && !node.isConnected) nodeMap.set(node, (nodeMap.get(node) || 0) - 1);
|
|
217
|
+
} else if (record.type === 'attributes' && record.attributeName === 'class') {
|
|
218
|
+
attrRecords.add(record.target);
|
|
230
219
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
220
|
+
}
|
|
221
|
+
const traverseIncludingSelf = (el, fn, visited)=>{
|
|
222
|
+
if (!visited.has(el)) {
|
|
223
|
+
visited.add(el);
|
|
224
|
+
fn(el);
|
|
225
|
+
for (const child of el.children){
|
|
226
|
+
traverseIncludingSelf(child, fn, visited);
|
|
238
227
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
updateTarget(disconnectedTarget, disconnectedTargetStatus.change > 0);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
228
|
+
} else {
|
|
229
|
+
nodeMap.delete(el);
|
|
244
230
|
}
|
|
245
231
|
};
|
|
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);
|
|
258
|
-
}
|
|
259
|
-
if (removedClasses.length) {
|
|
260
|
-
updateClassCount(removedClasses, false);
|
|
232
|
+
for (const [node, count] of nodeMap){
|
|
233
|
+
if (count > 0) {
|
|
234
|
+
traverseIncludingSelf(node, diffAndSnapshot, visited);
|
|
235
|
+
} else if (count < 0 && !node.isConnected) {
|
|
236
|
+
traverseIncludingSelf(node, removeSnapshot, visited);
|
|
261
237
|
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
238
|
+
}
|
|
239
|
+
for (const el of attrRecords){
|
|
240
|
+
if (!visited.has(el)) diffAndSnapshot(el);
|
|
241
|
+
}
|
|
242
|
+
for (const [cls, change] of deltaCounts){
|
|
243
|
+
const current = this.classCounts.get(cls) || 0;
|
|
244
|
+
const next = current + change;
|
|
245
|
+
if (next > 0) {
|
|
246
|
+
this.classCounts.set(cls, next);
|
|
247
|
+
if (current === 0) this.add(cls);
|
|
273
248
|
} else {
|
|
274
|
-
this.classCounts.delete(
|
|
275
|
-
this.remove(
|
|
249
|
+
this.classCounts.delete(cls);
|
|
250
|
+
this.remove(cls);
|
|
276
251
|
}
|
|
277
|
-
}
|
|
252
|
+
}
|
|
278
253
|
globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('runtime:mutated', {
|
|
279
|
-
records
|
|
280
|
-
classCounts:
|
|
254
|
+
records,
|
|
255
|
+
classCounts: deltaCounts,
|
|
281
256
|
cssRuntime: this
|
|
282
257
|
});
|
|
283
258
|
});
|
|
284
259
|
this.observer.observe(this.root, {
|
|
260
|
+
childList: true,
|
|
285
261
|
attributes: true,
|
|
286
|
-
attributeOldValue: true,
|
|
287
262
|
attributeFilter: [
|
|
288
263
|
'class'
|
|
289
264
|
],
|
|
290
|
-
|
|
265
|
+
attributeOldValue: true,
|
|
291
266
|
subtree: true
|
|
292
267
|
});
|
|
293
|
-
if (!this.progressive)
|
|
294
|
-
this.host.removeAttribute('hidden');
|
|
295
|
-
}
|
|
296
|
-
// @ts-ignore
|
|
268
|
+
if (!this.progressive) this.host.removeAttribute('hidden');
|
|
297
269
|
this.observing = true;
|
|
298
270
|
globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('runtime:observed', {
|
|
299
271
|
cssRuntime: this
|
|
@@ -436,7 +408,6 @@ class CSSRuntime extends MasterCSS {
|
|
|
436
408
|
if (!this.observing) return;
|
|
437
409
|
if (this.observer) {
|
|
438
410
|
this.observer.disconnect();
|
|
439
|
-
// @ts-expect-error readonly
|
|
440
411
|
this.observer = undefined;
|
|
441
412
|
}
|
|
442
413
|
// @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.65","@master/css-devtools-hook":"^2.0.0-rc.65"},"devDependencies":{"@playwright/test":"^1.49.1","shared":"^2.0.0-rc.65"},"version":"2.0.0-rc.65"}
|