elit 3.0.1 → 3.0.3
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/build.d.ts +4 -12
- package/dist/build.d.ts.map +1 -0
- package/dist/chokidar.d.ts +7 -9
- package/dist/chokidar.d.ts.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +250 -21
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/dom.d.ts +7 -14
- package/dist/dom.d.ts.map +1 -0
- package/dist/el.d.ts +19 -191
- package/dist/el.d.ts.map +1 -0
- package/dist/fs.d.ts +35 -35
- package/dist/fs.d.ts.map +1 -0
- package/dist/hmr.d.ts +3 -3
- package/dist/hmr.d.ts.map +1 -0
- package/dist/http.d.ts +20 -22
- package/dist/http.d.ts.map +1 -0
- package/dist/https.d.ts +12 -15
- package/dist/https.d.ts.map +1 -0
- package/dist/index.d.ts +10 -629
- package/dist/index.d.ts.map +1 -0
- package/dist/mime-types.d.ts +9 -9
- package/dist/mime-types.d.ts.map +1 -0
- package/dist/path.d.ts +22 -19
- package/dist/path.d.ts.map +1 -0
- package/dist/router.d.ts +10 -17
- package/dist/router.d.ts.map +1 -0
- package/dist/runtime.d.ts +5 -6
- package/dist/runtime.d.ts.map +1 -0
- package/dist/server.d.ts +109 -7
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +712 -137
- package/dist/server.mjs +711 -137
- package/dist/state.d.ts +21 -27
- package/dist/state.d.ts.map +1 -0
- package/dist/style.d.ts +14 -55
- package/dist/style.d.ts.map +1 -0
- package/dist/types.d.ts +26 -240
- package/dist/types.d.ts.map +1 -0
- package/dist/ws.d.ts +14 -17
- package/dist/ws.d.ts.map +1 -0
- package/dist/wss.d.ts +16 -16
- package/dist/wss.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/build.ts +337 -0
- package/src/chokidar.ts +401 -0
- package/src/cli.ts +638 -0
- package/src/config.ts +205 -0
- package/src/dom.ts +817 -0
- package/src/el.ts +164 -0
- package/src/fs.ts +727 -0
- package/src/hmr.ts +137 -0
- package/src/http.ts +775 -0
- package/src/https.ts +411 -0
- package/src/index.ts +14 -0
- package/src/mime-types.ts +222 -0
- package/src/path.ts +493 -0
- package/src/router.ts +237 -0
- package/src/runtime.ts +97 -0
- package/src/server.ts +1593 -0
- package/src/state.ts +468 -0
- package/src/style.ts +524 -0
- package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
- package/src/ws.ts +506 -0
- package/src/wss.ts +241 -0
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -207
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -163
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -629
- package/dist/mime-types.d.mts +0 -48
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -47
- package/dist/runtime.d.mts +0 -97
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -111
- package/dist/style.d.mts +0 -159
- package/dist/types-C0nGi6MX.d.mts +0 -346
- package/dist/types.d.mts +0 -452
- package/dist/ws.d.mts +0 -195
- package/dist/wss.d.mts +0 -108
package/src/style.ts
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elit - CreateStyle CSS Generation System
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface CSSVariable {
|
|
6
|
+
name: string;
|
|
7
|
+
value: string;
|
|
8
|
+
toString(): string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CSSRule {
|
|
12
|
+
selector: string;
|
|
13
|
+
styles: Record<string, string | number>;
|
|
14
|
+
nested?: CSSRule[];
|
|
15
|
+
type: 'tag' | 'class' | 'id' | 'pseudo-class' | 'pseudo-element' | 'name' | 'custom' | 'media' | 'attribute';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MediaRule {
|
|
19
|
+
type: string;
|
|
20
|
+
condition: string;
|
|
21
|
+
rules: CSSRule[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface KeyframeStep {
|
|
25
|
+
step: string | number;
|
|
26
|
+
styles: Record<string, string | number>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface Keyframes {
|
|
30
|
+
name: string;
|
|
31
|
+
steps: KeyframeStep[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface FontFace {
|
|
35
|
+
fontFamily: string;
|
|
36
|
+
src: string;
|
|
37
|
+
fontWeight?: string | number;
|
|
38
|
+
fontStyle?: string;
|
|
39
|
+
fontDisplay?: string;
|
|
40
|
+
unicodeRange?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ContainerRule {
|
|
44
|
+
name?: string;
|
|
45
|
+
condition: string;
|
|
46
|
+
rules: CSSRule[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface SupportsRule {
|
|
50
|
+
condition: string;
|
|
51
|
+
rules: CSSRule[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface LayerRule {
|
|
55
|
+
name: string;
|
|
56
|
+
rules: CSSRule[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class CreateStyle {
|
|
60
|
+
private variables: CSSVariable[] = [];
|
|
61
|
+
private rules: CSSRule[] = [];
|
|
62
|
+
private mediaRules: MediaRule[] = [];
|
|
63
|
+
private keyframes: Keyframes[] = [];
|
|
64
|
+
private fontFaces: FontFace[] = [];
|
|
65
|
+
private imports: string[] = [];
|
|
66
|
+
private containerRules: ContainerRule[] = [];
|
|
67
|
+
private supportsRules: SupportsRule[] = [];
|
|
68
|
+
private layerRules: LayerRule[] = [];
|
|
69
|
+
private _layerOrder: string[] = [];
|
|
70
|
+
|
|
71
|
+
// CSS Variables
|
|
72
|
+
addVar(name: string, value: string): CSSVariable {
|
|
73
|
+
const cssVar: CSSVariable = {
|
|
74
|
+
name: name.startsWith('--') ? name : `--${name}`,
|
|
75
|
+
value,
|
|
76
|
+
toString() { return `var(${this.name})`; }
|
|
77
|
+
};
|
|
78
|
+
this.variables.push(cssVar);
|
|
79
|
+
return cssVar;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var(variable: CSSVariable | string, fallback?: string): string {
|
|
83
|
+
const varName = typeof variable === 'string'
|
|
84
|
+
? (variable.startsWith('--') ? variable : `--${variable}`)
|
|
85
|
+
: variable.name;
|
|
86
|
+
return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Basic Selectors
|
|
90
|
+
addTag(tag: string, styles: Record<string, string | number>): CSSRule {
|
|
91
|
+
const rule: CSSRule = { selector: tag, styles, type: 'tag' };
|
|
92
|
+
this.rules.push(rule);
|
|
93
|
+
return rule;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
addClass(name: string, styles: Record<string, string | number>): CSSRule {
|
|
97
|
+
const selector = name.startsWith('.') ? name : `.${name}`;
|
|
98
|
+
const rule: CSSRule = { selector, styles, type: 'class' };
|
|
99
|
+
this.rules.push(rule);
|
|
100
|
+
return rule;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
addId(name: string, styles: Record<string, string | number>): CSSRule {
|
|
104
|
+
const selector = name.startsWith('#') ? name : `#${name}`;
|
|
105
|
+
const rule: CSSRule = { selector, styles, type: 'id' };
|
|
106
|
+
this.rules.push(rule);
|
|
107
|
+
return rule;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Pseudo Selectors
|
|
111
|
+
addPseudoClass(pseudo: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
112
|
+
const pseudoClass = pseudo.startsWith(':') ? pseudo : `:${pseudo}`;
|
|
113
|
+
const selector = baseSelector ? `${baseSelector}${pseudoClass}` : pseudoClass;
|
|
114
|
+
const rule: CSSRule = { selector, styles, type: 'pseudo-class' };
|
|
115
|
+
this.rules.push(rule);
|
|
116
|
+
return rule;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
addPseudoElement(pseudo: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
120
|
+
const pseudoElement = pseudo.startsWith('::') ? pseudo : `::${pseudo}`;
|
|
121
|
+
const selector = baseSelector ? `${baseSelector}${pseudoElement}` : pseudoElement;
|
|
122
|
+
const rule: CSSRule = { selector, styles, type: 'pseudo-element' };
|
|
123
|
+
this.rules.push(rule);
|
|
124
|
+
return rule;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Attribute Selectors
|
|
128
|
+
addAttribute(attr: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
129
|
+
const attrSelector = attr.startsWith('[') ? attr : `[${attr}]`;
|
|
130
|
+
const selector = baseSelector ? `${baseSelector}${attrSelector}` : attrSelector;
|
|
131
|
+
const rule: CSSRule = { selector, styles, type: 'attribute' };
|
|
132
|
+
this.rules.push(rule);
|
|
133
|
+
return rule;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
attrEquals(attr: string, value: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
137
|
+
return this.addAttribute(`${attr}="${value}"`, styles, baseSelector);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
attrContainsWord(attr: string, value: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
141
|
+
return this.addAttribute(`${attr}~="${value}"`, styles, baseSelector);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
attrStartsWith(attr: string, value: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
145
|
+
return this.addAttribute(`${attr}^="${value}"`, styles, baseSelector);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
attrEndsWith(attr: string, value: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
149
|
+
return this.addAttribute(`${attr}$="${value}"`, styles, baseSelector);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
attrContains(attr: string, value: string, styles: Record<string, string | number>, baseSelector?: string): CSSRule {
|
|
153
|
+
return this.addAttribute(`${attr}*="${value}"`, styles, baseSelector);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Combinator Selectors
|
|
157
|
+
descendant(ancestor: string, descendant: string, styles: Record<string, string | number>): CSSRule {
|
|
158
|
+
return this.createAndAddRule(`${ancestor} ${descendant}`, styles);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
child(parent: string, childSel: string, styles: Record<string, string | number>): CSSRule {
|
|
162
|
+
return this.createAndAddRule(`${parent} > ${childSel}`, styles);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
adjacentSibling(element: string, sibling: string, styles: Record<string, string | number>): CSSRule {
|
|
166
|
+
return this.createAndAddRule(`${element} + ${sibling}`, styles);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
generalSibling(element: string, sibling: string, styles: Record<string, string | number>): CSSRule {
|
|
170
|
+
return this.createAndAddRule(`${element} ~ ${sibling}`, styles);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
multiple(selectors: string[], styles: Record<string, string | number>): CSSRule {
|
|
174
|
+
return this.createAndAddRule(selectors.join(', '), styles);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Nesting (BEM-style)
|
|
178
|
+
addName(name: string, styles: Record<string, string | number>): CSSRule {
|
|
179
|
+
const selector = name.startsWith('--') ? `&${name}` : `&--${name}`;
|
|
180
|
+
const rule: CSSRule = { selector, styles, type: 'name' };
|
|
181
|
+
return rule;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
nesting(parentRule: CSSRule, ...childRules: CSSRule[]): CSSRule {
|
|
185
|
+
parentRule.nested = childRules;
|
|
186
|
+
return parentRule;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// @keyframes - Animations
|
|
190
|
+
keyframe(name: string, steps: Record<string | number, Record<string, string | number>>): Keyframes {
|
|
191
|
+
const keyframeSteps: KeyframeStep[] = Object.entries(steps).map(([step, styles]) => ({
|
|
192
|
+
step: step === 'from' ? 'from' : step === 'to' ? 'to' : `${step}%`,
|
|
193
|
+
styles
|
|
194
|
+
}));
|
|
195
|
+
const kf: Keyframes = { name, steps: keyframeSteps };
|
|
196
|
+
this.keyframes.push(kf);
|
|
197
|
+
return kf;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
keyframeFromTo(name: string, from: Record<string, string | number>, to: Record<string, string | number>): Keyframes {
|
|
201
|
+
return this.keyframe(name, { from, to });
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// @font-face - Custom Fonts
|
|
205
|
+
fontFace(options: FontFace): FontFace {
|
|
206
|
+
this.fontFaces.push(options);
|
|
207
|
+
return options;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// @import - Import Stylesheets
|
|
211
|
+
import(url: string, mediaQuery?: string): string {
|
|
212
|
+
const importRule = mediaQuery ? `@import url("${url}") ${mediaQuery};` : `@import url("${url}");`;
|
|
213
|
+
this.imports.push(importRule);
|
|
214
|
+
return importRule;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// @media - Media Queries
|
|
218
|
+
media(type: string, condition: string, rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
219
|
+
const mediaRule: MediaRule = { type, condition, rules: this.rulesToCSSRules(rules) };
|
|
220
|
+
this.mediaRules.push(mediaRule);
|
|
221
|
+
return mediaRule;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
mediaScreen(condition: string, rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
225
|
+
return this.media('screen', condition, rules);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
mediaPrint(rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
229
|
+
return this.media('print', '', rules);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
mediaMinWidth(minWidth: string, rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
233
|
+
return this.media('screen', `min-width: ${minWidth}`, rules);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
mediaMaxWidth(maxWidth: string, rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
237
|
+
return this.media('screen', `max-width: ${maxWidth}`, rules);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
mediaDark(rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
241
|
+
const mediaRule: MediaRule = { type: '', condition: 'prefers-color-scheme: dark', rules: this.rulesToCSSRules(rules) };
|
|
242
|
+
this.mediaRules.push(mediaRule);
|
|
243
|
+
return mediaRule;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
mediaLight(rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
247
|
+
const mediaRule: MediaRule = { type: '', condition: 'prefers-color-scheme: light', rules: this.rulesToCSSRules(rules) };
|
|
248
|
+
this.mediaRules.push(mediaRule);
|
|
249
|
+
return mediaRule;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
mediaReducedMotion(rules: Record<string, Record<string, string | number>>): MediaRule {
|
|
253
|
+
const mediaRule: MediaRule = { type: '', condition: 'prefers-reduced-motion: reduce', rules: this.rulesToCSSRules(rules) };
|
|
254
|
+
this.mediaRules.push(mediaRule);
|
|
255
|
+
return mediaRule;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// @container - Container Queries
|
|
259
|
+
container(condition: string, rules: Record<string, Record<string, string | number>>, name?: string): ContainerRule {
|
|
260
|
+
const containerRule: ContainerRule = { name, condition, rules: this.rulesToCSSRules(rules) };
|
|
261
|
+
this.containerRules.push(containerRule);
|
|
262
|
+
return containerRule;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
addContainer(name: string, styles: Record<string, string | number>): CSSRule {
|
|
266
|
+
const containerStyles = { ...styles, containerName: name };
|
|
267
|
+
return this.addClass(name, containerStyles);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// @supports - Feature Queries
|
|
271
|
+
supports(condition: string, rules: Record<string, Record<string, string | number>>): SupportsRule {
|
|
272
|
+
const supportsRule: SupportsRule = { condition, rules: this.rulesToCSSRules(rules) };
|
|
273
|
+
this.supportsRules.push(supportsRule);
|
|
274
|
+
return supportsRule;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// @layer - Cascade Layers
|
|
278
|
+
layerOrder(...layers: string[]): void {
|
|
279
|
+
this._layerOrder = layers;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
layer(name: string, rules: Record<string, Record<string, string | number>>): LayerRule {
|
|
283
|
+
const layerRule: LayerRule = { name, rules: this.rulesToCSSRules(rules) };
|
|
284
|
+
this.layerRules.push(layerRule);
|
|
285
|
+
return layerRule;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Custom Rules
|
|
289
|
+
add(rules: Record<string, Record<string, string | number>>): CSSRule[] {
|
|
290
|
+
const cssRules: CSSRule[] = Object.entries(rules).map(([selector, styles]) => {
|
|
291
|
+
const rule: CSSRule = { selector, styles, type: 'custom' };
|
|
292
|
+
this.rules.push(rule);
|
|
293
|
+
return rule;
|
|
294
|
+
});
|
|
295
|
+
return cssRules;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
important(value: string | number): string {
|
|
299
|
+
return `${value} !important`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Utility Methods
|
|
303
|
+
private toKebabCase(str: string): string {
|
|
304
|
+
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Helper: Create and add rule (eliminates duplication in combinator selectors)
|
|
308
|
+
private createAndAddRule(selector: string, styles: Record<string, string | number>, type: CSSRule['type'] = 'custom'): CSSRule {
|
|
309
|
+
const rule: CSSRule = { selector, styles, type };
|
|
310
|
+
this.rules.push(rule);
|
|
311
|
+
return rule;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Helper: Convert rules object to CSSRule array (eliminates duplication in media/container/supports/layer)
|
|
315
|
+
private rulesToCSSRules(rules: Record<string, Record<string, string | number>>): CSSRule[] {
|
|
316
|
+
return Object.entries(rules).map(([selector, styles]) => ({
|
|
317
|
+
selector,
|
|
318
|
+
styles,
|
|
319
|
+
type: 'custom' as const
|
|
320
|
+
}));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Helper: Render rules with indentation (eliminates duplication in render methods)
|
|
324
|
+
private renderRulesWithIndent(rules: CSSRule[], indent: string = ' '): string {
|
|
325
|
+
return rules.map(rule => this.renderRule(rule, indent)).join('\n');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private stylesToString(styles: Record<string, string | number>, indent: string = ' '): string {
|
|
329
|
+
return Object.entries(styles)
|
|
330
|
+
.map(([prop, value]) => {
|
|
331
|
+
const cssValue = typeof value === 'object' && value !== null && 'name' in value
|
|
332
|
+
? `var(${(value as CSSVariable).name})`
|
|
333
|
+
: value;
|
|
334
|
+
return `${indent}${this.toKebabCase(prop)}: ${cssValue};`;
|
|
335
|
+
})
|
|
336
|
+
.join('\n');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private renderRule(rule: CSSRule, indent: string = ''): string {
|
|
340
|
+
let css = `${indent}${rule.selector} {\n${this.stylesToString(rule.styles, indent + ' ')}\n`;
|
|
341
|
+
|
|
342
|
+
if (rule.nested && rule.nested.length > 0) {
|
|
343
|
+
for (const nestedRule of rule.nested) {
|
|
344
|
+
const nestedSelector = nestedRule.selector.startsWith('&')
|
|
345
|
+
? nestedRule.selector.replace(/&/g, rule.selector)
|
|
346
|
+
: `${rule.selector} ${nestedRule.selector}`;
|
|
347
|
+
css += `\n${indent}${nestedSelector} {\n${this.stylesToString(nestedRule.styles, indent + ' ')}\n${indent}}\n`;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
css += `${indent}}`;
|
|
352
|
+
return css;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
private renderMediaRule(media: MediaRule): string {
|
|
356
|
+
const condition = media.type && media.condition
|
|
357
|
+
? `${media.type} and (${media.condition})`
|
|
358
|
+
: media.type
|
|
359
|
+
? media.type
|
|
360
|
+
: `(${media.condition})`;
|
|
361
|
+
return `@media ${condition} {\n${this.renderRulesWithIndent(media.rules)}\n}`;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
private renderKeyframes(kf: Keyframes): string {
|
|
365
|
+
let css = `@keyframes ${kf.name} {\n`;
|
|
366
|
+
for (const step of kf.steps) {
|
|
367
|
+
css += ` ${step.step} {\n${this.stylesToString(step.styles, ' ')}\n }\n`;
|
|
368
|
+
}
|
|
369
|
+
css += '}';
|
|
370
|
+
return css;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private renderFontFace(ff: FontFace): string {
|
|
374
|
+
let css = '@font-face {\n';
|
|
375
|
+
css += ` font-family: "${ff.fontFamily}";\n`;
|
|
376
|
+
css += ` src: ${ff.src};\n`;
|
|
377
|
+
if (ff.fontWeight) css += ` font-weight: ${ff.fontWeight};\n`;
|
|
378
|
+
if (ff.fontStyle) css += ` font-style: ${ff.fontStyle};\n`;
|
|
379
|
+
if (ff.fontDisplay) css += ` font-display: ${ff.fontDisplay};\n`;
|
|
380
|
+
if (ff.unicodeRange) css += ` unicode-range: ${ff.unicodeRange};\n`;
|
|
381
|
+
css += '}';
|
|
382
|
+
return css;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private renderContainerRule(container: ContainerRule): string {
|
|
386
|
+
const nameStr = container.name ? `${container.name} ` : '';
|
|
387
|
+
return `@container ${nameStr}(${container.condition}) {\n${this.renderRulesWithIndent(container.rules)}\n}`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private renderSupportsRule(supports: SupportsRule): string {
|
|
391
|
+
return `@supports (${supports.condition}) {\n${this.renderRulesWithIndent(supports.rules)}\n}`;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
private renderLayerRule(layer: LayerRule): string {
|
|
395
|
+
return `@layer ${layer.name} {\n${this.renderRulesWithIndent(layer.rules)}\n}`;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Render Output
|
|
399
|
+
render(...additionalRules: (CSSRule | CSSRule[] | MediaRule | Keyframes | ContainerRule | SupportsRule | LayerRule | undefined | null)[]): string {
|
|
400
|
+
const parts: string[] = [];
|
|
401
|
+
|
|
402
|
+
if (this.imports.length > 0) {
|
|
403
|
+
parts.push(this.imports.join('\n'));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (this._layerOrder.length > 0) {
|
|
407
|
+
parts.push(`@layer ${this._layerOrder.join(', ')};`);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (this.variables.length > 0) {
|
|
411
|
+
const varDeclarations = this.variables
|
|
412
|
+
.map(v => ` ${v.name}: ${v.value};`)
|
|
413
|
+
.join('\n');
|
|
414
|
+
parts.push(`:root {\n${varDeclarations}\n}`);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
for (const ff of this.fontFaces) {
|
|
418
|
+
parts.push(this.renderFontFace(ff));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
for (const kf of this.keyframes) {
|
|
422
|
+
parts.push(this.renderKeyframes(kf));
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const allRules: CSSRule[] = [...this.rules];
|
|
426
|
+
const allMediaRules: MediaRule[] = [...this.mediaRules];
|
|
427
|
+
const allKeyframes: Keyframes[] = [];
|
|
428
|
+
const allContainerRules: ContainerRule[] = [...this.containerRules];
|
|
429
|
+
const allSupportsRules: SupportsRule[] = [...this.supportsRules];
|
|
430
|
+
const allLayerRules: LayerRule[] = [...this.layerRules];
|
|
431
|
+
|
|
432
|
+
for (const item of additionalRules) {
|
|
433
|
+
if (!item) continue;
|
|
434
|
+
if (Array.isArray(item)) {
|
|
435
|
+
allRules.push(...item);
|
|
436
|
+
} else if ('condition' in item && 'rules' in item && !('name' in item && 'steps' in item)) {
|
|
437
|
+
if ('type' in item) {
|
|
438
|
+
allMediaRules.push(item as MediaRule);
|
|
439
|
+
} else if ('name' in item && typeof (item as any).name === 'string') {
|
|
440
|
+
allContainerRules.push(item as ContainerRule);
|
|
441
|
+
} else {
|
|
442
|
+
allSupportsRules.push(item as SupportsRule);
|
|
443
|
+
}
|
|
444
|
+
} else if ('name' in item && 'steps' in item) {
|
|
445
|
+
allKeyframes.push(item as Keyframes);
|
|
446
|
+
} else if ('name' in item && 'rules' in item) {
|
|
447
|
+
allLayerRules.push(item as LayerRule);
|
|
448
|
+
} else {
|
|
449
|
+
allRules.push(item as CSSRule);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
for (const kf of allKeyframes) {
|
|
454
|
+
parts.push(this.renderKeyframes(kf));
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
for (const layer of allLayerRules) {
|
|
458
|
+
parts.push(this.renderLayerRule(layer));
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
for (const rule of allRules) {
|
|
462
|
+
parts.push(this.renderRule(rule));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
for (const supports of allSupportsRules) {
|
|
466
|
+
parts.push(this.renderSupportsRule(supports));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
for (const container of allContainerRules) {
|
|
470
|
+
parts.push(this.renderContainerRule(container));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
for (const media of allMediaRules) {
|
|
474
|
+
parts.push(this.renderMediaRule(media));
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return parts.join('\n\n');
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
inject(styleId?: string): HTMLStyleElement {
|
|
481
|
+
const css = this.render();
|
|
482
|
+
const style = document.createElement('style');
|
|
483
|
+
if (styleId) style.id = styleId;
|
|
484
|
+
style.textContent = css;
|
|
485
|
+
document.head.appendChild(style);
|
|
486
|
+
return style;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
clear(): void {
|
|
490
|
+
this.variables = [];
|
|
491
|
+
this.rules = [];
|
|
492
|
+
this.mediaRules = [];
|
|
493
|
+
this.keyframes = [];
|
|
494
|
+
this.fontFaces = [];
|
|
495
|
+
this.imports = [];
|
|
496
|
+
this.containerRules = [];
|
|
497
|
+
this.supportsRules = [];
|
|
498
|
+
this.layerRules = [];
|
|
499
|
+
this._layerOrder = [];
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export const styles = new CreateStyle();
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
export const {
|
|
507
|
+
addVar, var: getVar,
|
|
508
|
+
addTag, addClass, addId,
|
|
509
|
+
addPseudoClass, addPseudoElement, addAttribute, attrEquals, attrContainsWord, attrStartsWith, attrEndsWith, attrContains,
|
|
510
|
+
descendant, child: childStyle, adjacentSibling, generalSibling, multiple: multipleStyle,
|
|
511
|
+
addName, nesting,
|
|
512
|
+
keyframe, keyframeFromTo,
|
|
513
|
+
fontFace,
|
|
514
|
+
import: importStyle,
|
|
515
|
+
media: mediaStyle,
|
|
516
|
+
mediaScreen, mediaPrint, mediaMinWidth, mediaMaxWidth, mediaDark, mediaLight, mediaReducedMotion,
|
|
517
|
+
container, addContainer,
|
|
518
|
+
supports: supportsStyle,
|
|
519
|
+
layerOrder, layer,
|
|
520
|
+
add: addStyle, important,
|
|
521
|
+
render: renderStyle, inject: injectStyle, clear: clearStyle
|
|
522
|
+
} = styles;
|
|
523
|
+
|
|
524
|
+
export default styles;
|