@master/css-runtime 2.0.0-rc.47 → 2.0.0-rc.48
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 +5 -5
- package/dist/global.min.js +1 -1
- package/dist/index.cjs +165 -144
- package/dist/index.mjs +166 -145
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -14,7 +14,8 @@ class RuntimeCSS extends css.MasterCSS {
|
|
|
14
14
|
observer;
|
|
15
15
|
constructor(root = document, customConfig = css.config){
|
|
16
16
|
super(customConfig), this.root = root, this.customConfig = customConfig, this.observing = false, this.progressive = false;
|
|
17
|
-
|
|
17
|
+
const existingRuntimeCSS = globalThis.runtimeCSSs.find((eachCSS)=>eachCSS.root === this.root);
|
|
18
|
+
if (existingRuntimeCSS) throw new Error('Cannot create multiple RuntimeCSS instances for the same root element.');
|
|
18
19
|
const rootConstructorName = this.root?.constructor.name;
|
|
19
20
|
if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
|
|
20
21
|
// @ts-ignore
|
|
@@ -35,138 +36,24 @@ class RuntimeCSS extends css.MasterCSS {
|
|
|
35
36
|
subtree: true,
|
|
36
37
|
childList: true
|
|
37
38
|
}) {
|
|
38
|
-
if (this.observing
|
|
39
|
-
if (
|
|
40
|
-
console.warn('Cannot observe the same root element repeatedly.');
|
|
41
|
-
return this;
|
|
42
|
-
}
|
|
43
|
-
if (this.root?.styleSheets) for (const sheet of this.root.styleSheets){
|
|
39
|
+
if (this.observing) return this;
|
|
40
|
+
if (this.root.styleSheets) for (const sheet of this.root.styleSheets){
|
|
44
41
|
const { ownerNode } = sheet;
|
|
45
42
|
if (ownerNode && ownerNode.id === 'master') {
|
|
46
|
-
// @ts-ignore
|
|
47
43
|
this.style = ownerNode;
|
|
48
44
|
// @ts-ignore
|
|
49
45
|
this.progressive = true;
|
|
50
46
|
break;
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
|
-
if (this.
|
|
54
|
-
|
|
55
|
-
for(; index < this.style.sheet.cssRules.length; index++){
|
|
56
|
-
const eachCSSRule = this.style.sheet.cssRules[index];
|
|
57
|
-
switch(eachCSSRule.constructor.name){
|
|
58
|
-
case 'CSSKeyframesRule':
|
|
59
|
-
continue;
|
|
60
|
-
case 'CSSMediaRule':
|
|
61
|
-
const result = /\(prefers-color-scheme: ?(.*?)\)/.exec(eachCSSRule.conditionText);
|
|
62
|
-
if (result) {
|
|
63
|
-
const firstCSSRule = eachCSSRule.cssRules[0];
|
|
64
|
-
if (firstCSSRule?.constructor.name === 'CSSStyleRule' && firstCSSRule.selectorText === ':root') {
|
|
65
|
-
this.pushVariableNativeRule(result[1], firstCSSRule);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
break;
|
|
70
|
-
case 'CSSStyleRule':
|
|
71
|
-
const selectorText = eachCSSRule.selectorText;
|
|
72
|
-
if (eachCSSRule.style.length) {
|
|
73
|
-
let isVariablesRule = true;
|
|
74
|
-
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
75
|
-
for(let i = 0; i < eachCSSRule.style.length; i++){
|
|
76
|
-
if (!eachCSSRule.style[i]?.startsWith('--')) {
|
|
77
|
-
isVariablesRule = false;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (isVariablesRule) {
|
|
82
|
-
if (selectorText === ':root') {
|
|
83
|
-
this.pushVariableNativeRule('', eachCSSRule);
|
|
84
|
-
continue;
|
|
85
|
-
} else {
|
|
86
|
-
const result = /:host(.*?)/.exec(selectorText);
|
|
87
|
-
if (result) {
|
|
88
|
-
this.pushVariableNativeRule(result[1], eachCSSRule);
|
|
89
|
-
continue;
|
|
90
|
-
} else if (!selectorText.startsWith('.\\$')) {
|
|
91
|
-
const [mode] = selectorText.split(',');
|
|
92
|
-
this.pushVariableNativeRule(mode.slice(1), eachCSSRule);
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
for(; index < this.style.sheet.cssRules.length; index++){
|
|
103
|
-
const getRule = (cssRule)=>{
|
|
104
|
-
if (cssRule.selectorText) {
|
|
105
|
-
const selectorTexts = cssRule.selectorText.split(', ');
|
|
106
|
-
const escapedClassNames = selectorTexts[0].split(' ');
|
|
107
|
-
for (const eachSelectorText of escapedClassNames){
|
|
108
|
-
if (eachSelectorText[0] === '.') {
|
|
109
|
-
const escapedClassName = eachSelectorText.slice(1);
|
|
110
|
-
let className = '';
|
|
111
|
-
for(let j = 0; j < escapedClassName.length; j++){
|
|
112
|
-
const char = escapedClassName[j];
|
|
113
|
-
const nextChar = escapedClassName[j + 1];
|
|
114
|
-
if (char === '\\') {
|
|
115
|
-
j++;
|
|
116
|
-
if (nextChar !== '\\') {
|
|
117
|
-
className += nextChar;
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
} else if ([
|
|
121
|
-
',',
|
|
122
|
-
'.',
|
|
123
|
-
'#',
|
|
124
|
-
'[',
|
|
125
|
-
'!',
|
|
126
|
-
'*',
|
|
127
|
-
'>',
|
|
128
|
-
'+',
|
|
129
|
-
'~',
|
|
130
|
-
':',
|
|
131
|
-
'@'
|
|
132
|
-
].includes(char)) {
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
className += char;
|
|
136
|
-
}
|
|
137
|
-
if (!Object.prototype.hasOwnProperty.call(this.ruleBy, className) && !Object.prototype.hasOwnProperty.call(this.styles, className)) {
|
|
138
|
-
const currentRule = this.generate(className)[0];
|
|
139
|
-
if (currentRule) return currentRule;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
} else if (cssRule.cssRules) {
|
|
144
|
-
for (const rule of cssRule.cssRules){
|
|
145
|
-
const currentRule = getRule(rule);
|
|
146
|
-
if (currentRule) return currentRule;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
const rule = getRule(this.style.sheet.cssRules[index]);
|
|
151
|
-
if (rule) {
|
|
152
|
-
this.syntaxes.push(rule);
|
|
153
|
-
this.ruleBy[rule.className] = rule;
|
|
154
|
-
for(let i = 0; i < rule.natives.length; i++){
|
|
155
|
-
rule.natives[i].cssRule = this.style.sheet.cssRules[index + i];
|
|
156
|
-
}
|
|
157
|
-
index += rule.natives.length - 1;
|
|
158
|
-
// variables
|
|
159
|
-
this.handleRuleWithVariableNames(rule, true);
|
|
160
|
-
// animations
|
|
161
|
-
this.handleRuleWithAnimationNames(rule, true);
|
|
162
|
-
rule.definition.insert?.call(rule);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
49
|
+
if (this.progressive) {
|
|
50
|
+
this.hydrate(this.style.sheet.cssRules);
|
|
165
51
|
} else {
|
|
166
|
-
// @ts-ignore
|
|
167
52
|
this.style = document.createElement('style');
|
|
168
53
|
this.style.id = 'master';
|
|
169
54
|
this.container.append(this.style);
|
|
55
|
+
this.style.sheet.insertRule(this.layerStatementRule.text);
|
|
56
|
+
this.layerStatementRule.nodes[0].native = this.style.sheet.cssRules.item(0);
|
|
170
57
|
}
|
|
171
58
|
const handleClassList = (classList)=>{
|
|
172
59
|
classList.forEach((className)=>{
|
|
@@ -304,7 +191,7 @@ class RuntimeCSS extends css.MasterCSS {
|
|
|
304
191
|
/**
|
|
305
192
|
* class name 從 DOM tree 中被移除,
|
|
306
193
|
* 匹配並刪除對應的 rule
|
|
307
|
-
*/ this.
|
|
194
|
+
*/ this.remove(className);
|
|
308
195
|
} else {
|
|
309
196
|
if (!Object.prototype.hasOwnProperty.call(this.classesUsage, className)) {
|
|
310
197
|
// add
|
|
@@ -330,34 +217,154 @@ class RuntimeCSS extends css.MasterCSS {
|
|
|
330
217
|
this.observing = true;
|
|
331
218
|
return this;
|
|
332
219
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
220
|
+
hydrate(nativeCSSRules) {
|
|
221
|
+
const cssSyntaxLayerBlockRules = [];
|
|
222
|
+
for(let i = 0; i < nativeCSSRules.length; i++){
|
|
223
|
+
const eachNativeCSSRule = nativeCSSRules[i];
|
|
224
|
+
if (eachNativeCSSRule.constructor.name === 'CSSLayerBlockRule') {
|
|
225
|
+
const cssLayerBlockRule = eachNativeCSSRule;
|
|
226
|
+
if (eachNativeCSSRule.name === 'theme') {
|
|
227
|
+
this.themeLayer.native = cssLayerBlockRule;
|
|
228
|
+
let variableRule;
|
|
229
|
+
let lastVariableName;
|
|
230
|
+
for(let j = 0; j < cssLayerBlockRule.cssRules.length; j++){
|
|
231
|
+
const cssRule = cssLayerBlockRule.cssRules[j];
|
|
232
|
+
const variableCSSRule = cssRule.constructor.name === 'CSSMediaRule' ? cssRule.cssRules[0] : cssRule;
|
|
233
|
+
const variableName = variableCSSRule.style[0].slice(2);
|
|
234
|
+
if (variableName !== lastVariableName) {
|
|
235
|
+
lastVariableName = variableName;
|
|
236
|
+
variableRule = new css.Rule(variableName);
|
|
237
|
+
this.themeLayer.rules.push(variableRule);
|
|
238
|
+
this.themeLayer.usages[variableRule.name] = 0;
|
|
239
|
+
}
|
|
240
|
+
variableRule?.nodes.push({
|
|
241
|
+
native: cssRule,
|
|
242
|
+
text: cssRule.cssText
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
if (this.themeLayer.rules.length) this.rules.push(this.themeLayer);
|
|
246
|
+
} else {
|
|
247
|
+
cssSyntaxLayerBlockRules.push(cssLayerBlockRule);
|
|
248
|
+
}
|
|
249
|
+
} else if (eachNativeCSSRule.constructor.name === 'CSSLayerStatementRule') {
|
|
250
|
+
this.layerStatementRule.nodes[0].native = eachNativeCSSRule;
|
|
251
|
+
} else if (eachNativeCSSRule.constructor.name === 'CSSKeyframesRule') {
|
|
252
|
+
const keyframsRule = eachNativeCSSRule;
|
|
253
|
+
const animationRule = new css.Rule(keyframsRule.name, [
|
|
254
|
+
{
|
|
255
|
+
native: keyframsRule,
|
|
256
|
+
text: keyframsRule.cssText
|
|
257
|
+
}
|
|
258
|
+
]);
|
|
259
|
+
this.animationsNonLayer.rules.push(animationRule);
|
|
260
|
+
this.rules.push(animationRule);
|
|
261
|
+
this.animationsNonLayer.usages[animationRule.name] = 0;
|
|
340
262
|
}
|
|
341
263
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
264
|
+
for (const cssLayerBlockRule of cssSyntaxLayerBlockRules){
|
|
265
|
+
const handleSyntaxLayer = (layer)=>{
|
|
266
|
+
layer.native = cssLayerBlockRule;
|
|
267
|
+
for(let j = 0; j < cssLayerBlockRule.cssRules.length; j++){
|
|
268
|
+
const cssRule = cssLayerBlockRule.cssRules[j];
|
|
269
|
+
const createSyntaxRule = (cssRule)=>{
|
|
270
|
+
if (cssRule.selectorText) {
|
|
271
|
+
const syntaxRule = this.createFromSelectorText(cssRule.selectorText)[0];
|
|
272
|
+
if (syntaxRule) return syntaxRule;
|
|
273
|
+
} else if (cssRule.cssRules) {
|
|
274
|
+
for (const eachCSSRule of cssRule.cssRules){
|
|
275
|
+
const syntaxRule = createSyntaxRule(eachCSSRule);
|
|
276
|
+
if (syntaxRule) return syntaxRule;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
const syntaxRule = createSyntaxRule(cssRule);
|
|
281
|
+
if (syntaxRule) {
|
|
282
|
+
layer.rules.push(syntaxRule);
|
|
283
|
+
layer.insertVariables(syntaxRule);
|
|
284
|
+
layer.insertAnimations(syntaxRule);
|
|
285
|
+
for (const eachNode of syntaxRule.nodes){
|
|
286
|
+
if (!eachNode.native) eachNode.native = cssRule;
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
cssLayerBlockRule.deleteRule?.(j--);
|
|
290
|
+
console.error(`Cannot recognize the CSS rule in the ${layer.name} layer. \`${cssRule.cssText}\` (https://rc.css.master.co/messages/hydration-errors)`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
for (const eachRule of layer.rules){
|
|
294
|
+
for(let k = eachRule.nodes.length - 1; k >= 0; k--){
|
|
295
|
+
if (!eachRule.nodes[k].native) {
|
|
296
|
+
eachRule.nodes.splice(k, 1);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (layer.rules.length) this.rules.push(layer);
|
|
301
|
+
};
|
|
302
|
+
switch(cssLayerBlockRule.name){
|
|
303
|
+
case 'base':
|
|
304
|
+
handleSyntaxLayer(this.baseLayer);
|
|
305
|
+
break;
|
|
306
|
+
case 'preset':
|
|
307
|
+
handleSyntaxLayer(this.presetLayer);
|
|
308
|
+
break;
|
|
309
|
+
case 'components':
|
|
310
|
+
this.stylesLayer.native = cssLayerBlockRule;
|
|
311
|
+
let stylePreText;
|
|
312
|
+
const createSyntaxRules = (cssRule)=>{
|
|
313
|
+
if (cssRule.selectorText) {
|
|
314
|
+
const syntaxRules = this.createFromSelectorText(cssRule.selectorText);
|
|
315
|
+
if (syntaxRules.length) {
|
|
316
|
+
stylePreText = cssRule.selectorText + '{';
|
|
317
|
+
return syntaxRules;
|
|
318
|
+
}
|
|
319
|
+
} else if (cssRule.cssRules) {
|
|
320
|
+
for (const eachCSSRule of cssRule.cssRules){
|
|
321
|
+
const syntaxRules = this.createFromSelectorText(eachCSSRule.selectorText);
|
|
322
|
+
if (syntaxRules) return syntaxRules;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
for(let j = 0; j < cssLayerBlockRule.cssRules.length; j++){
|
|
327
|
+
const cssRule = cssLayerBlockRule.cssRules[j];
|
|
328
|
+
const syntaxRules = createSyntaxRules(cssRule);
|
|
329
|
+
if (syntaxRules) {
|
|
330
|
+
let matched = false;
|
|
331
|
+
for (const eachSyntaxRule of syntaxRules){
|
|
332
|
+
for (const node of eachSyntaxRule.nodes){
|
|
333
|
+
if (!node.native && node.text.includes(stylePreText)) {
|
|
334
|
+
node.native = cssRule;
|
|
335
|
+
if (!this.stylesLayer.rules.includes(eachSyntaxRule)) {
|
|
336
|
+
this.stylesLayer.rules.push(eachSyntaxRule);
|
|
337
|
+
this.stylesLayer.insertVariables(eachSyntaxRule);
|
|
338
|
+
this.stylesLayer.insertAnimations(eachSyntaxRule);
|
|
339
|
+
}
|
|
340
|
+
matched = true;
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (matched) break;
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
cssLayerBlockRule?.deleteRule?.(j--);
|
|
348
|
+
console.error(`Cannot recognize the CSS rule in the components layer. \`${cssRule.cssText}\` (https://rc.css.master.co/messages/hydration-errors)`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
for (const eachRule of this.stylesLayer.rules){
|
|
352
|
+
for(let k = eachRule.nodes.length - 1; k >= 0; k--){
|
|
353
|
+
if (!eachRule.nodes[k].native) {
|
|
354
|
+
eachRule.nodes.splice(k, 1);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (this.stylesLayer.rules.length) this.rules.push(this.stylesLayer);
|
|
359
|
+
break;
|
|
360
|
+
case 'general':
|
|
361
|
+
handleSyntaxLayer(this.generalLayer);
|
|
362
|
+
break;
|
|
351
363
|
}
|
|
352
364
|
}
|
|
353
|
-
if (!this.progressive) {
|
|
354
|
-
this.style?.remove();
|
|
355
|
-
// @ts-ignore
|
|
356
|
-
this.style = null;
|
|
357
|
-
}
|
|
358
|
-
return this;
|
|
359
365
|
}
|
|
360
366
|
disconnect() {
|
|
367
|
+
if (!this.observing) return;
|
|
361
368
|
if (this.observer) {
|
|
362
369
|
this.observer.disconnect();
|
|
363
370
|
this.observer = null;
|
|
@@ -365,6 +372,20 @@ class RuntimeCSS extends css.MasterCSS {
|
|
|
365
372
|
// @ts-ignore
|
|
366
373
|
this.observing = false;
|
|
367
374
|
this.reset();
|
|
375
|
+
// @ts-expect-error
|
|
376
|
+
this.classesUsage = {};
|
|
377
|
+
if (!this.progressive) {
|
|
378
|
+
this.style?.remove();
|
|
379
|
+
this.style = null;
|
|
380
|
+
}
|
|
381
|
+
return this;
|
|
382
|
+
}
|
|
383
|
+
refresh(customConfig = this.customConfig) {
|
|
384
|
+
if (!this.observing || !this.style.sheet) return this;
|
|
385
|
+
for(let i = 1; i <= this.style.sheet.cssRules.length - 1; i++){
|
|
386
|
+
this.style.sheet.deleteRule(i);
|
|
387
|
+
}
|
|
388
|
+
super.refresh(customConfig);
|
|
368
389
|
return this;
|
|
369
390
|
}
|
|
370
391
|
destroy() {
|