@master/css-runtime 2.0.0-rc.47 → 2.0.0-rc.49
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 +7 -7
- package/dist/global.min.js +1 -1
- package/dist/index.cjs +297 -283
- package/dist/index.mjs +298 -284
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MasterCSS, config } from '@master/css';
|
|
1
|
+
import { MasterCSS, config, Rule } from '@master/css';
|
|
2
2
|
|
|
3
3
|
class RuntimeCSS extends MasterCSS {
|
|
4
4
|
root;
|
|
@@ -10,7 +10,8 @@ class RuntimeCSS extends MasterCSS {
|
|
|
10
10
|
observer;
|
|
11
11
|
constructor(root = document, customConfig = config){
|
|
12
12
|
super(customConfig), this.root = root, this.customConfig = customConfig, this.observing = false, this.progressive = false;
|
|
13
|
-
|
|
13
|
+
const existingRuntimeCSS = globalThis.runtimeCSSs.find((eachCSS)=>eachCSS.root === this.root);
|
|
14
|
+
if (existingRuntimeCSS) throw new Error('Cannot create multiple RuntimeCSS instances for the same root element.');
|
|
14
15
|
const rootConstructorName = this.root?.constructor.name;
|
|
15
16
|
if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
|
|
16
17
|
// @ts-ignore
|
|
@@ -27,340 +28,353 @@ class RuntimeCSS extends MasterCSS {
|
|
|
27
28
|
* Observe the DOM for changes and update the running stylesheet. (browser only)
|
|
28
29
|
* @param options mutation observer options
|
|
29
30
|
* @returns this
|
|
30
|
-
*/ observe(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}) {
|
|
34
|
-
if (this.observing || !this.root) return this;
|
|
35
|
-
if (runtimeCSSs.find((eachRuntimeCSS)=>eachRuntimeCSS !== this && eachRuntimeCSS.root === this.root)) {
|
|
36
|
-
console.warn('Cannot observe the same root element repeatedly.');
|
|
37
|
-
return this;
|
|
38
|
-
}
|
|
39
|
-
if (this.root?.styleSheets) for (const sheet of this.root.styleSheets){
|
|
31
|
+
*/ observe() {
|
|
32
|
+
if (this.observing) return this;
|
|
33
|
+
if (this.root.styleSheets) for (const sheet of this.root.styleSheets){
|
|
40
34
|
const { ownerNode } = sheet;
|
|
41
35
|
if (ownerNode && ownerNode.id === 'master') {
|
|
42
|
-
// @ts-ignore
|
|
43
36
|
this.style = ownerNode;
|
|
44
37
|
// @ts-ignore
|
|
45
38
|
this.progressive = true;
|
|
46
39
|
break;
|
|
47
40
|
}
|
|
48
41
|
}
|
|
49
|
-
if (this.
|
|
50
|
-
|
|
51
|
-
for(; index < this.style.sheet.cssRules.length; index++){
|
|
52
|
-
const eachCSSRule = this.style.sheet.cssRules[index];
|
|
53
|
-
switch(eachCSSRule.constructor.name){
|
|
54
|
-
case 'CSSKeyframesRule':
|
|
55
|
-
continue;
|
|
56
|
-
case 'CSSMediaRule':
|
|
57
|
-
const result = /\(prefers-color-scheme: ?(.*?)\)/.exec(eachCSSRule.conditionText);
|
|
58
|
-
if (result) {
|
|
59
|
-
const firstCSSRule = eachCSSRule.cssRules[0];
|
|
60
|
-
if (firstCSSRule?.constructor.name === 'CSSStyleRule' && firstCSSRule.selectorText === ':root') {
|
|
61
|
-
this.pushVariableNativeRule(result[1], firstCSSRule);
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
break;
|
|
66
|
-
case 'CSSStyleRule':
|
|
67
|
-
const selectorText = eachCSSRule.selectorText;
|
|
68
|
-
if (eachCSSRule.style.length) {
|
|
69
|
-
let isVariablesRule = true;
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
71
|
-
for(let i = 0; i < eachCSSRule.style.length; i++){
|
|
72
|
-
if (!eachCSSRule.style[i]?.startsWith('--')) {
|
|
73
|
-
isVariablesRule = false;
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (isVariablesRule) {
|
|
78
|
-
if (selectorText === ':root') {
|
|
79
|
-
this.pushVariableNativeRule('', eachCSSRule);
|
|
80
|
-
continue;
|
|
81
|
-
} else {
|
|
82
|
-
const result = /:host(.*?)/.exec(selectorText);
|
|
83
|
-
if (result) {
|
|
84
|
-
this.pushVariableNativeRule(result[1], eachCSSRule);
|
|
85
|
-
continue;
|
|
86
|
-
} else if (!selectorText.startsWith('.\\$')) {
|
|
87
|
-
const [mode] = selectorText.split(',');
|
|
88
|
-
this.pushVariableNativeRule(mode.slice(1), eachCSSRule);
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
for(; index < this.style.sheet.cssRules.length; index++){
|
|
99
|
-
const getRule = (cssRule)=>{
|
|
100
|
-
if (cssRule.selectorText) {
|
|
101
|
-
const selectorTexts = cssRule.selectorText.split(', ');
|
|
102
|
-
const escapedClassNames = selectorTexts[0].split(' ');
|
|
103
|
-
for (const eachSelectorText of escapedClassNames){
|
|
104
|
-
if (eachSelectorText[0] === '.') {
|
|
105
|
-
const escapedClassName = eachSelectorText.slice(1);
|
|
106
|
-
let className = '';
|
|
107
|
-
for(let j = 0; j < escapedClassName.length; j++){
|
|
108
|
-
const char = escapedClassName[j];
|
|
109
|
-
const nextChar = escapedClassName[j + 1];
|
|
110
|
-
if (char === '\\') {
|
|
111
|
-
j++;
|
|
112
|
-
if (nextChar !== '\\') {
|
|
113
|
-
className += nextChar;
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
} else if ([
|
|
117
|
-
',',
|
|
118
|
-
'.',
|
|
119
|
-
'#',
|
|
120
|
-
'[',
|
|
121
|
-
'!',
|
|
122
|
-
'*',
|
|
123
|
-
'>',
|
|
124
|
-
'+',
|
|
125
|
-
'~',
|
|
126
|
-
':',
|
|
127
|
-
'@'
|
|
128
|
-
].includes(char)) {
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
className += char;
|
|
132
|
-
}
|
|
133
|
-
if (!Object.prototype.hasOwnProperty.call(this.ruleBy, className) && !Object.prototype.hasOwnProperty.call(this.styles, className)) {
|
|
134
|
-
const currentRule = this.generate(className)[0];
|
|
135
|
-
if (currentRule) return currentRule;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
} else if (cssRule.cssRules) {
|
|
140
|
-
for (const rule of cssRule.cssRules){
|
|
141
|
-
const currentRule = getRule(rule);
|
|
142
|
-
if (currentRule) return currentRule;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
const rule = getRule(this.style.sheet.cssRules[index]);
|
|
147
|
-
if (rule) {
|
|
148
|
-
this.syntaxes.push(rule);
|
|
149
|
-
this.ruleBy[rule.className] = rule;
|
|
150
|
-
for(let i = 0; i < rule.natives.length; i++){
|
|
151
|
-
rule.natives[i].cssRule = this.style.sheet.cssRules[index + i];
|
|
152
|
-
}
|
|
153
|
-
index += rule.natives.length - 1;
|
|
154
|
-
// variables
|
|
155
|
-
this.handleRuleWithVariableNames(rule, true);
|
|
156
|
-
// animations
|
|
157
|
-
this.handleRuleWithAnimationNames(rule, true);
|
|
158
|
-
rule.definition.insert?.call(rule);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
42
|
+
if (this.progressive) {
|
|
43
|
+
this.hydrate(this.style.sheet.cssRules);
|
|
161
44
|
} else {
|
|
162
|
-
// @ts-ignore
|
|
163
45
|
this.style = document.createElement('style');
|
|
164
46
|
this.style.id = 'master';
|
|
165
47
|
this.container.append(this.style);
|
|
48
|
+
this.style.sheet.insertRule(this.layerStatementRule.text);
|
|
49
|
+
this.layerStatementRule.nodes[0].native = this.style.sheet.cssRules.item(0);
|
|
166
50
|
}
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
51
|
+
const firstConnectedElementsClasses = new Map();
|
|
52
|
+
const addClasses = (element)=>{
|
|
53
|
+
element.classList.forEach((className)=>{
|
|
54
|
+
if (this.classUsages.has(className)) {
|
|
55
|
+
this.classUsages.set(className, this.classUsages.get(className) + 1);
|
|
171
56
|
} else {
|
|
172
|
-
this.
|
|
57
|
+
this.classUsages.set(className, 1);
|
|
173
58
|
this.add(className);
|
|
174
59
|
}
|
|
60
|
+
const classes = firstConnectedElementsClasses.get(element);
|
|
61
|
+
if (classes) {
|
|
62
|
+
classes.push(className);
|
|
63
|
+
} else {
|
|
64
|
+
firstConnectedElementsClasses.set(element, [
|
|
65
|
+
className
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
175
68
|
});
|
|
176
69
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
70
|
+
addClasses(this.host);
|
|
71
|
+
/**
|
|
72
|
+
* 待所有 DOM 結構完成解析後,開始繪製 Rule 樣式
|
|
73
|
+
*/ (this.root.constructor.name === 'HTMLDocument' ? this.host : this.container).querySelectorAll('[class]').forEach((element)=>{
|
|
74
|
+
addClasses(element);
|
|
75
|
+
});
|
|
76
|
+
// @ts-expect-error readonly
|
|
183
77
|
this.observer = new MutationObserver((mutationRecords)=>{
|
|
184
|
-
// console.
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
for (const eachChildren of children){
|
|
199
|
-
if (eachChildren.classList && !updatedElements.includes(eachChildren)) {
|
|
200
|
-
updatedElements.push(eachChildren);
|
|
201
|
-
handleClassNameDeeply(eachChildren, remove);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
78
|
+
// console.clear()
|
|
79
|
+
// console.log('-----------')
|
|
80
|
+
// const test = 'swiper-slide-next'
|
|
81
|
+
// console.log(`${test}: ${this.classUsages.get(test)}`)
|
|
82
|
+
const eachClassUsages = new Map();
|
|
83
|
+
const updatedAttrElements = new Set();
|
|
84
|
+
const updatedConnectedElements = new Set();
|
|
85
|
+
const updatedElements = new Set();
|
|
86
|
+
const updateClassUsage = (classes, isAdding = false)=>{
|
|
87
|
+
const usage = isAdding ? 1 : -1;
|
|
88
|
+
classes.forEach((className)=>{
|
|
89
|
+
// if (className === test) console.log(` ${isAdding ? '+' : '-'} ${className} ${(eachClassUsages.get(className) || 0) + usage}`, target)
|
|
90
|
+
eachClassUsages.set(className, (eachClassUsages.get(className) || 0) + usage);
|
|
91
|
+
});
|
|
204
92
|
};
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
} else {
|
|
209
|
-
correctionOfClassName[className] = 1;
|
|
93
|
+
const updateElementTree = (element, adding)=>{
|
|
94
|
+
if (element.isConnected) {
|
|
95
|
+
updatedConnectedElements.add(element);
|
|
210
96
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
} else if (Object.prototype.hasOwnProperty.call(this.classesUsage, className)) {
|
|
216
|
-
correctionOfClassName[className] = -1;
|
|
97
|
+
updatedElements.add(element);
|
|
98
|
+
updateClassUsage(element.classList, adding);
|
|
99
|
+
for (const child of element.children){
|
|
100
|
+
updateElementTree(child, adding);
|
|
217
101
|
}
|
|
218
102
|
};
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
103
|
+
// console.log('///')
|
|
104
|
+
mutationRecords.forEach((mutation)=>{
|
|
105
|
+
const target = mutation.target;
|
|
106
|
+
switch(mutation.type){
|
|
107
|
+
case 'attributes':
|
|
108
|
+
const oldClassList = mutation.oldValue ? mutation.oldValue.split(/\s+/) : [];
|
|
109
|
+
const newClassList = target.classList;
|
|
110
|
+
newClassList.forEach((c)=>{
|
|
111
|
+
if (!oldClassList.includes(c)) ;
|
|
112
|
+
});
|
|
113
|
+
break;
|
|
229
114
|
}
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
* According to this history,
|
|
237
|
-
* MutationObserver was designed to work that way.
|
|
238
|
-
* Any call to setAttribute triggers a mutation,
|
|
239
|
-
* regardless of whether the value is being changed or set to the current value
|
|
240
|
-
*/ if (attributeMutationRecords.find((eachAttributeMutationRecord)=>eachAttributeMutationRecord.target === target)) {
|
|
241
|
-
continue;
|
|
242
|
-
} else {
|
|
115
|
+
});
|
|
116
|
+
// console.log('///')
|
|
117
|
+
mutationRecords.forEach((mutation)=>{
|
|
118
|
+
const target = mutation.target;
|
|
119
|
+
switch(mutation.type){
|
|
120
|
+
case 'attributes':
|
|
243
121
|
/**
|
|
244
|
-
*
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
122
|
+
* We only need to determine the first attribute record of the same target,
|
|
123
|
+
* because the first record has the original old class name.
|
|
124
|
+
*
|
|
125
|
+
* The target is skipped if it is contained in the unhandled childList.
|
|
126
|
+
*/ if (updatedAttrElements.has(target) || updatedElements.has(target)) return;
|
|
127
|
+
updatedAttrElements.add(target);
|
|
128
|
+
const oldClassList = mutation.oldValue ? mutation.oldValue.split(/\s+/) : [];
|
|
129
|
+
const newClassList = target.classList;
|
|
130
|
+
const addedClasses = [];
|
|
131
|
+
newClassList.forEach((c)=>{
|
|
132
|
+
if (!oldClassList.includes(c)) addedClasses.push(c);
|
|
133
|
+
});
|
|
134
|
+
const removedClasses = oldClassList.filter((c)=>!newClassList.contains(c));
|
|
135
|
+
// if (addedClasses.length) console.log('[attribute]', '[add]', addedClasses, target)
|
|
136
|
+
if (addedClasses.length) updateClassUsage(addedClasses, true);
|
|
137
|
+
// if (removedClasses.length) console.log('[attribute]', '[remove]', removedClasses, target)
|
|
138
|
+
if (removedClasses.length) updateClassUsage(removedClasses, false);
|
|
139
|
+
break;
|
|
140
|
+
case 'childList':
|
|
141
|
+
if (updatedConnectedElements.has(target)) return;
|
|
142
|
+
// if (mutation.addedNodes.length) console.log('[childList]', '[add]', mutation.addedNodes)
|
|
143
|
+
mutation.addedNodes.forEach((node)=>'classList' in node && updateElementTree(node, true));
|
|
144
|
+
// if (mutation.removedNodes.length) console.log('[childList]', '[remove]', mutation.removedNodes)
|
|
145
|
+
mutation.removedNodes.forEach((node)=>'classList' in node && updateElementTree(node, false));
|
|
146
|
+
break;
|
|
254
147
|
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
*
|
|
266
|
-
* 該批 mutationRecords 中,某個 target 同時有 attribute 及 childList 的變更,
|
|
267
|
-
* 則以 childList 節點插入及移除的 target.className 為主
|
|
268
|
-
*/ const updated = updatedElements.includes(target);
|
|
269
|
-
const classNames = target.classList;
|
|
270
|
-
const oldClassNames = oldValue ? oldValue.split(' ') : [];
|
|
271
|
-
if (updated) {
|
|
272
|
-
if (target.isConnected) {
|
|
273
|
-
continue;
|
|
274
|
-
} else {
|
|
275
|
-
for (const oldClassName of oldClassNames){
|
|
276
|
-
if (!classNames.contains(oldClassName)) {
|
|
277
|
-
removeClassName(oldClassName);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
} else if (target.isConnected) {
|
|
282
|
-
classNames.forEach((className)=>{
|
|
283
|
-
if (!oldClassNames.includes(className)) {
|
|
284
|
-
addClassName(className);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
for (const oldClassName of oldClassNames){
|
|
288
|
-
if (!classNames.contains(oldClassName)) {
|
|
289
|
-
removeClassName(oldClassName);
|
|
290
|
-
}
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* Merge the class usage changes into the current class usage map.
|
|
151
|
+
*/ eachClassUsages.forEach((countChange, className)=>{
|
|
152
|
+
let currentCount = this.classUsages.get(className) || 0;
|
|
153
|
+
let newCount = currentCount + countChange;
|
|
154
|
+
if (newCount > 0) {
|
|
155
|
+
this.classUsages.set(className, newCount);
|
|
156
|
+
if (currentCount === 0) {
|
|
157
|
+
this.add(className);
|
|
291
158
|
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
for(const className in correctionOfClassName){
|
|
295
|
-
const correction = correctionOfClassName[className];
|
|
296
|
-
const count = (this.classesUsage[className] || 0) + correction;
|
|
297
|
-
if (count === 0) {
|
|
298
|
-
// remove
|
|
299
|
-
delete this.classesUsage[className];
|
|
300
|
-
/**
|
|
301
|
-
* class name 從 DOM tree 中被移除,
|
|
302
|
-
* 匹配並刪除對應的 rule
|
|
303
|
-
*/ this.delete(className);
|
|
304
159
|
} else {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 新 class name 被 connected 至 DOM tree,
|
|
309
|
-
* 匹配並創建對應的 Rule
|
|
310
|
-
*/ this.add(className);
|
|
311
|
-
}
|
|
312
|
-
this.classesUsage[className] = count;
|
|
160
|
+
this.classUsages.delete(className);
|
|
161
|
+
this.remove(className);
|
|
313
162
|
}
|
|
314
|
-
}
|
|
163
|
+
});
|
|
164
|
+
// start: debug
|
|
165
|
+
// const safeClassUsages: any = {};
|
|
166
|
+
// ((this.root.constructor.name === 'HTMLDocument') ? this.host : this.container)
|
|
167
|
+
// .querySelectorAll('[class]')
|
|
168
|
+
// .forEach((element) => {
|
|
169
|
+
// element.classList.forEach((className) => {
|
|
170
|
+
// if (Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
|
|
171
|
+
// safeClassUsages[className]++
|
|
172
|
+
// } else {
|
|
173
|
+
// safeClassUsages[className] = 1
|
|
174
|
+
// }
|
|
175
|
+
// })
|
|
176
|
+
// })
|
|
177
|
+
// this.host.classList.forEach((className) => {
|
|
178
|
+
// if (Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
|
|
179
|
+
// safeClassUsages[className]++
|
|
180
|
+
// } else {
|
|
181
|
+
// safeClassUsages[className] = 1
|
|
182
|
+
// }
|
|
183
|
+
// })
|
|
184
|
+
// // 與 this.classUsages 比較並且打印不同的部分
|
|
185
|
+
// for (const className in safeClassUsages) {
|
|
186
|
+
// if (this.classUsages.get(className) !== safeClassUsages[className]) {
|
|
187
|
+
// throw new Error(`[css] ${className} ${this.classUsages.get(className)} (correct: ${safeClassUsages[className]})`)
|
|
188
|
+
// }
|
|
189
|
+
// }
|
|
190
|
+
// end: debug
|
|
315
191
|
});
|
|
316
192
|
this.observer.observe(this.root, {
|
|
317
|
-
...options,
|
|
318
193
|
attributes: true,
|
|
319
194
|
attributeOldValue: true,
|
|
320
195
|
attributeFilter: [
|
|
321
196
|
'class'
|
|
322
|
-
]
|
|
197
|
+
],
|
|
198
|
+
childList: true,
|
|
199
|
+
subtree: true
|
|
323
200
|
});
|
|
324
|
-
this.
|
|
201
|
+
if (!this.progressive) {
|
|
202
|
+
this.host.style.removeProperty('display');
|
|
203
|
+
}
|
|
325
204
|
// @ts-ignore
|
|
326
205
|
this.observing = true;
|
|
327
206
|
return this;
|
|
328
207
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
208
|
+
hydrate(nativeCSSRules) {
|
|
209
|
+
const cssSyntaxLayerBlockRules = [];
|
|
210
|
+
for(let i = 0; i < nativeCSSRules.length; i++){
|
|
211
|
+
const eachNativeCSSRule = nativeCSSRules[i];
|
|
212
|
+
if (eachNativeCSSRule.constructor.name === 'CSSLayerBlockRule') {
|
|
213
|
+
const cssLayerBlockRule = eachNativeCSSRule;
|
|
214
|
+
if (eachNativeCSSRule.name === 'theme') {
|
|
215
|
+
this.themeLayer.native = cssLayerBlockRule;
|
|
216
|
+
let variableRule;
|
|
217
|
+
let lastVariableName;
|
|
218
|
+
for(let j = 0; j < cssLayerBlockRule.cssRules.length; j++){
|
|
219
|
+
const cssRule = cssLayerBlockRule.cssRules[j];
|
|
220
|
+
const variableCSSRule = cssRule.constructor.name === 'CSSMediaRule' ? cssRule.cssRules[0] : cssRule;
|
|
221
|
+
const variableName = variableCSSRule.style[0].slice(2);
|
|
222
|
+
if (variableName !== lastVariableName) {
|
|
223
|
+
lastVariableName = variableName;
|
|
224
|
+
variableRule = new Rule(variableName);
|
|
225
|
+
this.themeLayer.rules.push(variableRule);
|
|
226
|
+
this.themeLayer.usages[variableRule.name] = 0;
|
|
227
|
+
}
|
|
228
|
+
variableRule?.nodes.push({
|
|
229
|
+
native: cssRule,
|
|
230
|
+
text: cssRule.cssText
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
if (this.themeLayer.rules.length) this.rules.push(this.themeLayer);
|
|
234
|
+
} else {
|
|
235
|
+
cssSyntaxLayerBlockRules.push(cssLayerBlockRule);
|
|
236
|
+
}
|
|
237
|
+
} else if (eachNativeCSSRule.constructor.name === 'CSSLayerStatementRule') {
|
|
238
|
+
this.layerStatementRule.nodes[0].native = eachNativeCSSRule;
|
|
239
|
+
} else if (eachNativeCSSRule.constructor.name === 'CSSKeyframesRule') {
|
|
240
|
+
const keyframsRule = eachNativeCSSRule;
|
|
241
|
+
const animationRule = new Rule(keyframsRule.name, [
|
|
242
|
+
{
|
|
243
|
+
native: keyframsRule,
|
|
244
|
+
text: keyframsRule.cssText
|
|
245
|
+
}
|
|
246
|
+
]);
|
|
247
|
+
this.animationsNonLayer.rules.push(animationRule);
|
|
248
|
+
this.rules.push(animationRule);
|
|
249
|
+
this.animationsNonLayer.usages[animationRule.name] = 0;
|
|
336
250
|
}
|
|
337
251
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
252
|
+
for (const cssLayerBlockRule of cssSyntaxLayerBlockRules){
|
|
253
|
+
const handleSyntaxLayer = (layer)=>{
|
|
254
|
+
layer.native = cssLayerBlockRule;
|
|
255
|
+
for(let j = 0; j < cssLayerBlockRule.cssRules.length; j++){
|
|
256
|
+
const cssRule = cssLayerBlockRule.cssRules[j];
|
|
257
|
+
const createSyntaxRule = (cssRule)=>{
|
|
258
|
+
if (cssRule.selectorText) {
|
|
259
|
+
const syntaxRule = this.createFromSelectorText(cssRule.selectorText)[0];
|
|
260
|
+
if (syntaxRule) return syntaxRule;
|
|
261
|
+
} else if (cssRule.cssRules) {
|
|
262
|
+
for (const eachCSSRule of cssRule.cssRules){
|
|
263
|
+
const syntaxRule = createSyntaxRule(eachCSSRule);
|
|
264
|
+
if (syntaxRule) return syntaxRule;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
const syntaxRule = createSyntaxRule(cssRule);
|
|
269
|
+
if (syntaxRule) {
|
|
270
|
+
layer.rules.push(syntaxRule);
|
|
271
|
+
layer.insertVariables(syntaxRule);
|
|
272
|
+
layer.insertAnimations(syntaxRule);
|
|
273
|
+
for (const eachNode of syntaxRule.nodes){
|
|
274
|
+
if (!eachNode.native) eachNode.native = cssRule;
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
cssLayerBlockRule.deleteRule?.(j--);
|
|
278
|
+
console.error(`Cannot recognize the CSS rule in the ${layer.name} layer. \`${cssRule.cssText}\` (https://rc.css.master.co/messages/hydration-errors)`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
for (const eachRule of layer.rules){
|
|
282
|
+
for(let k = eachRule.nodes.length - 1; k >= 0; k--){
|
|
283
|
+
if (!eachRule.nodes[k].native) {
|
|
284
|
+
eachRule.nodes.splice(k, 1);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (layer.rules.length) this.rules.push(layer);
|
|
289
|
+
};
|
|
290
|
+
switch(cssLayerBlockRule.name){
|
|
291
|
+
case 'base':
|
|
292
|
+
handleSyntaxLayer(this.baseLayer);
|
|
293
|
+
break;
|
|
294
|
+
case 'preset':
|
|
295
|
+
handleSyntaxLayer(this.presetLayer);
|
|
296
|
+
break;
|
|
297
|
+
case 'components':
|
|
298
|
+
this.componentsLayer.native = cssLayerBlockRule;
|
|
299
|
+
let stylePreText;
|
|
300
|
+
const createSyntaxRules = (cssRule)=>{
|
|
301
|
+
if (cssRule.selectorText) {
|
|
302
|
+
const syntaxRules = this.createFromSelectorText(cssRule.selectorText);
|
|
303
|
+
if (syntaxRules.length) {
|
|
304
|
+
stylePreText = cssRule.selectorText + '{';
|
|
305
|
+
return syntaxRules;
|
|
306
|
+
}
|
|
307
|
+
} else if (cssRule.cssRules) {
|
|
308
|
+
for (const eachCSSRule of cssRule.cssRules){
|
|
309
|
+
const syntaxRules = this.createFromSelectorText(eachCSSRule.selectorText);
|
|
310
|
+
if (syntaxRules) return syntaxRules;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
for(let j = 0; j < cssLayerBlockRule.cssRules.length; j++){
|
|
315
|
+
const cssRule = cssLayerBlockRule.cssRules[j];
|
|
316
|
+
const syntaxRules = createSyntaxRules(cssRule);
|
|
317
|
+
if (syntaxRules) {
|
|
318
|
+
let matched = false;
|
|
319
|
+
for (const eachSyntaxRule of syntaxRules){
|
|
320
|
+
for (const node of eachSyntaxRule.nodes){
|
|
321
|
+
if (!node.native && node.text.includes(stylePreText)) {
|
|
322
|
+
node.native = cssRule;
|
|
323
|
+
if (!this.componentsLayer.rules.includes(eachSyntaxRule)) {
|
|
324
|
+
this.componentsLayer.rules.push(eachSyntaxRule);
|
|
325
|
+
this.componentsLayer.insertVariables(eachSyntaxRule);
|
|
326
|
+
this.componentsLayer.insertAnimations(eachSyntaxRule);
|
|
327
|
+
}
|
|
328
|
+
matched = true;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (matched) break;
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
cssLayerBlockRule?.deleteRule?.(j--);
|
|
336
|
+
console.error(`Cannot recognize the CSS rule in the components layer. \`${cssRule.cssText}\` (https://rc.css.master.co/messages/hydration-errors)`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
for (const eachRule of this.componentsLayer.rules){
|
|
340
|
+
for(let k = eachRule.nodes.length - 1; k >= 0; k--){
|
|
341
|
+
if (!eachRule.nodes[k].native) {
|
|
342
|
+
eachRule.nodes.splice(k, 1);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (this.componentsLayer.rules.length) this.rules.push(this.componentsLayer);
|
|
347
|
+
break;
|
|
348
|
+
case 'general':
|
|
349
|
+
handleSyntaxLayer(this.generalLayer);
|
|
350
|
+
break;
|
|
347
351
|
}
|
|
348
352
|
}
|
|
349
|
-
if (!this.progressive) {
|
|
350
|
-
this.style?.remove();
|
|
351
|
-
// @ts-ignore
|
|
352
|
-
this.style = null;
|
|
353
|
-
}
|
|
354
|
-
return this;
|
|
355
353
|
}
|
|
356
354
|
disconnect() {
|
|
355
|
+
if (!this.observing) return;
|
|
357
356
|
if (this.observer) {
|
|
358
357
|
this.observer.disconnect();
|
|
359
|
-
|
|
358
|
+
// @ts-expect-error readonly
|
|
359
|
+
this.observer = undefined;
|
|
360
360
|
}
|
|
361
361
|
// @ts-ignore
|
|
362
362
|
this.observing = false;
|
|
363
363
|
this.reset();
|
|
364
|
+
// @ts-expect-error
|
|
365
|
+
this.classUsages = {};
|
|
366
|
+
if (!this.progressive) {
|
|
367
|
+
this.style?.remove();
|
|
368
|
+
this.style = null;
|
|
369
|
+
}
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
refresh(customConfig = this.customConfig) {
|
|
373
|
+
if (!this.observing || !this.style.sheet) return this;
|
|
374
|
+
for(let i = 1; i <= this.style.sheet.cssRules.length - 1; i++){
|
|
375
|
+
this.style.sheet.deleteRule(i);
|
|
376
|
+
}
|
|
377
|
+
super.refresh(customConfig);
|
|
364
378
|
return this;
|
|
365
379
|
}
|
|
366
380
|
destroy() {
|