@master/css-runtime 2.0.0-rc.53 → 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.mjs CHANGED
@@ -1,43 +1,38 @@
1
1
  import { MasterCSS, config, Rule } from '@master/css';
2
+ import { installHook } from '@master/css-devtools-hook';
2
3
 
3
- class RuntimeCSS extends MasterCSS {
4
+ function registerGlobal(CSSRuntime) {
5
+ if (!globalThis.CSSRuntime) globalThis.CSSRuntime = CSSRuntime;
6
+ installHook();
7
+ }
8
+
9
+ class CSSRuntime extends MasterCSS {
4
10
  root;
5
11
  customConfig;
6
- // @ts-expect-error
12
+ static instances = new WeakMap();
7
13
  host;
8
14
  observing;
9
15
  progressive;
10
- // @ts-expect-error
11
16
  container;
12
17
  observer;
13
18
  constructor(root = document, customConfig = config){
14
19
  super(customConfig), this.root = root, this.customConfig = customConfig, this.observing = false, this.progressive = false;
15
- this.init();
16
- this.supportVendors = new Set();
17
- const styleDeclaration = document.documentElement.style;
18
- if ('webkitTransform' in styleDeclaration) this.supportVendors.add('webkit');
19
- if ('MozTransform' in styleDeclaration) this.supportVendors.add('moz');
20
- if ('msTransform' in styleDeclaration) this.supportVendors.add('ms');
21
- if ('OTransform' in styleDeclaration) this.supportVendors.add('o');
22
- }
23
- init() {
24
- const existingRuntimeCSS = globalThis.runtimeCSSs.find((eachCSS)=>eachCSS.root === this.root);
25
- if (existingRuntimeCSS) throw new Error('Cannot create multiple RuntimeCSS instances for the same root element.');
26
- const rootConstructorName = this.root?.constructor.name;
20
+ const rootConstructorName = root?.constructor.name;
27
21
  if (rootConstructorName === 'HTMLDocument' || rootConstructorName === 'Document') {
28
- // @ts-ignore
29
- this.root.defaultView.globalThis.runtimeCSS = this;
30
- // @ts-ignore readonly
22
+ this.root.defaultView.globalThis.cssRuntime = this;
31
23
  this.container = this.root.head;
32
- // @ts-ignore readonly
33
24
  this.host = this.root.documentElement;
34
25
  } else {
35
- // @ts-ignore readonly
36
26
  this.container = this.root;
37
- // @ts-ignore readonly
38
27
  this.host = this.root.host;
39
28
  }
40
- runtimeCSSs.push(this);
29
+ this.supportVendors = new Set();
30
+ const styleDeclaration = document.documentElement.style;
31
+ if ('webkitTransform' in styleDeclaration) this.supportVendors.add('webkit');
32
+ if ('MozTransform' in styleDeclaration) this.supportVendors.add('moz');
33
+ if ('msTransform' in styleDeclaration) this.supportVendors.add('ms');
34
+ if ('OTransform' in styleDeclaration) this.supportVendors.add('o');
35
+ globalThis.CSSRuntime.instances.set(this.root, this);
41
36
  }
42
37
  /**
43
38
  * Observe the DOM for changes and update the running stylesheet. (browser only)
@@ -66,10 +61,10 @@ class RuntimeCSS extends MasterCSS {
66
61
  const firstConnectedElementsClasses = new Map();
67
62
  const addClasses = (element)=>{
68
63
  element.classList.forEach((className)=>{
69
- if (this.classUsages.has(className)) {
70
- this.classUsages.set(className, this.classUsages.get(className) + 1);
64
+ if (this.classCounts.has(className)) {
65
+ this.classCounts.set(className, this.classCounts.get(className) + 1);
71
66
  } else {
72
- this.classUsages.set(className, 1);
67
+ this.classCounts.set(className, 1);
73
68
  this.add(className);
74
69
  }
75
70
  const classes = firstConnectedElementsClasses.get(element);
@@ -94,14 +89,14 @@ class RuntimeCSS extends MasterCSS {
94
89
  // const test = ''
95
90
  // if (test) {
96
91
  // console.log('')
97
- // console.log(`${test}: ${this.classUsages.get(test)}`)
92
+ // console.log(`${test}: ${this.classCounts.get(test)}`)
98
93
  // }
99
- const eachClassUsages = new Map();
94
+ const eachClassCounts = new Map();
100
95
  const targetFirstAttrMutationRecord = new Map();
101
- const updateClassUsage = (classes, isAdding = false)=>{
96
+ const updateClassCount = (classes, isAdding = false)=>{
102
97
  const usage = isAdding ? 1 : -1;
103
98
  classes.forEach((className)=>{
104
- eachClassUsages.set(className, (eachClassUsages.get(className) || 0) + usage);
99
+ eachClassCounts.set(className, (eachClassCounts.get(className) || 0) + usage);
105
100
  });
106
101
  };
107
102
  const connectedStatusMap = new Map();
@@ -144,12 +139,12 @@ class RuntimeCSS extends MasterCSS {
144
139
  targetFirstAttrMutationRecord.delete(target);
145
140
  }
146
141
  if (adding) {
147
- updateClassUsage(target.classList, adding);
142
+ updateClassCount(target.classList, adding);
148
143
  } else {
149
144
  if (firstAttrMutationRecord) {
150
- updateClassUsage(firstAttrMutationRecord.oldValue ? firstAttrMutationRecord.oldValue.split(/\s+/) : [], adding);
145
+ updateClassCount(firstAttrMutationRecord.oldValue ? firstAttrMutationRecord.oldValue.split(/\s+/) : [], adding);
151
146
  } else {
152
- updateClassUsage(target.classList, adding);
147
+ updateClassCount(target.classList, adding);
153
148
  }
154
149
  disconnectedStatusMap.forEach((disconnectedTargetStatus, disconnectedTarget)=>{
155
150
  if (disconnectedTargetStatus.mutationRecord.target === target && disconnectedTargetStatus.change !== 0) {
@@ -174,59 +169,33 @@ class RuntimeCSS extends MasterCSS {
174
169
  const removedClasses = oldClassList.filter((c)=>!newClassList.contains(c));
175
170
  if (addedClasses.length) {
176
171
  // console.log('[attribute]', '[add] ', addedClasses, target)
177
- updateClassUsage(addedClasses, true);
172
+ updateClassCount(addedClasses, true);
178
173
  }
179
174
  if (removedClasses.length) {
180
175
  // console.log('[attribute]', '[remove]', removedClasses, target)
181
- updateClassUsage(removedClasses, false);
176
+ updateClassCount(removedClasses, false);
182
177
  }
183
178
  });
184
179
  /**
185
180
  * Merge the class usage changes into the current class usage map.
186
- */ eachClassUsages.forEach((countChange, className)=>{
187
- let currentCount = this.classUsages.get(className) || 0;
181
+ */ eachClassCounts.forEach((countChange, className)=>{
182
+ let currentCount = this.classCounts.get(className) || 0;
188
183
  let newCount = currentCount + countChange;
189
184
  if (newCount > 0) {
190
- this.classUsages.set(className, newCount);
185
+ this.classCounts.set(className, newCount);
191
186
  if (currentCount === 0) {
192
187
  this.add(className);
193
188
  }
194
189
  } else {
195
- this.classUsages.delete(className);
190
+ this.classCounts.delete(className);
196
191
  this.remove(className);
197
192
  }
198
193
  });
199
- // start: debug
200
- // const safeClassUsages: any = {};
201
- // ((this.root.constructor.name === 'HTMLDocument') ? this.host : this.container)
202
- // .querySelectorAll('[class]')
203
- // .forEach((element) => {
204
- // element.classList.forEach((className) => {
205
- // if (Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
206
- // safeClassUsages[className]++
207
- // } else {
208
- // safeClassUsages[className] = 1
209
- // }
210
- // })
211
- // })
212
- // this.host.classList.forEach((className) => {
213
- // if (Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
214
- // safeClassUsages[className]++
215
- // } else {
216
- // safeClassUsages[className] = 1
217
- // }
218
- // })
219
- // for (const className in safeClassUsages) {
220
- // if (this.classUsages.get(className) !== safeClassUsages[className]) {
221
- // throw new Error(`[css] ${className} ${this.classUsages.get(className)} (correct: ${safeClassUsages[className]})`)
222
- // }
223
- // }
224
- // this.classUsages.forEach((count, className) => {
225
- // if (!Object.prototype.hasOwnProperty.call(safeClassUsages, className)) {
226
- // throw new Error(`[css] ${className} ${count} (correct: 0)`)
227
- // }
228
- // })
229
- // end: debug
194
+ globalThis.__MASTER_CSS_DEVTOOLS_HOOK__?.emit('mutated', {
195
+ records: mutationRecords,
196
+ classCounts: eachClassCounts,
197
+ cssRuntime: this
198
+ });
230
199
  });
231
200
  this.observer.observe(this.root, {
232
201
  attributes: true,
@@ -244,10 +213,11 @@ class RuntimeCSS extends MasterCSS {
244
213
  this.observing = true;
245
214
  return this;
246
215
  }
247
- hydrate(nativeCSSRules) {
216
+ hydrate(nativeLayerRules) {
248
217
  const cssLayerRules = [];
249
- for(let i = 0; i < nativeCSSRules.length; i++){
250
- const eachNativeCSSRule = nativeCSSRules[i];
218
+ const checkSheet = new CSSStyleSheet();
219
+ for(let i = 0; i < nativeLayerRules.length; i++){
220
+ const eachNativeCSSRule = nativeLayerRules[i];
251
221
  if (eachNativeCSSRule.constructor.name === 'CSSLayerBlockRule') {
252
222
  const eachCSSLayerRule = eachNativeCSSRule;
253
223
  if (eachNativeCSSRule.name === 'theme') {
@@ -288,20 +258,8 @@ class RuntimeCSS extends MasterCSS {
288
258
  this.animationsNonLayer.usages[animationRule.name] = 0;
289
259
  }
290
260
  }
291
- const createSyntaxRules = (cssRule)=>{
292
- if (cssRule.selectorText) {
293
- return this.createFromSelectorText(cssRule.selectorText);
294
- } else if (cssRule.cssRules) {
295
- for (const eachCSSRule of cssRule.cssRules){
296
- const syntaxRules = createSyntaxRules(eachCSSRule);
297
- if (syntaxRules?.length) {
298
- return syntaxRules;
299
- }
300
- }
301
- }
302
- };
303
261
  for (const eachCSSLayerRule of cssLayerRules){
304
- const eachCSSRules = Array.from(eachCSSLayerRule.cssRules);
262
+ const nativeLayerRules = Array.from(eachCSSLayerRule.cssRules);
305
263
  let layer;
306
264
  switch(eachCSSLayerRule.name){
307
265
  case 'base':
@@ -318,62 +276,46 @@ class RuntimeCSS extends MasterCSS {
318
276
  break;
319
277
  }
320
278
  layer.native = eachCSSLayerRule;
321
- eachCSSRules.forEach((eachCSSRule)=>{
322
- const syntaxRules = createSyntaxRules(eachCSSRule);
323
- if (syntaxRules) {
324
- const retrieveNative = (selectorText)=>{
325
- for(let eachTargetCSSRuleIndex = 0; eachTargetCSSRuleIndex < eachCSSRules.length; eachTargetCSSRuleIndex++){
326
- const eachTargetCSSRule = eachCSSRules[eachTargetCSSRuleIndex];
327
- const matchSelector = (eachSelectorText)=>{
328
- if (eachSelectorText.replace(/,\s+/g, ',') === selectorText) {
329
- eachCSSRules.splice(eachTargetCSSRuleIndex, 1);
330
- return true;
331
- }
332
- return false;
333
- };
334
- if (eachTargetCSSRule instanceof CSSStyleRule) {
335
- if (matchSelector(eachTargetCSSRule.selectorText)) {
336
- return eachTargetCSSRule;
337
- }
338
- } else if (eachTargetCSSRule instanceof CSSMediaRule) {
339
- for(let eachMediaChildRuleIndex = 0; eachMediaChildRuleIndex < eachTargetCSSRule.cssRules.length; eachMediaChildRuleIndex++){
340
- const eachMediaChildRule = eachTargetCSSRule.cssRules[eachMediaChildRuleIndex];
341
- if (eachMediaChildRule instanceof CSSStyleRule) {
342
- if (matchSelector(eachMediaChildRule.selectorText)) {
343
- return eachTargetCSSRule;
344
- }
279
+ for (const eachNativeRule of nativeLayerRules){
280
+ const selectorText = this.getSelectorText(eachNativeRule);
281
+ if (!selectorText) {
282
+ console.error(`Cannot get the selector text from \`${eachNativeRule.cssText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
283
+ continue;
284
+ }
285
+ const createdRules = this.createFromSelectorText(selectorText);
286
+ if (createdRules) {
287
+ for (const createdRule of createdRules){
288
+ layer.rules.push(createdRule);
289
+ layer.insertVariables(createdRule);
290
+ layer.insertAnimations(createdRule);
291
+ createdRule.nodes.forEach((node)=>{
292
+ const createdNodeNativeRule = checkSheet.cssRules.item(checkSheet.insertRule(node.text));
293
+ if (createdNodeNativeRule) {
294
+ for (const eachFindingNativeRule of nativeLayerRules){
295
+ if (createdNodeNativeRule.cssText === eachFindingNativeRule.cssText) {
296
+ node.native = eachFindingNativeRule;
297
+ nativeLayerRules.splice(nativeLayerRules.indexOf(eachFindingNativeRule), 1);
298
+ return;
345
299
  }
346
300
  }
347
301
  }
348
- }
349
- };
350
- for (const syntaxRule of syntaxRules){
351
- layer.rules.push(syntaxRule);
352
- layer.insertVariables(syntaxRule);
353
- layer.insertAnimations(syntaxRule);
354
- syntaxRule.nodes.forEach((node)=>{
355
- const native = retrieveNative(node.selectorText);
356
- if (native) {
357
- node.native = native;
358
- } else {
359
- console.error(`Cannot retrieve the CSS rule for \`${node.selectorText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
360
- }
302
+ console.error(`Cannot retrieve CSS rule for \`${node.selectorText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
361
303
  });
362
304
  }
363
305
  } else {
364
- console.error(`Cannot recognize the CSS rule \`${eachCSSRule.cssText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
365
- }
366
- });
367
- for (const eachRule of layer.rules){
368
- for(let k = eachRule.nodes.length - 1; k >= 0; k--){
369
- if (!eachRule.nodes[k].native) {
370
- eachRule.nodes.splice(k, 1);
371
- }
306
+ console.error(`Cannot recognize \`${eachNativeRule.cssText}\`. (${layer.name}) (https://rc.css.master.co/messages/hydration-errors)`);
372
307
  }
373
308
  }
374
309
  if (layer.rules.length) this.rules.push(layer);
375
310
  }
376
311
  }
312
+ getSelectorText(cssRule) {
313
+ if ('selectorText' in cssRule) {
314
+ return cssRule.selectorText;
315
+ } else if ('cssRules' in cssRule) {
316
+ return this.getSelectorText(cssRule.cssRules.item(0));
317
+ }
318
+ }
377
319
  disconnect() {
378
320
  if (!this.observing) return;
379
321
  if (this.observer) {
@@ -384,7 +326,7 @@ class RuntimeCSS extends MasterCSS {
384
326
  // @ts-ignore
385
327
  this.observing = false;
386
328
  this.reset();
387
- this.classUsages.clear();
329
+ this.classCounts.clear();
388
330
  if (!this.progressive) {
389
331
  this.style?.remove();
390
332
  this.style = null;
@@ -401,23 +343,26 @@ class RuntimeCSS extends MasterCSS {
401
343
  }
402
344
  destroy() {
403
345
  this.disconnect();
404
- runtimeCSSs.splice(runtimeCSSs.indexOf(this), 1);
346
+ globalThis.CSSRuntime.instances.delete(this.root);
405
347
  return this;
406
348
  }
407
349
  }
408
- const runtimeCSSs = [];
409
- (()=>{
410
- globalThis.RuntimeCSS = RuntimeCSS;
411
- globalThis.runtimeCSSs = runtimeCSSs;
412
- })();
350
+ (function(CSSRuntime) {
351
+ registerGlobal(CSSRuntime);
352
+ })(CSSRuntime);
413
353
 
414
354
  /**
415
- * Initialize a new RuntimeCSS instance and observe the target root
355
+ * Initialize a new CSSRuntime instance and observe the target root
416
356
  * @param config master css config
417
- * @param targetRoot target root to observe
357
+ * @param root target root to observe
358
+ * @param autoObserve auto observe the target root
418
359
  * @returns master css instance
419
- */ function initCSSRuntime(config) {
420
- return new RuntimeCSS(document, config).observe();
360
+ */ function initCSSRuntime(config, root = document, autoObserve = true) {
361
+ let cssRuntime = globalThis.CSSRuntime.instances.get(root);
362
+ if (cssRuntime) return cssRuntime;
363
+ cssRuntime = new CSSRuntime(document, config);
364
+ if (autoObserve) cssRuntime.observe();
365
+ return cssRuntime;
421
366
  }
422
367
 
423
- export { RuntimeCSS, RuntimeCSS as default, initCSSRuntime };
368
+ export { CSSRuntime, CSSRuntime as default, initCSSRuntime };
package/dist/init.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import CSSRuntime from './core';
2
+ import type { Config } from '@master/css';
3
+ /**
4
+ * Initialize a new CSSRuntime instance and observe the target root
5
+ * @param config master css config
6
+ * @param root target root to observe
7
+ * @param autoObserve auto observe the target root
8
+ * @returns master css instance
9
+ */
10
+ export default function initCSSRuntime(config?: Config, root?: Document | ShadowRoot, autoObserve?: boolean): CSSRuntime;
@@ -0,0 +1,9 @@
1
+ import type { Config } from '@master/css';
2
+ import type Core from './core';
3
+ declare global {
4
+ var CSSRuntime: typeof Core;
5
+ var cssRuntime: Core;
6
+ var masterCSSConfig: Config;
7
+ var masterCSSConfigs: Config[];
8
+ }
9
+ export default function registerGlobal(CSSRuntime: typeof Core): void;
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","test":"vitest","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":"./dist/index.cjs","import":"./dist/index.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.53"},"devDependencies":{"@playwright/test":"^1.49.1","@types/cssom":"^0.4.3","css-tree":"^3.1.0","cssom":"^0.5.0","shared":"^2.0.0-rc.53"},"version":"2.0.0-rc.53"}
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.55","@master/css-devtools-hook":"^2.0.0-rc.55"},"devDependencies":{"@playwright/test":"^1.49.1","shared":"^2.0.0-rc.55"},"version":"2.0.0-rc.55"}
@@ -1,9 +0,0 @@
1
- import { RuntimeCSS } from './core';
2
- import type { Config } from '@master/css';
3
- /**
4
- * Initialize a new RuntimeCSS instance and observe the target root
5
- * @param config master css config
6
- * @param targetRoot target root to observe
7
- * @returns master css instance
8
- */
9
- export default function initCSSRuntime(config?: Config): RuntimeCSS;
@@ -1,9 +0,0 @@
1
- import type { Config } from '@master/css';
2
- import type { RuntimeCSS as _CSSRuntime } from '../core';
3
- declare global {
4
- var RuntimeCSS: typeof _CSSRuntime;
5
- var runtimeCSSs: _CSSRuntime[];
6
- var runtimeCSS: _CSSRuntime;
7
- var masterCSSConfig: Config;
8
- var masterCSSConfigs: Config[];
9
- }