@barocss/browser 0.0.3 → 0.4.0
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/README.md +2 -2
- package/dist/cdn/barocss.js +307 -229
- package/dist/cdn/barocss.js.map +1 -1
- package/dist/cdn/barocss.umd.cjs +1 -1
- package/dist/cdn/barocss.umd.cjs.map +1 -1
- package/dist/index.d.ts +268 -5
- package/dist/index.es.js +63 -53
- package/dist/index.umd.js +3 -3
- package/package.json +10 -6
- package/dist/baro-boot.d.ts +0 -8
- package/dist/browser-runtime.d.ts +0 -119
- package/dist/change-detector.d.ts +0 -80
- package/dist/style-partition-manager.d.ts +0 -51
- package/dist/utils.d.ts +0 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,268 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
1
|
+
import { Config } from '@barocss/kit';
|
|
2
|
+
import { GenerateCssRulesResult } from '@barocss/kit';
|
|
3
|
+
import { IncrementalParser } from '@barocss/kit';
|
|
4
|
+
|
|
5
|
+
export declare function baroBoot({ loadingClassName, ...options }?: BaroBootOptions): void;
|
|
6
|
+
|
|
7
|
+
declare type BaroBootOptions = BrowserRuntimeOptions & {
|
|
8
|
+
loadingClassName?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export declare const baroStart: typeof baroBoot;
|
|
12
|
+
|
|
13
|
+
export declare class BrowserRuntime {
|
|
14
|
+
private cache;
|
|
15
|
+
private rootCache;
|
|
16
|
+
private context;
|
|
17
|
+
private options;
|
|
18
|
+
private isDestroyed;
|
|
19
|
+
private incrementalParser;
|
|
20
|
+
private changeDetector;
|
|
21
|
+
private stylePartitionManager;
|
|
22
|
+
constructor(options?: BrowserRuntimeOptions);
|
|
23
|
+
/**
|
|
24
|
+
* Add debug logs (by level)
|
|
25
|
+
*/
|
|
26
|
+
private debugLog;
|
|
27
|
+
private init;
|
|
28
|
+
private injectPreflightCSS;
|
|
29
|
+
private ensureCssVars;
|
|
30
|
+
private getInsertionPoint;
|
|
31
|
+
/**
|
|
32
|
+
* Dynamically add one or more class names and generate/insert CSS
|
|
33
|
+
*/
|
|
34
|
+
addClass(classes: string | string[]): void;
|
|
35
|
+
/**
|
|
36
|
+
* Process classes
|
|
37
|
+
*/
|
|
38
|
+
private processClasses;
|
|
39
|
+
/**
|
|
40
|
+
* Process classes using incremental parsing
|
|
41
|
+
*/
|
|
42
|
+
private processClassesIncremental;
|
|
43
|
+
/**
|
|
44
|
+
* Public method to apply parser results, update internal caches, and inject CSS
|
|
45
|
+
*/
|
|
46
|
+
applyParseResults(results: Array<GenerateCssRulesResult>, _opts?: {
|
|
47
|
+
isBrowser?: boolean;
|
|
48
|
+
}): void;
|
|
49
|
+
/**
|
|
50
|
+
* MutationObserver instance method to automatically call addClass when class attributes change in DOM
|
|
51
|
+
*/
|
|
52
|
+
observe(root?: HTMLElement, options?: {
|
|
53
|
+
scan?: boolean;
|
|
54
|
+
onReady?: () => void;
|
|
55
|
+
}): MutationObserver;
|
|
56
|
+
private normalizeClasses;
|
|
57
|
+
has(cls: string): boolean;
|
|
58
|
+
getCss(cls: string): string | undefined;
|
|
59
|
+
getAllCss(): string;
|
|
60
|
+
getClasses(): string[];
|
|
61
|
+
/**
|
|
62
|
+
* Get comprehensive cache statistics
|
|
63
|
+
*/
|
|
64
|
+
getCacheStats(): {
|
|
65
|
+
runtime: {
|
|
66
|
+
cachedClasses: number;
|
|
67
|
+
rootCacheSize: number;
|
|
68
|
+
};
|
|
69
|
+
ast: {
|
|
70
|
+
size: number;
|
|
71
|
+
maxSize: number;
|
|
72
|
+
hitRate: number;
|
|
73
|
+
};
|
|
74
|
+
incremental: {
|
|
75
|
+
processedClasses: number;
|
|
76
|
+
pendingClasses: number;
|
|
77
|
+
cacheStats: {
|
|
78
|
+
ast: {
|
|
79
|
+
size: number;
|
|
80
|
+
maxSize: number;
|
|
81
|
+
hitRate: number;
|
|
82
|
+
};
|
|
83
|
+
css: {};
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Clear all caches (useful for debugging or memory management)
|
|
89
|
+
*/
|
|
90
|
+
clearCaches(): void;
|
|
91
|
+
reset(): void;
|
|
92
|
+
updateConfig(newConfig: Config): void;
|
|
93
|
+
removeClass(classes: string | string[]): void;
|
|
94
|
+
destroy(): void;
|
|
95
|
+
getStats(): {
|
|
96
|
+
cachedClasses: number;
|
|
97
|
+
styleElementId: string;
|
|
98
|
+
isDestroyed: boolean;
|
|
99
|
+
config: Config;
|
|
100
|
+
cacheStats: {
|
|
101
|
+
runtime: {
|
|
102
|
+
cachedClasses: number;
|
|
103
|
+
rootCacheSize: number;
|
|
104
|
+
};
|
|
105
|
+
ast: {
|
|
106
|
+
size: number;
|
|
107
|
+
maxSize: number;
|
|
108
|
+
hitRate: number;
|
|
109
|
+
};
|
|
110
|
+
incremental: {
|
|
111
|
+
processedClasses: number;
|
|
112
|
+
pendingClasses: number;
|
|
113
|
+
cacheStats: {
|
|
114
|
+
ast: {
|
|
115
|
+
size: number;
|
|
116
|
+
maxSize: number;
|
|
117
|
+
hitRate: number;
|
|
118
|
+
};
|
|
119
|
+
css: {};
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export declare interface BrowserRuntimeOptions {
|
|
127
|
+
config?: Config;
|
|
128
|
+
styleId?: string;
|
|
129
|
+
insertionPoint?: 'head' | 'body' | HTMLElement;
|
|
130
|
+
maxRulesPerPartition?: number;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Change detection system for DOM mutations
|
|
135
|
+
*
|
|
136
|
+
* ⚠️ BROWSER-ONLY: This class is designed for browser environments only.
|
|
137
|
+
* It uses MutationObserver and DOM APIs that are not available in Node.js.
|
|
138
|
+
*
|
|
139
|
+
* This class monitors DOM changes and automatically processes new CSS classes
|
|
140
|
+
* that are added to elements. It uses MutationObserver to detect:
|
|
141
|
+
* - Class attribute changes on existing elements
|
|
142
|
+
* - New elements being added to the DOM
|
|
143
|
+
* - Changes in child elements
|
|
144
|
+
*
|
|
145
|
+
* For server-side usage, use IncrementalParser directly with processClassesSync()
|
|
146
|
+
* or processClasses() methods.
|
|
147
|
+
*/
|
|
148
|
+
export declare class ChangeDetector {
|
|
149
|
+
/** MutationObserver instance for DOM change detection */
|
|
150
|
+
private observer;
|
|
151
|
+
/** Reference to IncrementalParser for class processing */
|
|
152
|
+
private incrementalParser;
|
|
153
|
+
/** Reference to BrowserRuntime for CSS injection (optional) */
|
|
154
|
+
private BrowserRuntime?;
|
|
155
|
+
/**
|
|
156
|
+
* Create a new ChangeDetector instance
|
|
157
|
+
*
|
|
158
|
+
* @param incrementalParser - IncrementalParser instance for class processing
|
|
159
|
+
* @param BrowserRuntime - Optional BrowserRuntime instance for CSS injection
|
|
160
|
+
*/
|
|
161
|
+
constructor(incrementalParser: IncrementalParser, BrowserRuntime?: BrowserRuntime);
|
|
162
|
+
setParser(parser: IncrementalParser): void;
|
|
163
|
+
/**
|
|
164
|
+
* Starts observing DOM changes for new CSS classes
|
|
165
|
+
*
|
|
166
|
+
* This method sets up a MutationObserver that monitors:
|
|
167
|
+
* - Attribute changes (specifically class attribute modifications)
|
|
168
|
+
* - Child list changes (new elements being added)
|
|
169
|
+
* - Subtree changes (changes in descendant elements)
|
|
170
|
+
*
|
|
171
|
+
* The observer automatically processes any new classes it discovers
|
|
172
|
+
* by adding them to the IncrementalParser's pending queue.
|
|
173
|
+
*
|
|
174
|
+
* @param root - The root element to observe (defaults to document.body)
|
|
175
|
+
* @param options - Configuration options including initial scan and onReady callback
|
|
176
|
+
* @returns The MutationObserver instance for external control
|
|
177
|
+
*/
|
|
178
|
+
observe(root?: HTMLElement, options?: {
|
|
179
|
+
scan?: boolean;
|
|
180
|
+
onReady?: () => void;
|
|
181
|
+
}): MutationObserver;
|
|
182
|
+
/**
|
|
183
|
+
* Scan existing classes in the DOM and process them
|
|
184
|
+
*/
|
|
185
|
+
private scanExistingClasses;
|
|
186
|
+
/**
|
|
187
|
+
* Processes an individual element and extracts new classes
|
|
188
|
+
*
|
|
189
|
+
* This method is called for each element discovered during DOM mutations.
|
|
190
|
+
* It:
|
|
191
|
+
* - Extracts all class names from the element's className
|
|
192
|
+
* - Filters out already processed classes
|
|
193
|
+
* - Adds new classes to the collection for batch processing
|
|
194
|
+
*
|
|
195
|
+
* @param element - The HTML element to process
|
|
196
|
+
* @param newClasses - Set to collect newly discovered class names
|
|
197
|
+
*/
|
|
198
|
+
private processElement;
|
|
199
|
+
/**
|
|
200
|
+
* Stops observing DOM changes and cleans up resources
|
|
201
|
+
*
|
|
202
|
+
* This method disconnects the MutationObserver and clears the
|
|
203
|
+
* observer reference to prevent memory leaks and allow the
|
|
204
|
+
* ChangeDetector to be properly garbage collected.
|
|
205
|
+
*/
|
|
206
|
+
disconnect(): void;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export declare function getRuntime(options: BrowserRuntimeOptions): BrowserRuntime;
|
|
210
|
+
|
|
211
|
+
export declare function normalizeClassName(className: any): string;
|
|
212
|
+
|
|
213
|
+
export declare function normalizeClassNameList(className: any): string[];
|
|
214
|
+
|
|
215
|
+
export declare interface StylePartition {
|
|
216
|
+
id: string;
|
|
217
|
+
styles: string[];
|
|
218
|
+
styleElement: HTMLStyleElement;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export declare class StylePartitionManager {
|
|
222
|
+
private partitions;
|
|
223
|
+
private categoryPartitions;
|
|
224
|
+
private partitionCounter;
|
|
225
|
+
private maxRulesPerPartition;
|
|
226
|
+
private insertionPoint;
|
|
227
|
+
private classToPartitionMap;
|
|
228
|
+
private classToCategoryPartitionMap;
|
|
229
|
+
private styleIdPrefix;
|
|
230
|
+
constructor(insertionPoint: HTMLElement, maxRulesPerPartition?: number, styleIdPrefix?: string);
|
|
231
|
+
private initializeDefaultPartition;
|
|
232
|
+
private createNewCategoryPartition;
|
|
233
|
+
private createNewPartition;
|
|
234
|
+
hasRule(rule: string): boolean;
|
|
235
|
+
hasCategoryRule(rule: string, category: string): boolean;
|
|
236
|
+
setRuleCache(rule: string, partitionIndex: number): void;
|
|
237
|
+
setCategoryRuleCache(rule: string, category: string): void;
|
|
238
|
+
get currentPartition(): StylePartition;
|
|
239
|
+
getCategoryPartition(category: string): StylePartition | undefined;
|
|
240
|
+
hasDetachedPartitions(): boolean;
|
|
241
|
+
/**
|
|
242
|
+
* Escape CSS rule text
|
|
243
|
+
* - Properly escape special characters
|
|
244
|
+
* - Prevent CSS syntax errors
|
|
245
|
+
*/
|
|
246
|
+
private escapeCssRule;
|
|
247
|
+
addRule(rule: string): boolean;
|
|
248
|
+
addCategoryRule(rule: string, category: string): boolean;
|
|
249
|
+
addRootRules(rules: string[]): {
|
|
250
|
+
success: number;
|
|
251
|
+
failed: number;
|
|
252
|
+
};
|
|
253
|
+
addRules(rules: GenerateCssRulesResult[]): {
|
|
254
|
+
success: number;
|
|
255
|
+
failed: number;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* 특정 규칙이 어느 파티션에 있는지 찾기
|
|
259
|
+
*/
|
|
260
|
+
findRulePartition(rule: string): StylePartition | null;
|
|
261
|
+
updateRuleContent(category: string, ruleContent: string): void;
|
|
262
|
+
/**
|
|
263
|
+
* 모든 파티션 정리
|
|
264
|
+
*/
|
|
265
|
+
cleanup(): void;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { }
|
package/dist/index.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseResultCache as
|
|
2
|
-
class
|
|
1
|
+
import { parseResultCache as y, createContext as f, IncrementalParser as g, clearAstCache as P } from "@barocss/kit";
|
|
2
|
+
class u {
|
|
3
3
|
constructor(t, e = 50, s = "barocss-style-partition-") {
|
|
4
4
|
this.partitions = [], this.categoryPartitions = /* @__PURE__ */ new Map(), this.partitionCounter = 0, this.maxRulesPerPartition = 50, this.classToPartitionMap = /* @__PURE__ */ new Map(), this.classToCategoryPartitionMap = /* @__PURE__ */ new Map(), this.styleIdPrefix = "barocss-style-partition-", this.insertionPoint = t, this.maxRulesPerPartition = e, this.styleIdPrefix = s, this.initializeDefaultPartition();
|
|
5
5
|
}
|
|
@@ -43,6 +43,9 @@ class p {
|
|
|
43
43
|
getCategoryPartition(t) {
|
|
44
44
|
return this.categoryPartitions.get(t);
|
|
45
45
|
}
|
|
46
|
+
hasDetachedPartitions() {
|
|
47
|
+
return [...this.partitions, ...this.categoryPartitions.values()].some((t) => !t.styleElement.isConnected);
|
|
48
|
+
}
|
|
46
49
|
/**
|
|
47
50
|
* Escape CSS rule text
|
|
48
51
|
* - Properly escape special characters
|
|
@@ -104,10 +107,10 @@ class p {
|
|
|
104
107
|
addRules(t) {
|
|
105
108
|
let e = 0, s = 0;
|
|
106
109
|
for (const i of t) {
|
|
107
|
-
const
|
|
108
|
-
if (
|
|
110
|
+
const n = y.get(i.cls)?.utility?.category;
|
|
111
|
+
if (n)
|
|
109
112
|
for (const o of i.cssList)
|
|
110
|
-
this.addCategoryRule(o,
|
|
113
|
+
this.addCategoryRule(o, n);
|
|
111
114
|
else
|
|
112
115
|
for (const o of i.cssList)
|
|
113
116
|
this.addRule(o) ? e++ : s++;
|
|
@@ -141,16 +144,16 @@ class p {
|
|
|
141
144
|
t.styleElement.parentNode && t.styleElement.parentNode.removeChild(t.styleElement);
|
|
142
145
|
}), this.categoryPartitions.forEach((t) => {
|
|
143
146
|
t.styleElement.parentNode && t.styleElement.parentNode.removeChild(t.styleElement);
|
|
144
|
-
}), this.partitions = [], this.partitionCounter = 0, this.classToPartitionMap.clear(), this.classToCategoryPartitionMap.clear();
|
|
147
|
+
}), this.partitions = [], this.categoryPartitions.clear(), this.partitionCounter = 0, this.classToPartitionMap.clear(), this.classToCategoryPartitionMap.clear();
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
|
-
function
|
|
150
|
+
function p(a) {
|
|
148
151
|
return a ? a instanceof SVGAnimatedString ? a.baseVal.toString() : a.toString() : "";
|
|
149
152
|
}
|
|
150
153
|
function c(a) {
|
|
151
|
-
return a ?
|
|
154
|
+
return a ? p(a).split(/\s+/).filter(Boolean) : [];
|
|
152
155
|
}
|
|
153
|
-
class
|
|
156
|
+
class m {
|
|
154
157
|
/**
|
|
155
158
|
* Create a new ChangeDetector instance
|
|
156
159
|
*
|
|
@@ -158,7 +161,10 @@ class P {
|
|
|
158
161
|
* @param BrowserRuntime - Optional BrowserRuntime instance for CSS injection
|
|
159
162
|
*/
|
|
160
163
|
constructor(t, e) {
|
|
161
|
-
this.observer = null, this.
|
|
164
|
+
this.observer = null, this.incrementalParser = t, this.BrowserRuntime = e;
|
|
165
|
+
}
|
|
166
|
+
setParser(t) {
|
|
167
|
+
this.incrementalParser = t;
|
|
162
168
|
}
|
|
163
169
|
/**
|
|
164
170
|
* Starts observing DOM changes for new CSS classes
|
|
@@ -179,21 +185,21 @@ class P {
|
|
|
179
185
|
return typeof window > "u" ? new MutationObserver(() => {
|
|
180
186
|
}) : (this.observer && this.observer.disconnect(), this.observer = new MutationObserver((s) => {
|
|
181
187
|
const i = /* @__PURE__ */ new Set();
|
|
182
|
-
if (s.forEach((
|
|
183
|
-
if (
|
|
184
|
-
const
|
|
185
|
-
|
|
188
|
+
if (s.forEach((r) => {
|
|
189
|
+
if (r.type === "attributes" && r.attributeName === "class") {
|
|
190
|
+
const n = r.target;
|
|
191
|
+
n.className && c(n.className).forEach((l) => {
|
|
186
192
|
this.incrementalParser.isProcessed(l) || i.add(l);
|
|
187
193
|
});
|
|
188
194
|
}
|
|
189
|
-
|
|
190
|
-
|
|
195
|
+
r.type === "childList" && r.addedNodes.forEach((n) => {
|
|
196
|
+
n instanceof Element && (this.processElement(n, i), n.querySelectorAll("[class]").forEach((o) => {
|
|
191
197
|
this.processElement(o, i);
|
|
192
198
|
}));
|
|
193
199
|
});
|
|
194
200
|
}), i.size > 0) {
|
|
195
|
-
const
|
|
196
|
-
this.BrowserRuntime?.applyParseResults(
|
|
201
|
+
const r = Array.from(i), n = this.incrementalParser.processClasses(r);
|
|
202
|
+
this.BrowserRuntime?.applyParseResults(n);
|
|
197
203
|
}
|
|
198
204
|
}), this.observer.observe(t, {
|
|
199
205
|
attributes: !0,
|
|
@@ -207,18 +213,18 @@ class P {
|
|
|
207
213
|
*/
|
|
208
214
|
scanExistingClasses(t, e) {
|
|
209
215
|
const s = /* @__PURE__ */ new Set();
|
|
210
|
-
t.className && c(t.className).forEach((
|
|
211
|
-
this.incrementalParser.isProcessed(
|
|
216
|
+
t.className && c(t.className).forEach((n) => {
|
|
217
|
+
this.incrementalParser.isProcessed(n) || s.add(n);
|
|
212
218
|
});
|
|
213
219
|
const i = t.querySelectorAll("[class]");
|
|
214
|
-
for (const
|
|
215
|
-
if (
|
|
216
|
-
const
|
|
217
|
-
for (const o of
|
|
220
|
+
for (const r of i)
|
|
221
|
+
if (r.className) {
|
|
222
|
+
const n = c(r.className);
|
|
223
|
+
for (const o of n)
|
|
218
224
|
this.incrementalParser.isProcessed(o) || s.add(o);
|
|
219
225
|
}
|
|
220
226
|
if (s.size > 0) {
|
|
221
|
-
const
|
|
227
|
+
const r = Array.from(s), n = this.incrementalParser.processClasses(r), o = n.filter((h) => y.get(h.cls)?.utility?.category === "layout"), l = n.filter((h) => y.get(h.cls)?.utility?.category !== "layout");
|
|
222
228
|
this.BrowserRuntime?.applyParseResults(o), e?.onReady?.(), this.BrowserRuntime?.applyParseResults(l);
|
|
223
229
|
}
|
|
224
230
|
}
|
|
@@ -227,19 +233,17 @@ class P {
|
|
|
227
233
|
*
|
|
228
234
|
* This method is called for each element discovered during DOM mutations.
|
|
229
235
|
* It:
|
|
230
|
-
* - Checks if the element has already been processed
|
|
231
236
|
* - Extracts all class names from the element's className
|
|
232
237
|
* - Filters out already processed classes
|
|
233
238
|
* - Adds new classes to the collection for batch processing
|
|
234
|
-
* - Marks the element as processed to avoid duplicates
|
|
235
239
|
*
|
|
236
240
|
* @param element - The HTML element to process
|
|
237
241
|
* @param newClasses - Set to collect newly discovered class names
|
|
238
242
|
*/
|
|
239
243
|
processElement(t, e) {
|
|
240
|
-
|
|
244
|
+
t.className && c(t.className).forEach((i) => {
|
|
241
245
|
this.incrementalParser.isProcessed(i) || e.add(i);
|
|
242
|
-
})
|
|
246
|
+
});
|
|
243
247
|
}
|
|
244
248
|
/**
|
|
245
249
|
* Stops observing DOM changes and cleans up resources
|
|
@@ -252,7 +256,7 @@ class P {
|
|
|
252
256
|
this.observer && (this.observer.disconnect(), this.observer = null);
|
|
253
257
|
}
|
|
254
258
|
}
|
|
255
|
-
class
|
|
259
|
+
class C {
|
|
256
260
|
constructor(t = {}) {
|
|
257
261
|
this.cache = /* @__PURE__ */ new Map(), this.rootCache = /* @__PURE__ */ new Set(), this.isDestroyed = !1;
|
|
258
262
|
const e = {};
|
|
@@ -261,7 +265,7 @@ class m {
|
|
|
261
265
|
styleId: t.styleId || "barocss-runtime",
|
|
262
266
|
insertionPoint: t.insertionPoint || "head",
|
|
263
267
|
maxRulesPerPartition: t.maxRulesPerPartition || 50
|
|
264
|
-
}, this.context =
|
|
268
|
+
}, this.context = f(this.options.config), this.incrementalParser = new g(this.context), this.changeDetector = new m(this.incrementalParser, this), this.stylePartitionManager = new u(this.getInsertionPoint(), this.options.maxRulesPerPartition, `${this.options.styleId}-partition`), this.init();
|
|
265
269
|
}
|
|
266
270
|
// Debugging and logging helpers
|
|
267
271
|
/**
|
|
@@ -320,11 +324,16 @@ class m {
|
|
|
320
324
|
* Public method to apply parser results, update internal caches, and inject CSS
|
|
321
325
|
*/
|
|
322
326
|
applyParseResults(t, e) {
|
|
327
|
+
if (this.isDestroyed) return;
|
|
328
|
+
if (this.getInsertionPoint().isConnected && this.stylePartitionManager.hasDetachedPartitions()) {
|
|
329
|
+
const r = Array.from(this.cache.values());
|
|
330
|
+
this.reset(), t = [...r, ...t], t.forEach((n) => this.incrementalParser.markProcessed(n.cls));
|
|
331
|
+
}
|
|
323
332
|
const s = [], i = [];
|
|
324
|
-
for (const
|
|
325
|
-
if (
|
|
326
|
-
for (const
|
|
327
|
-
this.rootCache.has(
|
|
333
|
+
for (const r of t)
|
|
334
|
+
if (r.css && Array.isArray(r.cssList) && (s.push(r), this.cache.set(r.cls, r)), r.rootCss && Array.isArray(r.rootCssList))
|
|
335
|
+
for (const n of r.rootCssList)
|
|
336
|
+
this.rootCache.has(n) || (this.rootCache.add(n), i.push(n));
|
|
328
337
|
i.length > 0 && this.stylePartitionManager.addRootRules(i.filter(Boolean)), s.length > 0 && this.stylePartitionManager.addRules(s), this.debugLog("info", `Applied ${t.length} parser results`, {
|
|
329
338
|
cssRuleCount: s.length,
|
|
330
339
|
rootCssCount: i.length
|
|
@@ -357,36 +366,37 @@ class m {
|
|
|
357
366
|
* Get comprehensive cache statistics
|
|
358
367
|
*/
|
|
359
368
|
getCacheStats() {
|
|
369
|
+
const t = this.incrementalParser.getStats();
|
|
360
370
|
return {
|
|
361
371
|
runtime: {
|
|
362
372
|
cachedClasses: this.cache.size,
|
|
363
373
|
rootCacheSize: this.rootCache.size
|
|
364
374
|
},
|
|
365
|
-
ast:
|
|
366
|
-
incremental:
|
|
375
|
+
ast: t.cacheStats.ast,
|
|
376
|
+
incremental: t
|
|
367
377
|
};
|
|
368
378
|
}
|
|
369
379
|
/**
|
|
370
380
|
* Clear all caches (useful for debugging or memory management)
|
|
371
381
|
*/
|
|
372
382
|
clearCaches() {
|
|
373
|
-
this.cache.clear(), this.rootCache.clear(),
|
|
383
|
+
this.isDestroyed || (this.cache.clear(), this.rootCache.clear(), P(this.context), this.incrementalParser.clearProcessed(), this.stylePartitionManager.cleanup(), this.stylePartitionManager = new u(this.getInsertionPoint(), this.options.maxRulesPerPartition, `${this.options.styleId}-partition`), this.injectPreflightCSS(), this.ensureCssVars());
|
|
374
384
|
}
|
|
375
385
|
reset() {
|
|
376
|
-
this.cache.clear(), this.rootCache.clear(), this.stylePartitionManager.cleanup();
|
|
386
|
+
this.isDestroyed || (this.cache.clear(), this.rootCache.clear(), this.incrementalParser.clearProcessed(), this.stylePartitionManager.cleanup(), this.stylePartitionManager = new u(this.getInsertionPoint(), this.options.maxRulesPerPartition, `${this.options.styleId}-partition`), this.injectPreflightCSS(), this.ensureCssVars());
|
|
377
387
|
}
|
|
378
388
|
updateConfig(t) {
|
|
379
|
-
|
|
389
|
+
if (this.isDestroyed) return;
|
|
380
390
|
const e = Array.from(this.cache.keys());
|
|
381
|
-
this.reset(), e.length > 0 && this.addClass(e);
|
|
391
|
+
this.options.config = t, this.context = f(t), this.incrementalParser = new g(this.context), this.changeDetector.setParser(this.incrementalParser), this.reset(), e.length > 0 && this.addClass(e);
|
|
382
392
|
}
|
|
383
393
|
removeClass(t) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
394
|
+
if (this.isDestroyed) return;
|
|
395
|
+
const e = new Set(this.normalizeClasses(t)), s = Array.from(this.cache.values()).filter((i) => !e.has(i.cls));
|
|
396
|
+
s.length !== this.cache.size && (this.reset(), s.forEach((i) => this.incrementalParser.markProcessed(i.cls)), this.applyParseResults(s));
|
|
387
397
|
}
|
|
388
398
|
destroy() {
|
|
389
|
-
this.stylePartitionManager.cleanup(), this.cache.clear(), this.rootCache.clear(), this.isDestroyed = !0;
|
|
399
|
+
this.isDestroyed || (this.changeDetector.disconnect(), this.stylePartitionManager.cleanup(), this.cache.clear(), this.rootCache.clear(), this.isDestroyed = !0);
|
|
390
400
|
}
|
|
391
401
|
getStats() {
|
|
392
402
|
return {
|
|
@@ -398,9 +408,9 @@ class m {
|
|
|
398
408
|
};
|
|
399
409
|
}
|
|
400
410
|
}
|
|
401
|
-
let
|
|
411
|
+
let d = null;
|
|
402
412
|
function R(a) {
|
|
403
|
-
return
|
|
413
|
+
return d || (d = new C(a)), d;
|
|
404
414
|
}
|
|
405
415
|
function b({ loadingClassName: a = "baro-boot", ...t } = {}) {
|
|
406
416
|
const e = `${a}-doing`, s = `${a}-done`;
|
|
@@ -412,14 +422,14 @@ function b({ loadingClassName: a = "baro-boot", ...t } = {}) {
|
|
|
412
422
|
console.error("BaroCSS boot failed:", i);
|
|
413
423
|
}
|
|
414
424
|
}
|
|
415
|
-
const
|
|
425
|
+
const E = b;
|
|
416
426
|
export {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
427
|
+
C as BrowserRuntime,
|
|
428
|
+
m as ChangeDetector,
|
|
429
|
+
u as StylePartitionManager,
|
|
420
430
|
b as baroBoot,
|
|
421
|
-
|
|
431
|
+
E as baroStart,
|
|
422
432
|
R as getRuntime,
|
|
423
|
-
|
|
433
|
+
p as normalizeClassName,
|
|
424
434
|
c as normalizeClassNameList
|
|
425
435
|
};
|
package/dist/index.umd.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
(function(o,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("@barocss/kit")):typeof define=="function"&&define.amd?define(["exports","@barocss/kit"],l):(o=typeof globalThis<"u"?globalThis:o||self,l(o.BaroCSSBrowser={},o.BaroCSSKit))})(this,(function(o,l){"use strict";class
|
|
1
|
+
(function(o,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("@barocss/kit")):typeof define=="function"&&define.amd?define(["exports","@barocss/kit"],l):(o=typeof globalThis<"u"?globalThis:o||self,l(o.BaroCSSBrowser={},o.BaroCSSKit))})(this,(function(o,l){"use strict";class u{constructor(t,e=50,s="barocss-style-partition-"){this.partitions=[],this.categoryPartitions=new Map,this.partitionCounter=0,this.maxRulesPerPartition=50,this.classToPartitionMap=new Map,this.classToCategoryPartitionMap=new Map,this.styleIdPrefix="barocss-style-partition-",this.insertionPoint=t,this.maxRulesPerPartition=e,this.styleIdPrefix=s,this.initializeDefaultPartition()}initializeDefaultPartition(){this.createNewPartition()}createNewCategoryPartition(t){const e={id:this.styleIdPrefix+`-${t}`,styles:[],styleElement:document.createElement("style")};return e.styleElement.id=e.id,e.styleElement.setAttribute("data-barocss","partition"),e.styleElement.setAttribute("data-category",t),this.insertionPoint.appendChild(e.styleElement),this.categoryPartitions.set(t,e),e}createNewPartition(){const t={id:this.styleIdPrefix+`-${this.partitionCounter++}`,styles:[],styleElement:document.createElement("style")};return this.partitions.push(t),t.styleElement.id=t.id,t.styleElement.setAttribute("data-barocss","partition"),t.styleElement.setAttribute("data-partition-index",this.partitionCounter.toString()),this.insertionPoint.appendChild(t.styleElement),t}hasRule(t){return this.classToPartitionMap.has(t)}hasCategoryRule(t,e){return this.classToCategoryPartitionMap.get(t)===e}setRuleCache(t,e){this.classToPartitionMap.set(t,e)}setCategoryRuleCache(t,e){this.classToCategoryPartitionMap.set(t,e)}get currentPartition(){return this.partitions[this.partitions.length-1]}getCategoryPartition(t){return this.categoryPartitions.get(t)}hasDetachedPartitions(){return[...this.partitions,...this.categoryPartitions.values()].some(t=>!t.styleElement.isConnected)}escapeCssRule(t){return t.replace(/\\\//g,"\\/")}addRule(t){if(this.hasRule(t))return!1;this.currentPartition.styles.length>=this.maxRulesPerPartition&&this.createNewPartition();const e=this.currentPartition,s=this.partitions.length-1;try{const i=e.styleElement.sheet;return i?i.insertRule(this.escapeCssRule(t),i.cssRules.length):e.styleElement.textContent+=t+`
|
|
2
2
|
`,this.setRuleCache(t,s),e.styles.push(t),!0}catch(i){return console.warn(`[StylePartitionManager] Failed to insert rule: ${t}`,i),!1}}addCategoryRule(t,e){if(this.hasCategoryRule(t,e))return!1;let s=this.getCategoryPartition(e);s||(s=this.createNewCategoryPartition(e));try{const i=s.styleElement.sheet;i?i.insertRule(this.escapeCssRule(t),i.cssRules.length):s.styleElement.textContent+=t+`
|
|
3
3
|
`}catch(i){return console.warn(`[StylePartitionManager] Failed to insert rule in category: ${e} ${t}`,i),!1}return this.setCategoryRuleCache(t,e),s.styles.push(t),!0}addRootRules(t){let e=this.getCategoryPartition("root");e||(e=this.createNewCategoryPartition("root"));try{const s=e.styleElement.sheet;for(const i of t)s?s.insertRule(this.escapeCssRule(i),s.cssRules.length):e.styleElement.textContent+=i+`
|
|
4
4
|
`}catch(s){return console.warn(`[StylePartitionManager] Failed to insert rule in category: root ${t.join(`
|
|
5
|
-
`)}`,s),{success:0,failed:t.length}}return{success:t.length,failed:0}}addRules(t){let e=0,s=0;for(const i of t){const
|
|
5
|
+
`)}`,s),{success:0,failed:t.length}}return{success:t.length,failed:0}}addRules(t){let e=0,s=0;for(const i of t){const n=l.parseResultCache.get(i.cls)?.utility?.category;if(n)for(const c of i.cssList)this.addCategoryRule(c,n);else for(const c of i.cssList)this.addRule(c)?e++:s++}return{success:e,failed:s}}findRulePartition(t){const e=this.classToPartitionMap.get(t);if(e!==void 0&&this.partitions[e])return this.partitions[e];const s=this.classToCategoryPartitionMap.get(t);return s!==void 0&&this.categoryPartitions.get(s)||null}updateRuleContent(t,e){const s=this.getCategoryPartition(t);if(s)s.styleElement.textContent=e;else{const i=this.createNewCategoryPartition(t);console.log(`[StylePartitionManager] Created new partition for category: ${t}`),i.styleElement.textContent=e}}cleanup(){this.partitions.forEach(t=>{t.styleElement.parentNode&&t.styleElement.parentNode.removeChild(t.styleElement)}),this.categoryPartitions.forEach(t=>{t.styleElement.parentNode&&t.styleElement.parentNode.removeChild(t.styleElement)}),this.partitions=[],this.categoryPartitions.clear(),this.partitionCounter=0,this.classToPartitionMap.clear(),this.classToCategoryPartitionMap.clear()}}function g(a){return a?a instanceof SVGAnimatedString?a.baseVal.toString():a.toString():""}function h(a){return a?g(a).split(/\s+/).filter(Boolean):[]}class P{constructor(t,e){this.observer=null,this.incrementalParser=t,this.BrowserRuntime=e}setParser(t){this.incrementalParser=t}observe(t=document.body,e){return typeof window>"u"?new MutationObserver(()=>{}):(this.observer&&this.observer.disconnect(),this.observer=new MutationObserver(s=>{const i=new Set;if(s.forEach(r=>{if(r.type==="attributes"&&r.attributeName==="class"){const n=r.target;n.className&&h(n.className).forEach(d=>{this.incrementalParser.isProcessed(d)||i.add(d)})}r.type==="childList"&&r.addedNodes.forEach(n=>{n instanceof Element&&(this.processElement(n,i),n.querySelectorAll("[class]").forEach(c=>{this.processElement(c,i)}))})}),i.size>0){const r=Array.from(i),n=this.incrementalParser.processClasses(r);this.BrowserRuntime?.applyParseResults(n)}}),this.observer.observe(t,{attributes:!0,subtree:!0,attributeFilter:["class"],childList:!0}),e?.scan&&this.scanExistingClasses(t,e),this.observer)}scanExistingClasses(t,e){const s=new Set;t.className&&h(t.className).forEach(n=>{this.incrementalParser.isProcessed(n)||s.add(n)});const i=t.querySelectorAll("[class]");for(const r of i)if(r.className){const n=h(r.className);for(const c of n)this.incrementalParser.isProcessed(c)||s.add(c)}if(s.size>0){const r=Array.from(s),n=this.incrementalParser.processClasses(r),c=n.filter(f=>l.parseResultCache.get(f.cls)?.utility?.category==="layout"),d=n.filter(f=>l.parseResultCache.get(f.cls)?.utility?.category!=="layout");this.BrowserRuntime?.applyParseResults(c),e?.onReady?.(),this.BrowserRuntime?.applyParseResults(d)}}processElement(t,e){t.className&&h(t.className).forEach(i=>{this.incrementalParser.isProcessed(i)||e.add(i)})}disconnect(){this.observer&&(this.observer.disconnect(),this.observer=null)}}class m{constructor(t={}){this.cache=new Map,this.rootCache=new Set,this.isDestroyed=!1;const e={};this.options={config:t.config||e,styleId:t.styleId||"barocss-runtime",insertionPoint:t.insertionPoint||"head",maxRulesPerPartition:t.maxRulesPerPartition||50},this.context=l.createContext(this.options.config),this.incrementalParser=new l.IncrementalParser(this.context),this.changeDetector=new P(this.incrementalParser,this),this.stylePartitionManager=new u(this.getInsertionPoint(),this.options.maxRulesPerPartition,`${this.options.styleId}-partition`),this.init()}debugLog(t,e,s){(console[t]||console.log)(`[BrowserRuntime:${t.toUpperCase()}] ${e}`,s||"")}init(){console.log("[BrowserRuntime] init"),this.injectPreflightCSS(),this.ensureCssVars()}injectPreflightCSS(){if(this.options.config.preflight){const t=this.context.getPreflightCSS(this.options.config.preflight);this.stylePartitionManager.updateRuleContent("preflight",t)}}ensureCssVars(){if(this.isDestroyed)return;const t=this.context.themeToCssVars?this.context.themeToCssVars():":root { /* CSS Variables will be generated here */ }";this.stylePartitionManager.updateRuleContent("css-vars",t)}getInsertionPoint(){if(this.options.insertionPoint instanceof HTMLElement)return this.options.insertionPoint;switch(this.options.insertionPoint){case"body":return document.body||document.head;case"head":default:return document.head}}addClass(t){if(this.isDestroyed)return;const e=this.normalizeClasses(t);this.processClasses(e)}processClasses(t){this.processClassesIncremental(t)}processClassesIncremental(t){const e=typeof window<"u",s=this.incrementalParser.processClasses(t);console.log("[BrowserRuntime] results",s,...t),this.applyParseResults(s,{isBrowser:e})}applyParseResults(t,e){if(this.isDestroyed)return;if(this.getInsertionPoint().isConnected&&this.stylePartitionManager.hasDetachedPartitions()){const r=Array.from(this.cache.values());this.reset(),t=[...r,...t],t.forEach(n=>this.incrementalParser.markProcessed(n.cls))}const s=[],i=[];for(const r of t)if(r.css&&Array.isArray(r.cssList)&&(s.push(r),this.cache.set(r.cls,r)),r.rootCss&&Array.isArray(r.rootCssList))for(const n of r.rootCssList)this.rootCache.has(n)||(this.rootCache.add(n),i.push(n));i.length>0&&this.stylePartitionManager.addRootRules(i.filter(Boolean)),s.length>0&&this.stylePartitionManager.addRules(s),this.debugLog("info",`Applied ${t.length} parser results`,{cssRuleCount:s.length,rootCssCount:i.length})}observe(t=document.body,e){return this.changeDetector.observe(t,e)}normalizeClasses(t){return Array.isArray(t)?t.flatMap(e=>e.split(/\s+/)):t.split(/\s+/)}has(t){return this.cache.has(t)}getCss(t){return this.cache.get(t)?.cssList.join(`
|
|
6
6
|
`)}getAllCss(){return Array.from(this.cache.values()).flatMap(e=>e.cssList).join(`
|
|
7
|
-
`)}getClasses(){return Array.from(this.cache.keys())}getCacheStats(){return{runtime:{cachedClasses:this.cache.size,rootCacheSize:this.rootCache.size},ast:
|
|
7
|
+
`)}getClasses(){return Array.from(this.cache.keys())}getCacheStats(){const t=this.incrementalParser.getStats();return{runtime:{cachedClasses:this.cache.size,rootCacheSize:this.rootCache.size},ast:t.cacheStats.ast,incremental:t}}clearCaches(){this.isDestroyed||(this.cache.clear(),this.rootCache.clear(),l.clearAstCache(this.context),this.incrementalParser.clearProcessed(),this.stylePartitionManager.cleanup(),this.stylePartitionManager=new u(this.getInsertionPoint(),this.options.maxRulesPerPartition,`${this.options.styleId}-partition`),this.injectPreflightCSS(),this.ensureCssVars())}reset(){this.isDestroyed||(this.cache.clear(),this.rootCache.clear(),this.incrementalParser.clearProcessed(),this.stylePartitionManager.cleanup(),this.stylePartitionManager=new u(this.getInsertionPoint(),this.options.maxRulesPerPartition,`${this.options.styleId}-partition`),this.injectPreflightCSS(),this.ensureCssVars())}updateConfig(t){if(this.isDestroyed)return;const e=Array.from(this.cache.keys());this.options.config=t,this.context=l.createContext(t),this.incrementalParser=new l.IncrementalParser(this.context),this.changeDetector.setParser(this.incrementalParser),this.reset(),e.length>0&&this.addClass(e)}removeClass(t){if(this.isDestroyed)return;const e=new Set(this.normalizeClasses(t)),s=Array.from(this.cache.values()).filter(i=>!e.has(i.cls));s.length!==this.cache.size&&(this.reset(),s.forEach(i=>this.incrementalParser.markProcessed(i.cls)),this.applyParseResults(s))}destroy(){this.isDestroyed||(this.changeDetector.disconnect(),this.stylePartitionManager.cleanup(),this.cache.clear(),this.rootCache.clear(),this.isDestroyed=!0)}getStats(){return{cachedClasses:this.cache.size,styleElementId:this.options.styleId,isDestroyed:this.isDestroyed,config:this.options.config,cacheStats:this.getCacheStats()}}}let y=null;function p(a){return y||(y=new m(a)),y}function C({loadingClassName:a="baro-boot",...t}={}){const e=`${a}-doing`,s=`${a}-done`;try{document.body.classList.add(e),p(t).observe(document.body,{scan:!0,onReady:()=>{document.body.classList.remove(e),document.body.classList.add(s)}})}catch(i){console.error("BaroCSS boot failed:",i)}}const R=C;o.BrowserRuntime=m,o.ChangeDetector=P,o.StylePartitionManager=u,o.baroBoot=C,o.baroStart=R,o.getRuntime=p,o.normalizeClassName=g,o.normalizeClassNameList=h,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barocss/browser",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/barocss/barocss.git",
|
|
7
|
+
"directory": "packages/barocss-browser"
|
|
8
|
+
},
|
|
4
9
|
"type": "module",
|
|
5
|
-
"main": "./dist/index.
|
|
10
|
+
"main": "./dist/index.es.js",
|
|
6
11
|
"types": "./dist/index.d.ts",
|
|
7
12
|
"exports": {
|
|
8
13
|
".": {
|
|
9
14
|
"types": "./dist/index.d.ts",
|
|
10
|
-
"import": "./dist/index.es.js"
|
|
11
|
-
"require": "./dist/index.umd.js"
|
|
15
|
+
"import": "./dist/index.es.js"
|
|
12
16
|
}
|
|
13
17
|
},
|
|
14
18
|
"files": [
|
|
@@ -20,7 +24,7 @@
|
|
|
20
24
|
"access": "public"
|
|
21
25
|
},
|
|
22
26
|
"dependencies": {
|
|
23
|
-
"@barocss/kit": "0.0
|
|
27
|
+
"@barocss/kit": "0.4.0"
|
|
24
28
|
},
|
|
25
29
|
"devDependencies": {
|
|
26
30
|
"jsdom": "^26.1.0",
|
|
@@ -33,7 +37,7 @@
|
|
|
33
37
|
"build:cdn": "vite build --config vite.cdn.config.ts",
|
|
34
38
|
"build:library": "pnpm run build && pnpm run build:cdn",
|
|
35
39
|
"test:watch": "vitest",
|
|
36
|
-
"
|
|
40
|
+
"test": "vitest run",
|
|
37
41
|
"type-check": "tsc --noEmit",
|
|
38
42
|
"lint": "eslint src/**/*.ts"
|
|
39
43
|
},
|
package/dist/baro-boot.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { BrowserRuntime, BrowserRuntimeOptions } from './browser-runtime';
|
|
2
|
-
export declare function getRuntime(options: BrowserRuntimeOptions): BrowserRuntime;
|
|
3
|
-
type BaroBootOptions = BrowserRuntimeOptions & {
|
|
4
|
-
loadingClassName?: string;
|
|
5
|
-
};
|
|
6
|
-
export declare function baroBoot({ loadingClassName, ...options }?: BaroBootOptions): void;
|
|
7
|
-
export declare const baroStart: typeof baroBoot;
|
|
8
|
-
export {};
|