@master/css-runtime 2.0.0-rc.54 → 2.0.0-rc.55

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/index.cjs CHANGED
@@ -3,45 +3,40 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var css = require('@master/css');
6
+ var cssDevtoolsHook = require('@master/css-devtools-hook');
6
7
 
7
- class RuntimeCSS extends css.MasterCSS {
8
+ function registerGlobal(CSSRuntime) {
9
+ if (!globalThis.CSSRuntime) globalThis.CSSRuntime = CSSRuntime;
10
+ cssDevtoolsHook.installHook();
11
+ }
12
+
13
+ class CSSRuntime extends css.MasterCSS {
8
14
  root;
9
15
  customConfig;
10
- // @ts-expect-error
16
+ static instances = new WeakMap();
11
17
  host;
12
18
  observing;
13
19
  progressive;
14
- // @ts-expect-error
15
20
  container;
16
21
  observer;
17
22
  constructor(root = document, customConfig = css.config){
18
23
  super(customConfig), this.root = root, this.customConfig = customConfig, this.observing = false, this.progressive = false;
19
- this.init();
20
- this.supportVendors = new Set();
21
- const styleDeclaration = document.documentElement.style;
22
- if ('webkitTransform' in styleDeclaration) this.supportVendors.add('webkit');
23
- if ('MozTransform' in styleDeclaration) this.supportVendors.add('moz');
24
- if ('msTransform' in styleDeclaration) this.supportVendors.add('ms');
25
- if ('OTransform' in styleDeclaration) this.supportVendors.add('o');
26
- }
27
- init() {
28
- const existingRuntimeCSS = globalThis.runtimeCSSs.find((eachCSS)=>eachCSS.root === this.root);
29
- if (existingRuntimeCSS) throw new Error('Cannot create multiple RuntimeCSS instances for the same root element.');
30
- const rootConstructorName = this.root?.constructor.name;
24
+ const rootConstructorName = root?.constructor.name;
31
25
  if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
32
- // @ts-ignore
33
- this.root.defaultView.globalThis.runtimeCSS = this;
34
- // @ts-ignore readonly
26
+ this.root.defaultView.globalThis.cssRuntime = this;
35
27
  this.container = this.root.head;
36
- // @ts-ignore readonly
37
28
  this.host = this.root.documentElement;
38
29
  } else {
39
- // @ts-ignore readonly
40
30
  this.container = this.root;
41
- // @ts-ignore readonly
42
31
  this.host = this.root.host;
43
32
  }
44
- runtimeCSSs.push(this);
33
+ this.supportVendors = new Set();
34
+ const styleDeclaration = document.documentElement.style;
35
+ if ('webkitTransform' in styleDeclaration) this.supportVendors.add('webkit');
36
+ if ('MozTransform' in styleDeclaration) this.supportVendors.add('moz');
37
+ if ('msTransform' in styleDeclaration) this.supportVendors.add('ms');
38
+ if ('OTransform' in styleDeclaration) this.supportVendors.add('o');
39
+ globalThis.CSSRuntime.instances.set(this.root, this);
45
40
  }
46
41
  /**
47
42
  * Observe the DOM for changes and update the running stylesheet. (browser only)
@@ -70,10 +65,10 @@ class RuntimeCSS extends css.MasterCSS {
70
65
  const firstConnectedElementsClasses = new Map();
71
66
  const addClasses = (element)=>{
72
67
  element.classList.forEach((className)=>{
73
- if (this.classUsages.has(className)) {
74
- this.classUsages.set(className, this.classUsages.get(className) + 1);
68
+ if (this.classCounts.has(className)) {
69
+ this.classCounts.set(className, this.classCounts.get(className) + 1);
75
70
  } else {
76
- this.classUsages.set(className, 1);
71
+ this.classCounts.set(className, 1);
77
72
  this.add(className);
78
73
  }
79
74
  const classes = firstConnectedElementsClasses.get(element);
@@ -98,14 +93,14 @@ class RuntimeCSS extends css.MasterCSS {
98
93
  // const test = ''
99
94
  // if (test) {
100
95
  // console.log('')
101
- // console.log(`${test}: ${this.classUsages.get(test)}`)
96
+ // console.log(`${test}: ${this.classCounts.get(test)}`)
102
97
  // }
103
- const eachClassUsages = new Map();
98
+ const eachClassCounts = new Map();
104
99
  const targetFirstAttrMutationRecord = new Map();
105
- const updateClassUsage = (classes, isAdding = false)=>{
100
+ const updateClassCount = (classes, isAdding = false)=>{
106
101
  const usage = isAdding ? 1 : -1;
107
102
  classes.forEach((className)=>{
108
- eachClassUsages.set(className, (eachClassUsages.get(className) || 0) + usage);
103
+ eachClassCounts.set(className, (eachClassCounts.get(className) || 0) + usage);
109
104
  });
110
105
  };
111
106
  const connectedStatusMap = new Map();
@@ -148,12 +143,12 @@ class RuntimeCSS extends css.MasterCSS {
148
143
  targetFirstAttrMutationRecord.delete(target);
149
144
  }
150
145
  if (adding) {
151
- updateClassUsage(target.classList, adding);
146
+ updateClassCount(target.classList, adding);
152
147
  } else {
153
148
  if (firstAttrMutationRecord) {
154
- updateClassUsage(firstAttrMutationRecord.oldValue ? firstAttrMutationRecord.oldValue.split(/\s+/) : [], adding);
149
+ updateClassCount(firstAttrMutationRecord.oldValue ? firstAttrMutationRecord.oldValue.split(/\s+/) : [], adding);
155
150
  } else {
156
- updateClassUsage(target.classList, adding);
151
+ updateClassCount(target.classList, adding);
157
152
  }
158
153
  disconnectedStatusMap.forEach((disconnectedTargetStatus, disconnectedTarget)=>{
159
154
  if (disconnectedTargetStatus.mutationRecord.target === target && disconnectedTargetStatus.change !== 0) {
@@ -178,59 +173,33 @@ class RuntimeCSS extends css.MasterCSS {
178
173
  const removedClasses = oldClassList.filter((c)=>!newClassList.contains(c));
179
174
  if (addedClasses.length) {
180
175
  // console.log('[attribute]', '[add] ', addedClasses, target)
181
- updateClassUsage(addedClasses, true);
176
+ updateClassCount(addedClasses, true);
182
177
  }
183
178
  if (removedClasses.length) {
184
179
  // console.log('[attribute]', '[remove]', removedClasses, target)
185
- updateClassUsage(removedClasses, false);
180
+ updateClassCount(removedClasses, false);
186
181
  }
187
182
  });
188
183
  /**
189
184
  * Merge the class usage changes into the current class usage map.
190
- */ eachClassUsages.forEach((countChange, className)=>{
191
- let currentCount = this.classUsages.get(className) || 0;
185
+ */ eachClassCounts.forEach((countChange, className)=>{
186
+ let currentCount = this.classCounts.get(className) || 0;
192
187
  let newCount = currentCount + countChange;
193
188
  if (newCount > 0) {
194
- this.classUsages.set(className, newCount);
189
+ this.classCounts.set(className, newCount);
195
190
  if (currentCount === 0) {
196
191
  this.add(className);
197
192
  }
198
193
  } else {
199
- this.classUsages.delete(className);
194
+ this.classCounts.delete(className);
200
195
  this.remove(className);
201
196
  }
202
197
  });
203
- // start: debug
204
- // const safeClassUsages: any = {};
205
- // ((this.root.constructor.name === 'HTMLDocument') ? this.host : this.container)
206
- // .querySelectorAll('[class]')
207
- // .forEach((element) => {
208
- // element.classList.forEach((className) => {
209
- // if (Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
210
- // safeClassUsages[className]++
211
- // } else {
212
- // safeClassUsages[className] = 1
213
- // }
214
- // })
215
- // })
216
- // this.host.classList.forEach((className) => {
217
- // if (Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
218
- // safeClassUsages[className]++
219
- // } else {
220
- // safeClassUsages[className] = 1
221
- // }
222
- // })
223
- // for (const className in safeClassUsages) {
224
- // if (this.classUsages.get(className) !== safeClassUsages[className]) {
225
- // throw new Error(`[css] ${className} ${this.classUsages.get(className)} (correct: ${safeClassUsages[className]})`)
226
- // }
227
- // }
228
- // this.classUsages.forEach((count, className) => {
229
- // if (!Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
230
- // throw new Error(`[css] ${className} ${count} (correct: 0)`)
231
- // }
232
- // })
233
- // end: debug
198
+ globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('mutated', {
199
+ records: mutationRecords,
200
+ classCounts: eachClassCounts,
201
+ cssRuntime: this
202
+ });
234
203
  });
235
204
  this.observer.observe(this.root, {
236
205
  attributes: true,
@@ -361,7 +330,7 @@ class RuntimeCSS extends css.MasterCSS {
361
330
  // @ts-ignore
362
331
  this.observing = false;
363
332
  this.reset();
364
- this.classUsages.clear();
333
+ this.classCounts.clear();
365
334
  if (!this.progressive) {
366
335
  this.style?.remove();
367
336
  this.style = null;
@@ -378,25 +347,28 @@ class RuntimeCSS extends css.MasterCSS {
378
347
  }
379
348
  destroy() {
380
349
  this.disconnect();
381
- runtimeCSSs.splice(runtimeCSSs.indexOf(this), 1);
350
+ globalThis.CSSRuntime.instances.delete(this.root);
382
351
  return this;
383
352
  }
384
353
  }
385
- const runtimeCSSs = [];
386
- (()=>{
387
- globalThis.RuntimeCSS = RuntimeCSS;
388
- globalThis.runtimeCSSs = runtimeCSSs;
389
- })();
354
+ (function(CSSRuntime) {
355
+ registerGlobal(CSSRuntime);
356
+ })(CSSRuntime);
390
357
 
391
358
  /**
392
- * Initialize a new RuntimeCSS instance and observe the target root
359
+ * Initialize a new CSSRuntime instance and observe the target root
393
360
  * @param config master css config
394
- * @param targetRoot target root to observe
361
+ * @param root target root to observe
362
+ * @param autoObserve auto observe the target root
395
363
  * @returns master css instance
396
- */ function initCSSRuntime(config) {
397
- return new RuntimeCSS(document, config).observe();
364
+ */ function initCSSRuntime(config, root = document, autoObserve = true) {
365
+ let cssRuntime = globalThis.CSSRuntime.instances.get(root);
366
+ if (cssRuntime) return cssRuntime;
367
+ cssRuntime = new CSSRuntime(document, config);
368
+ if (autoObserve) cssRuntime.observe();
369
+ return cssRuntime;
398
370
  }
399
371
 
400
- exports.RuntimeCSS = RuntimeCSS;
401
- exports.default = RuntimeCSS;
372
+ exports.CSSRuntime = CSSRuntime;
373
+ exports.default = CSSRuntime;
402
374
  exports.initCSSRuntime = initCSSRuntime;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { RuntimeCSS, RuntimeCSS as default } from './core';
2
- export { default as initCSSRuntime } from './init-css-runtime';
1
+ export { default as CSSRuntime, default } from './core';
2
+ export { default as initCSSRuntime } from './init';
@@ -0,0 +1,443 @@
1
+ 'use strict';
2
+
3
+ var css = require('@master/css');
4
+ var cssDevtoolsHook = require('@master/css-devtools-hook');
5
+
6
+ const createLogger = (type)=>{
7
+ return (message, ...args)=>{
8
+ if (console[type]) {
9
+ console[type](`%cMaster CSS%c ${message}`, 'color: gray;', 'color: inherit;', ...args);
10
+ }
11
+ };
12
+ };
13
+ const loggers = {
14
+ debug: createLogger('debug'),
15
+ info: createLogger('info'),
16
+ warn: createLogger('warn'),
17
+ error: createLogger('error'),
18
+ trace: createLogger('trace'),
19
+ table: console.table,
20
+ group: console.group,
21
+ groupCollapsed: console.group,
22
+ groupEnd: console.groupEnd,
23
+ time: console.time,
24
+ timeEnd: console.timeEnd
25
+ };
26
+ const log = createLogger('log');
27
+ Object.assign(log, loggers);
28
+
29
+ function startDebug() {
30
+ log('debug mode is enabled by default in development.');
31
+ const hook = cssDevtoolsHook.installHook();
32
+ hook.on('mutated', ({ records, classCounts, cssRuntime })=>{
33
+ const actualClassCounts = {};
34
+ let errored = false;
35
+ const resolveClass = (className)=>{
36
+ if (Object.prototype.hasOwnProperty.call(actualClassCounts, className)) {
37
+ actualClassCounts[className]++;
38
+ } else {
39
+ actualClassCounts[className] = 1;
40
+ }
41
+ };
42
+ (cssRuntime.root.constructor.name === 'HTMLDocument' ? cssRuntime.host : cssRuntime.container).querySelectorAll('[class]').forEach((element)=>{
43
+ element.classList.forEach(resolveClass);
44
+ });
45
+ cssRuntime.host.classList.forEach(resolveClass);
46
+ for(const className in actualClassCounts){
47
+ const eachCount = cssRuntime.classCounts.get(className);
48
+ const eachActualCount = actualClassCounts[className];
49
+ if (eachCount !== eachActualCount) {
50
+ log.error(`Count mismatch for`, {
51
+ class: className,
52
+ expected: eachActualCount,
53
+ received: eachCount
54
+ });
55
+ errored = true;
56
+ }
57
+ }
58
+ cssRuntime.classCounts.forEach((eachCount, className)=>{
59
+ if (!Object.prototype.hasOwnProperty.call(actualClassCounts, className)) {
60
+ log.error(`Count mismatch for`, {
61
+ class: className,
62
+ expected: 0,
63
+ received: eachCount
64
+ });
65
+ errored = true;
66
+ }
67
+ });
68
+ if (errored) {
69
+ console.debug('Records:', records);
70
+ console.debug('Counts:', classCounts);
71
+ }
72
+ });
73
+ }
74
+
75
+ function registerGlobal(CSSRuntime) {
76
+ if (!globalThis.CSSRuntime) globalThis.CSSRuntime = CSSRuntime;
77
+ cssDevtoolsHook.installHook();
78
+ {
79
+ startDebug();
80
+ }
81
+ }
82
+
83
+ class CSSRuntime extends css.MasterCSS {
84
+ root;
85
+ customConfig;
86
+ static instances = new WeakMap();
87
+ host;
88
+ observing;
89
+ progressive;
90
+ container;
91
+ observer;
92
+ constructor(root = document, customConfig = css.config){
93
+ super(customConfig), this.root = root, this.customConfig = customConfig, this.observing = false, this.progressive = false;
94
+ const rootConstructorName = root?.constructor.name;
95
+ if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
96
+ this.root.defaultView.globalThis.cssRuntime = this;
97
+ this.container = this.root.head;
98
+ this.host = this.root.documentElement;
99
+ } else {
100
+ this.container = this.root;
101
+ this.host = this.root.host;
102
+ }
103
+ this.supportVendors = new Set();
104
+ const styleDeclaration = document.documentElement.style;
105
+ if ('webkitTransform' in styleDeclaration) this.supportVendors.add('webkit');
106
+ if ('MozTransform' in styleDeclaration) this.supportVendors.add('moz');
107
+ if ('msTransform' in styleDeclaration) this.supportVendors.add('ms');
108
+ if ('OTransform' in styleDeclaration) this.supportVendors.add('o');
109
+ globalThis.CSSRuntime.instances.set(this.root, this);
110
+ }
111
+ /**
112
+ * Observe the DOM for changes and update the running stylesheet. (browser only)
113
+ * @param options mutation observer options
114
+ * @returns this
115
+ */ observe() {
116
+ if (this.observing) return this;
117
+ if (this.root.styleSheets) for (const sheet of this.root.styleSheets){
118
+ const { ownerNode } = sheet;
119
+ if (ownerNode && ownerNode.id === 'master') {
120
+ this.style = ownerNode;
121
+ // @ts-ignore
122
+ this.progressive = true;
123
+ break;
124
+ }
125
+ }
126
+ if (this.progressive) {
127
+ this.hydrate(this.style.sheet.cssRules);
128
+ } else {
129
+ this.style = document.createElement('style');
130
+ this.style.id = 'master';
131
+ this.container.append(this.style);
132
+ this.style.sheet.insertRule(this.layerStatementRule.text);
133
+ this.layerStatementRule.nodes[0].native = this.style.sheet.cssRules.item(0);
134
+ }
135
+ const firstConnectedElementsClasses = new Map();
136
+ const addClasses = (element)=>{
137
+ element.classList.forEach((className)=>{
138
+ if (this.classCounts.has(className)) {
139
+ this.classCounts.set(className, this.classCounts.get(className) + 1);
140
+ } else {
141
+ this.classCounts.set(className, 1);
142
+ this.add(className);
143
+ }
144
+ const classes = firstConnectedElementsClasses.get(element);
145
+ if (classes) {
146
+ classes.push(className);
147
+ } else {
148
+ firstConnectedElementsClasses.set(element, [
149
+ className
150
+ ]);
151
+ }
152
+ });
153
+ };
154
+ addClasses(this.host);
155
+ /**
156
+ * 待所有 DOM 結構完成解析後,開始繪製 Rule 樣式
157
+ */ (this.root.constructor.name === 'HTMLDocument' ? this.host : this.container).querySelectorAll('[class]').forEach((element)=>{
158
+ addClasses(element);
159
+ });
160
+ // @ts-expect-error readonly
161
+ this.observer = new MutationObserver((mutationRecords)=>{
162
+ // console.clear()
163
+ // const test = ''
164
+ // if (test) {
165
+ // console.log('')
166
+ // console.log(`${test}: ${this.classCounts.get(test)}`)
167
+ // }
168
+ const eachClassCounts = new Map();
169
+ const targetFirstAttrMutationRecord = new Map();
170
+ const updateClassCount = (classes, isAdding = false)=>{
171
+ const usage = isAdding ? 1 : -1;
172
+ classes.forEach((className)=>{
173
+ eachClassCounts.set(className, (eachClassCounts.get(className) || 0) + usage);
174
+ });
175
+ };
176
+ const connectedStatusMap = new Map();
177
+ const disconnectedStatusMap = new Map();
178
+ const recordStatus = (target, mutationRecord, map, adding)=>{
179
+ const status = map.get(target);
180
+ if (status) {
181
+ status.change += adding ? 1 : -1;
182
+ status.mutationRecord = mutationRecord;
183
+ } else {
184
+ map.set(target, {
185
+ change: adding ? 1 : -1,
186
+ mutationRecord
187
+ });
188
+ }
189
+ };
190
+ mutationRecords.forEach((mutationRecord)=>{
191
+ const target = mutationRecord.target;
192
+ switch(mutationRecord.type){
193
+ case 'attributes':
194
+ if (!targetFirstAttrMutationRecord.has(target)) {
195
+ targetFirstAttrMutationRecord.set(target, mutationRecord);
196
+ }
197
+ break;
198
+ case 'childList':
199
+ const targetStatusMap = target.isConnected ? connectedStatusMap : disconnectedStatusMap;
200
+ mutationRecord.addedNodes.forEach((node)=>'classList' in node && recordStatus(node, mutationRecord, targetStatusMap, true));
201
+ mutationRecord.removedNodes.forEach((node)=>'classList' in node && recordStatus(node, mutationRecord, targetStatusMap, false));
202
+ break;
203
+ }
204
+ });
205
+ const updatedTargetChangeMap = new Map();
206
+ const updateTarget = (target, adding)=>{
207
+ const change = updatedTargetChangeMap.get(target) || 0;
208
+ const newChange = change + (adding ? 1 : -1);
209
+ if (newChange >= -1 && newChange <= 1) {
210
+ updatedTargetChangeMap.set(target, newChange);
211
+ const firstAttrMutationRecord = targetFirstAttrMutationRecord.get(target);
212
+ if (firstAttrMutationRecord) {
213
+ targetFirstAttrMutationRecord.delete(target);
214
+ }
215
+ if (adding) {
216
+ updateClassCount(target.classList, adding);
217
+ } else {
218
+ if (firstAttrMutationRecord) {
219
+ updateClassCount(firstAttrMutationRecord.oldValue ? firstAttrMutationRecord.oldValue.split(/\s+/) : [], adding);
220
+ } else {
221
+ updateClassCount(target.classList, adding);
222
+ }
223
+ disconnectedStatusMap.forEach((disconnectedTargetStatus, disconnectedTarget)=>{
224
+ if (disconnectedTargetStatus.mutationRecord.target === target && disconnectedTargetStatus.change !== 0) {
225
+ updateTarget(disconnectedTarget, disconnectedTargetStatus.change > 0);
226
+ }
227
+ });
228
+ }
229
+ for (const child of target.children){
230
+ updateTarget(child, adding);
231
+ }
232
+ }
233
+ };
234
+ connectedStatusMap.forEach(({ change }, target)=>change !== 0 && updateTarget(target, change > 0));
235
+ targetFirstAttrMutationRecord.forEach((mutation, target)=>{
236
+ if (!target.isConnected) return;
237
+ const oldClassList = mutation.oldValue ? mutation.oldValue.split(/\s+/) : [];
238
+ const newClassList = target.classList;
239
+ const addedClasses = [];
240
+ newClassList.forEach((c)=>{
241
+ if (!oldClassList.includes(c)) addedClasses.push(c);
242
+ });
243
+ const removedClasses = oldClassList.filter((c)=>!newClassList.contains(c));
244
+ if (addedClasses.length) {
245
+ // console.log('[attribute]', '[add] ', addedClasses, target)
246
+ updateClassCount(addedClasses, true);
247
+ }
248
+ if (removedClasses.length) {
249
+ // console.log('[attribute]', '[remove]', removedClasses, target)
250
+ updateClassCount(removedClasses, false);
251
+ }
252
+ });
253
+ /**
254
+ * Merge the class usage changes into the current class usage map.
255
+ */ eachClassCounts.forEach((countChange, className)=>{
256
+ let currentCount = this.classCounts.get(className) || 0;
257
+ let newCount = currentCount + countChange;
258
+ if (newCount > 0) {
259
+ this.classCounts.set(className, newCount);
260
+ if (currentCount === 0) {
261
+ this.add(className);
262
+ }
263
+ } else {
264
+ this.classCounts.delete(className);
265
+ this.remove(className);
266
+ }
267
+ });
268
+ globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('mutated', {
269
+ records: mutationRecords,
270
+ classCounts: eachClassCounts,
271
+ cssRuntime: this
272
+ });
273
+ });
274
+ this.observer.observe(this.root, {
275
+ attributes: true,
276
+ attributeOldValue: true,
277
+ attributeFilter: [
278
+ 'class'
279
+ ],
280
+ childList: true,
281
+ subtree: true
282
+ });
283
+ if (!this.progressive) {
284
+ this.host.style.removeProperty('display');
285
+ }
286
+ // @ts-ignore
287
+ this.observing = true;
288
+ return this;
289
+ }
290
+ hydrate(nativeLayerRules) {
291
+ const cssLayerRules = [];
292
+ const checkSheet = new CSSStyleSheet();
293
+ for(let i = 0; i < nativeLayerRules.length; i++){
294
+ const eachNativeCSSRule = nativeLayerRules[i];
295
+ if (eachNativeCSSRule.constructor.name === 'CSSLayerBlockRule') {
296
+ const eachCSSLayerRule = eachNativeCSSRule;
297
+ if (eachNativeCSSRule.name === 'theme') {
298
+ this.themeLayer.native = eachCSSLayerRule;
299
+ let variableRule;
300
+ let lastVariableName;
301
+ for(let j = 0; j < eachCSSLayerRule.cssRules.length; j++){
302
+ const cssRule = eachCSSLayerRule.cssRules[j];
303
+ const variableCSSRule = cssRule.constructor.name === 'CSSMediaRule' ? cssRule.cssRules[0] : cssRule;
304
+ const variableName = variableCSSRule.style[0].slice(2);
305
+ if (variableName !== lastVariableName) {
306
+ lastVariableName = variableName;
307
+ variableRule = new css.Rule(variableName);
308
+ this.themeLayer.rules.push(variableRule);
309
+ this.themeLayer.usages[variableRule.name] = 0;
310
+ }
311
+ variableRule?.nodes.push({
312
+ native: cssRule,
313
+ text: cssRule.cssText
314
+ });
315
+ }
316
+ if (this.themeLayer.rules.length) this.rules.push(this.themeLayer);
317
+ } else {
318
+ cssLayerRules.push(eachCSSLayerRule);
319
+ }
320
+ } else if (eachNativeCSSRule.constructor.name === 'CSSLayerStatementRule') {
321
+ this.layerStatementRule.nodes[0].native = eachNativeCSSRule;
322
+ } else if (eachNativeCSSRule.constructor.name === 'CSSKeyframesRule') {
323
+ const keyframsRule = eachNativeCSSRule;
324
+ const animationRule = new css.Rule(keyframsRule.name, [
325
+ {
326
+ native: keyframsRule,
327
+ text: keyframsRule.cssText
328
+ }
329
+ ]);
330
+ this.animationsNonLayer.rules.push(animationRule);
331
+ this.rules.push(animationRule);
332
+ this.animationsNonLayer.usages[animationRule.name] = 0;
333
+ }
334
+ }
335
+ for (const eachCSSLayerRule of cssLayerRules){
336
+ const nativeLayerRules = Array.from(eachCSSLayerRule.cssRules);
337
+ let layer;
338
+ switch(eachCSSLayerRule.name){
339
+ case 'base':
340
+ layer = this.baseLayer;
341
+ break;
342
+ case 'preset':
343
+ layer = this.presetLayer;
344
+ break;
345
+ case 'components':
346
+ layer = this.componentsLayer;
347
+ break;
348
+ default:
349
+ layer = this.generalLayer;
350
+ break;
351
+ }
352
+ layer.native = eachCSSLayerRule;
353
+ for (const eachNativeRule of nativeLayerRules){
354
+ const selectorText = this.getSelectorText(eachNativeRule);
355
+ if (!selectorText) {
356
+ console.error(`Cannot get the selector text from \`${eachNativeRule.cssText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
357
+ continue;
358
+ }
359
+ const createdRules = this.createFromSelectorText(selectorText);
360
+ if (createdRules) {
361
+ for (const createdRule of createdRules){
362
+ layer.rules.push(createdRule);
363
+ layer.insertVariables(createdRule);
364
+ layer.insertAnimations(createdRule);
365
+ createdRule.nodes.forEach((node)=>{
366
+ const createdNodeNativeRule = checkSheet.cssRules.item(checkSheet.insertRule(node.text));
367
+ if (createdNodeNativeRule) {
368
+ for (const eachFindingNativeRule of nativeLayerRules){
369
+ if (createdNodeNativeRule.cssText === eachFindingNativeRule.cssText) {
370
+ node.native = eachFindingNativeRule;
371
+ nativeLayerRules.splice(nativeLayerRules.indexOf(eachFindingNativeRule), 1);
372
+ return;
373
+ }
374
+ }
375
+ }
376
+ console.error(`Cannot retrieve CSS rule for \`${node.selectorText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
377
+ });
378
+ }
379
+ } else {
380
+ console.error(`Cannot recognize \`${eachNativeRule.cssText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
381
+ }
382
+ }
383
+ if (layer.rules.length) this.rules.push(layer);
384
+ }
385
+ }
386
+ getSelectorText(cssRule) {
387
+ if ('selectorText' in cssRule) {
388
+ return cssRule.selectorText;
389
+ } else if ('cssRules' in cssRule) {
390
+ return this.getSelectorText(cssRule.cssRules.item(0));
391
+ }
392
+ }
393
+ disconnect() {
394
+ if (!this.observing) return;
395
+ if (this.observer) {
396
+ this.observer.disconnect();
397
+ // @ts-expect-error readonly
398
+ this.observer = undefined;
399
+ }
400
+ // @ts-ignore
401
+ this.observing = false;
402
+ this.reset();
403
+ this.classCounts.clear();
404
+ if (!this.progressive) {
405
+ this.style?.remove();
406
+ this.style = null;
407
+ }
408
+ return this;
409
+ }
410
+ refresh(customConfig = this.customConfig) {
411
+ if (!this.observing || !this.style.sheet) return this;
412
+ for(let i = 1; i <= this.style.sheet.cssRules.length - 1; i++){
413
+ this.style.sheet.deleteRule(i);
414
+ }
415
+ super.refresh(customConfig);
416
+ return this;
417
+ }
418
+ destroy() {
419
+ this.disconnect();
420
+ globalThis.CSSRuntime.instances.delete(this.root);
421
+ return this;
422
+ }
423
+ }
424
+ (function(CSSRuntime) {
425
+ registerGlobal(CSSRuntime);
426
+ })(CSSRuntime);
427
+
428
+ /**
429
+ * Initialize a new CSSRuntime instance and observe the target root
430
+ * @param config master css config
431
+ * @param root target root to observe
432
+ * @param autoObserve auto observe the target root
433
+ * @returns master css instance
434
+ */ function initCSSRuntime(config, root = document, autoObserve = true) {
435
+ let cssRuntime = globalThis.CSSRuntime.instances.get(root);
436
+ if (cssRuntime) return cssRuntime;
437
+ cssRuntime = new CSSRuntime(document, config);
438
+ if (autoObserve) cssRuntime.observe();
439
+ return cssRuntime;
440
+ }
441
+
442
+ exports.CSSRuntime = CSSRuntime;
443
+ exports.initCSSRuntime = initCSSRuntime;
@@ -0,0 +1 @@
1
+ export * from './index';