@navita/engine 0.0.0-main-20230917201540

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.
Files changed (4) hide show
  1. package/index.d.ts +51 -0
  2. package/index.js +870 -0
  3. package/index.mjs +866 -0
  4. package/package.json +19 -0
package/index.mjs ADDED
@@ -0,0 +1,866 @@
1
+ import path from 'node:path';
2
+ import hash from '@emotion/hash';
3
+ import { SourceMapGenerator } from 'source-map';
4
+ import createSort from 'sort-css-media-queries/lib/create-sort.js';
5
+
6
+ class Cache {
7
+ constructor(_idGenerator){
8
+ this._idGenerator = _idGenerator;
9
+ this._items = {};
10
+ }
11
+ getOrStore(value) {
12
+ const cacheKey = JSON.stringify(value);
13
+ if (this._items[cacheKey]) {
14
+ return this._items[cacheKey];
15
+ }
16
+ return this._items[cacheKey] = {
17
+ id: this._idGenerator.next(value),
18
+ ...value
19
+ };
20
+ }
21
+ items(ids = undefined) {
22
+ const items = Object.values(this._items);
23
+ if (ids === undefined) {
24
+ return items;
25
+ }
26
+ return items.filter((item)=>ids.includes(item.id));
27
+ }
28
+ }
29
+
30
+ function isObject(val) {
31
+ return val != null && typeof val === 'object' && Array.isArray(val) === false;
32
+ }
33
+
34
+ function splitStyleBlocks(blocks) {
35
+ const atRules = [];
36
+ const rules = [];
37
+ for (const block of blocks){
38
+ if (block.media || block.support) {
39
+ atRules.push(block);
40
+ } else {
41
+ rules.push(block);
42
+ }
43
+ }
44
+ return {
45
+ atRules,
46
+ rules
47
+ };
48
+ }
49
+
50
+ class IDGenerator {
51
+ counter = 1;
52
+ next() {
53
+ return this.counter++;
54
+ }
55
+ }
56
+
57
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
58
+ const charLength = chars.length;
59
+ class AlphaIDGenerator {
60
+ constructor(blacklist = [
61
+ 'ad'
62
+ ]){
63
+ this.blacklist = blacklist;
64
+ this.counter = 1;
65
+ }
66
+ next() {
67
+ const nextString = (id, className = '')=>{
68
+ if (id <= charLength) {
69
+ return chars[id - 1] + className;
70
+ }
71
+ return nextString(id / charLength | 0, chars[(id - 1) % charLength] + className);
72
+ };
73
+ let className;
74
+ do {
75
+ className = nextString(this.counter++);
76
+ }while (this.blacklist.includes(className.toLowerCase()))
77
+ return className;
78
+ }
79
+ }
80
+
81
+ class PropertyValueIDGenerator {
82
+ property = new AlphaIDGenerator();
83
+ cache = {};
84
+ next({ property , media ='' , support ='' , pseudo ='' , value }) {
85
+ const propertyKey = `${media}${support}${pseudo}${property}`;
86
+ if (this.cache[propertyKey] === undefined) {
87
+ this.cache[propertyKey] = {
88
+ key: this.property.next(),
89
+ cache: {}
90
+ };
91
+ }
92
+ const entry = this.cache[propertyKey];
93
+ if (entry.cache[value] === undefined) {
94
+ entry.cache[value] = Object.keys(entry.cache).length + 1;
95
+ }
96
+ return `${entry.key}${entry.cache[value]}`;
97
+ }
98
+ }
99
+
100
+ // https://github.com/styletron/styletron/blob/b552ddc5050a8cc5eec84a46a299d937d3bb0112/packages/styletron-engine-atomic/src/hyphenate-style-name.ts
101
+ const uppercasePattern = /[A-Z]/g;
102
+ const msPattern = /^ms-/;
103
+ const cache = {};
104
+ function hyphenateProperty(property) {
105
+ return property in cache ? cache[property] : cache[property] = property.replace(uppercasePattern, "-$&").toLowerCase().replace(msPattern, "-ms-");
106
+ }
107
+
108
+ // https://github.com/styletron/styletron/blob/b552ddc5050a8cc5eec84a46a299d937d3bb0112/packages/styletron-engine-atomic/src/css.ts#L36
109
+ function declarationsToBlock(style) {
110
+ let css = "";
111
+ for(const prop in style){
112
+ const val = style[prop];
113
+ if (typeof val === "string" || typeof val === "number") {
114
+ css += `${hyphenateProperty(prop)}:${val};`;
115
+ }
116
+ }
117
+ return css.slice(0, -1);
118
+ }
119
+
120
+ function printFontFaces(blocks) {
121
+ let fontFaces = '';
122
+ for (const block of blocks){
123
+ for (const rule of block.rule){
124
+ fontFaces += `@font-face{font-family:${block.id};${declarationsToBlock(rule)}}`;
125
+ }
126
+ }
127
+ return fontFaces;
128
+ }
129
+
130
+ // https://github.com/styletron/styletron/blob/master/packages/styletron-engine-atomic/src/css.ts#L48
131
+ function keyframesToBlock(keyframes) {
132
+ let result = "";
133
+ for(const animationState in keyframes){
134
+ result += `${animationState}{${declarationsToBlock(keyframes[animationState])}}`;
135
+ }
136
+ return result;
137
+ }
138
+ function printKeyFrames(blocks) {
139
+ let keyframes = '';
140
+ for (const block of blocks){
141
+ keyframes += `@keyframes ${block.id}{${keyframesToBlock(block.rule)}}`;
142
+ }
143
+ return keyframes;
144
+ }
145
+
146
+ function printSourceMap(sourceMapReferences, content) {
147
+ if (content.length === 0) {
148
+ return content;
149
+ }
150
+ const entries = Object.entries(sourceMapReferences);
151
+ if (entries.length === 0) {
152
+ return content;
153
+ }
154
+ const sourceMap = new SourceMapGenerator({
155
+ file: "navita.css"
156
+ });
157
+ const references = entries.flatMap(([filePath, references])=>references.map((reference)=>({
158
+ filePath,
159
+ ...reference
160
+ })));
161
+ for (const reference of references){
162
+ const { filePath , selector , line , column } = reference;
163
+ const generatedColumn = content.length - 1;
164
+ content += `${selector}{/* Only used for sourceMap */}`;
165
+ sourceMap.addMapping({
166
+ source: filePath,
167
+ original: {
168
+ line,
169
+ column
170
+ },
171
+ generated: {
172
+ line: 1,
173
+ column: generatedColumn
174
+ }
175
+ });
176
+ }
177
+ const sourceMapContent = Buffer.from(sourceMap.toString()).toString('base64');
178
+ content += `\n/*# sourceMappingURL=data:application/json;base64,${sourceMapContent} */`;
179
+ return content;
180
+ }
181
+
182
+ /**
183
+ * This list comes from:
184
+ * https://github.com/callstack/linaria/blob/master/packages/atomic/src/processors/helpers/propertyPriority.ts
185
+ */ const shorthandProperties = {
186
+ // The `all` property resets everything, and should effectively have priority zero.
187
+ // In practice, this can be achieved by using: div { all: ... } to have even less specificity, but to avoid duplicating all selectors, we just let it be
188
+ // 'all': []
189
+ animation: [
190
+ 'animation-name',
191
+ 'animation-duration',
192
+ 'animation-timing-function',
193
+ 'animation-delay',
194
+ 'animation-iteration-count',
195
+ 'animation-direction',
196
+ 'animation-fill-mode',
197
+ 'animation-play-state'
198
+ ],
199
+ background: [
200
+ 'background-attachment',
201
+ 'background-clip',
202
+ 'background-color',
203
+ 'background-image',
204
+ 'background-origin',
205
+ 'background-position',
206
+ 'background-repeat',
207
+ 'background-size'
208
+ ],
209
+ border: [
210
+ 'border-color',
211
+ 'border-style',
212
+ 'border-width'
213
+ ],
214
+ 'border-block-end': [
215
+ 'border-block-end-color',
216
+ 'border-block-end-style',
217
+ 'border-block-end-width'
218
+ ],
219
+ 'border-block-start': [
220
+ 'border-block-start-color',
221
+ 'border-block-start-style',
222
+ 'border-block-start-width'
223
+ ],
224
+ 'border-bottom': [
225
+ 'border-bottom-color',
226
+ 'border-bottom-style',
227
+ 'border-bottom-width'
228
+ ],
229
+ 'border-color': [
230
+ 'border-bottom-color',
231
+ 'border-left-color',
232
+ 'border-right-color',
233
+ 'border-top-color'
234
+ ],
235
+ 'border-image': [
236
+ 'border-image-outset',
237
+ 'border-image-repeat',
238
+ 'border-image-slice',
239
+ 'border-image-source',
240
+ 'border-image-width'
241
+ ],
242
+ 'border-inline-end': [
243
+ 'border-inline-end-color',
244
+ 'border-inline-end-style',
245
+ 'border-inline-end-width'
246
+ ],
247
+ 'border-inline-start': [
248
+ 'border-inline-start-color',
249
+ 'border-inline-start-style',
250
+ 'border-inline-start-width'
251
+ ],
252
+ 'border-left': [
253
+ 'border-left-color',
254
+ 'border-left-style',
255
+ 'border-left-width'
256
+ ],
257
+ 'border-radius': [
258
+ 'border-top-left-radius',
259
+ 'border-top-right-radius',
260
+ 'border-bottom-right-radius',
261
+ 'border-bottom-left-radius'
262
+ ],
263
+ 'border-right': [
264
+ 'border-right-color',
265
+ 'border-right-style',
266
+ 'border-right-width'
267
+ ],
268
+ 'border-style': [
269
+ 'border-bottom-style',
270
+ 'border-left-style',
271
+ 'border-right-style',
272
+ 'border-top-style'
273
+ ],
274
+ 'border-top': [
275
+ 'border-top-color',
276
+ 'border-top-style',
277
+ 'border-top-width'
278
+ ],
279
+ 'border-width': [
280
+ 'border-bottom-width',
281
+ 'border-left-width',
282
+ 'border-right-width',
283
+ 'border-top-width'
284
+ ],
285
+ 'column-rule': [
286
+ 'column-rule-width',
287
+ 'column-rule-style',
288
+ 'column-rule-color'
289
+ ],
290
+ columns: [
291
+ 'column-count',
292
+ 'column-width'
293
+ ],
294
+ flex: [
295
+ 'flex-grow',
296
+ 'flex-shrink',
297
+ 'flex-basis'
298
+ ],
299
+ 'flex-flow': [
300
+ 'flex-direction',
301
+ 'flex-wrap'
302
+ ],
303
+ font: [
304
+ 'font-family',
305
+ 'font-size',
306
+ 'font-stretch',
307
+ 'font-style',
308
+ 'font-variant',
309
+ 'font-weight',
310
+ 'line-height'
311
+ ],
312
+ gap: [
313
+ 'row-gap',
314
+ 'column-gap'
315
+ ],
316
+ grid: [
317
+ 'grid-auto-columns',
318
+ 'grid-auto-flow',
319
+ 'grid-auto-rows',
320
+ 'grid-template-areas',
321
+ 'grid-template-columns',
322
+ 'grid-template-rows'
323
+ ],
324
+ 'grid-area': [
325
+ 'grid-row-start',
326
+ 'grid-column-start',
327
+ 'grid-row-end',
328
+ 'grid-column-end'
329
+ ],
330
+ 'grid-column': [
331
+ 'grid-column-end',
332
+ 'grid-column-start'
333
+ ],
334
+ 'grid-row': [
335
+ 'grid-row-end',
336
+ 'grid-row-start'
337
+ ],
338
+ 'grid-template': [
339
+ 'grid-template-areas',
340
+ 'grid-template-columns',
341
+ 'grid-template-rows'
342
+ ],
343
+ 'list-style': [
344
+ 'list-style-image',
345
+ 'list-style-position',
346
+ 'list-style-type'
347
+ ],
348
+ margin: [
349
+ 'margin-bottom',
350
+ 'margin-left',
351
+ 'margin-right',
352
+ 'margin-top'
353
+ ],
354
+ mask: [
355
+ 'mask-clip',
356
+ 'mask-composite',
357
+ 'mask-image',
358
+ 'mask-mode',
359
+ 'mask-origin',
360
+ 'mask-position',
361
+ 'mask-repeat',
362
+ 'mask-size'
363
+ ],
364
+ offset: [
365
+ 'offset-anchor',
366
+ 'offset-distance',
367
+ 'offset-path',
368
+ 'offset-position',
369
+ 'offset-rotate'
370
+ ],
371
+ outline: [
372
+ 'outline-color',
373
+ 'outline-style',
374
+ 'outline-width'
375
+ ],
376
+ overflow: [
377
+ 'overflow-x',
378
+ 'overflow-y'
379
+ ],
380
+ padding: [
381
+ 'padding-bottom',
382
+ 'padding-left',
383
+ 'padding-right',
384
+ 'padding-top'
385
+ ],
386
+ 'place-content': [
387
+ 'align-content',
388
+ 'justify-content'
389
+ ],
390
+ 'place-items': [
391
+ 'align-items',
392
+ 'justify-items'
393
+ ],
394
+ 'place-self': [
395
+ 'align-self',
396
+ 'justify-self'
397
+ ],
398
+ 'scroll-margin': [
399
+ 'scroll-margin-bottom',
400
+ 'scroll-margin-left',
401
+ 'scroll-margin-right',
402
+ 'scroll-margin-top'
403
+ ],
404
+ 'scroll-padding': [
405
+ 'scroll-padding-bottom',
406
+ 'scroll-padding-left',
407
+ 'scroll-padding-right',
408
+ 'scroll-padding-top'
409
+ ],
410
+ 'text-decoration': [
411
+ 'text-decoration-color',
412
+ 'text-decoration-line',
413
+ 'text-decoration-style',
414
+ 'text-decoration-thickness'
415
+ ],
416
+ 'text-emphasis': [
417
+ 'text-emphasis-color',
418
+ 'text-emphasis-style'
419
+ ],
420
+ transition: [
421
+ 'transition-delay',
422
+ 'transition-duration',
423
+ 'transition-property',
424
+ 'transition-timing-function'
425
+ ]
426
+ };
427
+ const longhands = Object.values(shorthandProperties).reduce((a, b)=>[
428
+ ...a,
429
+ ...b
430
+ ], []);
431
+ /**
432
+ * The concept here is that shorthand properties, such as "border" gets
433
+ * a priority of one, while longhand properties, such as "border-color" gets
434
+ * a priority of 2.
435
+ *
436
+ * Read more:
437
+ * @see https://weser.io/blog/the-shorthand-longhand-problem-in-atomic-css
438
+ * @see https://www.w3.org/TR/selectors-3/#specificity
439
+ */ const getPropertyPriority = (property)=>longhands.includes(property) ? 2 : 1;
440
+
441
+ function printStyleBlocks(blocks) {
442
+ let stylesheet = '';
443
+ let previousStyle;
444
+ for (const style of blocks){
445
+ if (style.type === 'static' && previousStyle && (previousStyle.selector !== style.selector || previousStyle.pseudo !== style.pseudo || previousStyle.media !== style.media || previousStyle.support !== style.support)) {
446
+ stylesheet += '}';
447
+ }
448
+ // Close support queries:
449
+ // 1. When the current style is not a support query, and the previous style was support query
450
+ // 2. When the current style is a support query and the previous style was a support query with a different support query
451
+ if (previousStyle && previousStyle.support && (!style.support || style.support !== previousStyle.support)) {
452
+ stylesheet += '}';
453
+ }
454
+ // Close media queries:
455
+ // 1. When the current style is not a media query, and the previous style was media query
456
+ // 2. When the current style is a media query and the previous style was a media query with a different media query
457
+ if (previousStyle && previousStyle.media && (!style.media || style.media !== previousStyle.media)) {
458
+ stylesheet += '}';
459
+ }
460
+ // Only add media queries if the previous style was not the same media query
461
+ if (style.media && previousStyle?.media !== style.media) {
462
+ stylesheet += `@media ${style.media}{`;
463
+ }
464
+ // Only add support queries if the previous style was not the same support query
465
+ if (style.support && previousStyle?.support !== style.support) {
466
+ stylesheet += `@supports ${style.support}{`;
467
+ }
468
+ if (style.type === 'rule') {
469
+ const className = `.${style.id}`.repeat(getPropertyPriority(style.property));
470
+ stylesheet += `${className}${style.pseudo}{`;
471
+ } else if (style.type === 'static' && (previousStyle?.selector !== style.selector || previousStyle?.pseudo !== style.pseudo || previousStyle?.media !== style.media || previousStyle?.support !== style.support)) {
472
+ // If static, we don't add pseudo selectors currently
473
+ stylesheet += `${style.selector}${style.pseudo}{`;
474
+ }
475
+ stylesheet += `${style.property}:${style.value}`;
476
+ if (style.type === 'static') {
477
+ stylesheet += ';';
478
+ }
479
+ if (style.type === 'rule') {
480
+ stylesheet += '}';
481
+ }
482
+ previousStyle = style;
483
+ }
484
+ if (previousStyle?.support) {
485
+ stylesheet += '}';
486
+ }
487
+ if (previousStyle?.media) {
488
+ stylesheet += '}';
489
+ }
490
+ if (previousStyle?.type === 'static') {
491
+ stylesheet += '}';
492
+ }
493
+ return stylesheet;
494
+ }
495
+
496
+ const sortCSSMediaQueries = createSort();
497
+ function sortAtRules(blocks) {
498
+ return blocks.sort((a, b)=>sortCSSMediaQueries(a.media, b.media) || a.support.localeCompare(b.support));
499
+ }
500
+
501
+ function generateCombinedAtRules(currentMediaQuery, nestedMediaQuery) {
502
+ if (currentMediaQuery.length === 0) {
503
+ return nestedMediaQuery;
504
+ }
505
+ return `${currentMediaQuery} and ${nestedMediaQuery}`;
506
+ }
507
+
508
+ function isMediaQuery(property) {
509
+ return property.startsWith('@media');
510
+ }
511
+
512
+ const regex$1 = /^([:\[>&])/;
513
+ function isNestedSelector(property) {
514
+ return regex$1.test(property);
515
+ }
516
+
517
+ function isSupportsQuery(property) {
518
+ return property.startsWith("@supports");
519
+ }
520
+
521
+ const regex = /var\(([^,]+).*\)/;
522
+ function normalizeCSSVarsProperty(property) {
523
+ if (!property.startsWith('var(')) {
524
+ return property;
525
+ }
526
+ const matches = property.match(regex);
527
+ if (!matches) {
528
+ return property;
529
+ }
530
+ return matches[1];
531
+ }
532
+
533
+ function normalizeNestedProperty(nestedProperty) {
534
+ if (nestedProperty.charAt(0) === '&') {
535
+ return nestedProperty.slice(1);
536
+ }
537
+ return nestedProperty;
538
+ }
539
+
540
+ const UNITLESS = {
541
+ animationIterationCount: true,
542
+ borderImage: true,
543
+ borderImageOutset: true,
544
+ borderImageSlice: true,
545
+ borderImageWidth: true,
546
+ boxFlex: true,
547
+ boxFlexGroup: true,
548
+ columnCount: true,
549
+ columns: true,
550
+ flex: true,
551
+ flexGrow: true,
552
+ flexShrink: true,
553
+ fontWeight: true,
554
+ gridArea: true,
555
+ gridColumn: true,
556
+ gridColumnEnd: true,
557
+ gridColumnStart: true,
558
+ gridRow: true,
559
+ gridRowEnd: true,
560
+ gridRowStart: true,
561
+ initialLetter: true,
562
+ lineClamp: true,
563
+ lineHeight: true,
564
+ maxLines: true,
565
+ opacity: true,
566
+ order: true,
567
+ orphans: true,
568
+ scale: true,
569
+ tabSize: true,
570
+ WebkitLineClamp: true,
571
+ widows: true,
572
+ zIndex: true,
573
+ zoom: true,
574
+ // svg properties
575
+ fillOpacity: true,
576
+ floodOpacity: true,
577
+ maskBorder: true,
578
+ maskBorderOutset: true,
579
+ maskBorderSlice: true,
580
+ maskBorderWidth: true,
581
+ shapeImageThreshold: true,
582
+ stopOpacity: true,
583
+ strokeDashoffset: true,
584
+ strokeMiterlimit: true,
585
+ strokeOpacity: true,
586
+ strokeWidth: true
587
+ };
588
+ function pixelifyProperties(property, value) {
589
+ if (value !== 0 && !UNITLESS[property]) {
590
+ return `${value}px`;
591
+ }
592
+ return value;
593
+ }
594
+
595
+ // https://github.com/vanilla-extract-css/vanilla-extract/blob/40d7e72c041989a4dc847dc66b94a4c680b5536e/packages/css/src/transformCss.ts#L277
596
+ function transformContentProperty(value) {
597
+ return value && (value.includes('"') || value.includes("'") || /^([A-Za-z\-]+\([^]*|[^]*-quote|inherit|initial|none|normal|revert|unset)(\s|$)/.test(value)) ? value : `"${value}"`;
598
+ }
599
+
600
+ const transformValuePropertyMap = {
601
+ content: transformContentProperty
602
+ };
603
+ function processStyles({ cache , type }) {
604
+ return function process({ styles , pseudo ="" , media ="" , support ="" , selector ="" }) {
605
+ const result = [];
606
+ for (const [property, value] of Object.entries(styles)){
607
+ if (isObject(value)) {
608
+ if (isMediaQuery(property)) {
609
+ const combinedMedia = generateCombinedAtRules(media, property.slice(6).trim());
610
+ result.push(...process({
611
+ styles: value,
612
+ pseudo,
613
+ media: combinedMedia,
614
+ support,
615
+ selector
616
+ }));
617
+ } else if (isSupportsQuery(property)) {
618
+ const combinedSupport = generateCombinedAtRules(support, property.slice(9).trim());
619
+ result.push(...process({
620
+ styles: value,
621
+ pseudo,
622
+ media,
623
+ support: combinedSupport,
624
+ selector
625
+ }));
626
+ } else if (isNestedSelector(property)) {
627
+ // This is only allowed in simple pseudos currently.
628
+ const copies = property.split(',').map((p)=>p.trim());
629
+ for (const copy of copies){
630
+ result.push(...process({
631
+ styles: value,
632
+ pseudo: pseudo + normalizeNestedProperty(copy),
633
+ media,
634
+ support,
635
+ selector
636
+ }));
637
+ }
638
+ } else {
639
+ console.warn("Unknown property", property);
640
+ }
641
+ } else {
642
+ let newProperty = normalizeCSSVarsProperty(property);
643
+ let newValue = value;
644
+ if (typeof value === "string") {
645
+ newValue = value.trim().replace(/;[\n\s]*$/, "");
646
+ }
647
+ if (typeof value === "number") {
648
+ newValue = pixelifyProperties(newProperty, value);
649
+ }
650
+ if (transformValuePropertyMap[newProperty]) {
651
+ newValue = transformValuePropertyMap[newProperty](value);
652
+ }
653
+ newProperty = hyphenateProperty(newProperty);
654
+ // Remove trailing semicolon and new lines with regex
655
+ result.push(cache.getOrStore({
656
+ type,
657
+ selector,
658
+ property: newProperty,
659
+ value: newValue,
660
+ pseudo,
661
+ media,
662
+ support
663
+ }));
664
+ }
665
+ }
666
+ return result;
667
+ };
668
+ }
669
+
670
+ class ClassList extends String {
671
+ }
672
+
673
+ class Static {
674
+ }
675
+
676
+ const defaultOptions = {
677
+ enableSourceMaps: false,
678
+ enableDebugIdentifiers: false
679
+ };
680
+ class Engine {
681
+ caches = {
682
+ rule: new Cache(new PropertyValueIDGenerator()),
683
+ static: new Cache(new IDGenerator()),
684
+ keyframes: new Cache(new AlphaIDGenerator()),
685
+ fontFace: new Cache(new AlphaIDGenerator()),
686
+ identifiers: new Cache(new AlphaIDGenerator())
687
+ };
688
+ usedIds = {};
689
+ identifierCount = 0;
690
+ options = {};
691
+ sourceMapReferences = {};
692
+ constructor(options = {}){
693
+ this.options = {
694
+ ...defaultOptions,
695
+ ...Object.keys(options).reduce((acc, key)=>{
696
+ if (options[key] !== undefined) {
697
+ acc[key] = options[key];
698
+ }
699
+ return acc;
700
+ }, {})
701
+ };
702
+ }
703
+ addStatic(selector, styles) {
704
+ this.addUsedIds("static", processStyles({
705
+ type: "static",
706
+ cache: this.caches.static
707
+ })({
708
+ styles,
709
+ selector
710
+ }).map((style)=>style.id));
711
+ return new Static();
712
+ }
713
+ addStyle(styles) {
714
+ const rules = processStyles({
715
+ type: "rule",
716
+ cache: this.caches.rule
717
+ })({
718
+ styles
719
+ });
720
+ const ids = rules.map((rule)=>rule.id);
721
+ this.addUsedIds("rule", ids);
722
+ return new ClassList(ids.join(" "));
723
+ }
724
+ addFontFace(fontFace) {
725
+ const { id } = this.caches.fontFace.getOrStore({
726
+ type: "fontFace",
727
+ rule: Array.isArray(fontFace) ? fontFace : [
728
+ fontFace
729
+ ]
730
+ });
731
+ this.addUsedIds("fontFace", [
732
+ id
733
+ ]);
734
+ return id;
735
+ }
736
+ addKeyframes(keyframes) {
737
+ const { id } = this.caches.keyframes.getOrStore({
738
+ type: "keyframes",
739
+ rule: keyframes
740
+ });
741
+ this.addUsedIds("keyframes", [
742
+ id
743
+ ]);
744
+ return id;
745
+ }
746
+ addSourceMapReference({ filePath , identifier , classList , line , column , index }) {
747
+ if (!this.options.enableSourceMaps) {
748
+ return false;
749
+ }
750
+ const { name } = path.parse(filePath);
751
+ const extraClass = this.options.enableDebugIdentifiers ? `${name}_${identifier}` : '';
752
+ const selector = '.' + classList.toString().split(' ').concat(extraClass).filter(Boolean).join('.');
753
+ if (index === 0 || !this.sourceMapReferences[filePath]) {
754
+ this.sourceMapReferences[filePath] = [];
755
+ }
756
+ this.sourceMapReferences[filePath][index] = {
757
+ selector,
758
+ line,
759
+ column
760
+ };
761
+ return extraClass;
762
+ }
763
+ generateIdentifier(value) {
764
+ if (typeof value === 'undefined') {
765
+ let identifier = hash((this.identifierCount++).toString(36));
766
+ if (identifier.match(/^\d/)) {
767
+ identifier = `_${identifier}`;
768
+ }
769
+ return identifier;
770
+ }
771
+ const newValue = JSON.stringify(value);
772
+ const { id } = this.caches.identifiers.getOrStore({
773
+ value: newValue
774
+ });
775
+ this.addUsedIds("identifiers", [
776
+ id
777
+ ]);
778
+ return `_${id}`;
779
+ }
780
+ renderCssToString(options) {
781
+ const { filePaths , usedIds , opinionatedLayers =false } = options || {};
782
+ // We prioritize ids over filePaths. If neither are provided, we use all the used filePaths.
783
+ const { keyframes: keyframesCache , fontFace: fontFaceCache , static: staticCache , rule: ruleCache } = usedIds ?? this.getUsedCacheIds(filePaths ?? Object.keys(this.usedIds));
784
+ const { atRules , rules } = splitStyleBlocks(this.caches.rule.items(ruleCache));
785
+ const keyFrameCss = printKeyFrames(this.caches.keyframes.items(keyframesCache));
786
+ const fontFaceCss = printFontFaces(this.caches.fontFace.items(fontFaceCache));
787
+ const staticCss = printStyleBlocks(this.caches.static.items(staticCache));
788
+ const atRulesCss = printStyleBlocks(sortAtRules(atRules));
789
+ const rulesCss = printStyleBlocks(rules);
790
+ if (opinionatedLayers) {
791
+ const result = `${keyFrameCss}${fontFaceCss}` + (staticCss.length > 0 ? `@layer static{${staticCss}}` : '') + (rulesCss.length > 0 ? `@layer rules{${rulesCss}}` : '') + (atRulesCss.length > 0 ? `@layer at{${atRulesCss}}` : '');
792
+ if (result.length > 0) {
793
+ return `@layer static,rules,at;${result}`;
794
+ }
795
+ return '';
796
+ }
797
+ return printSourceMap(this.sourceMapReferences, keyFrameCss + fontFaceCss + staticCss + rulesCss + atRulesCss);
798
+ }
799
+ serialize() {
800
+ const { caches , usedIds , identifierCount , sourceMapReferences } = this;
801
+ return JSON.stringify({
802
+ caches,
803
+ usedIds,
804
+ identifierCount,
805
+ sourceMapReferences
806
+ });
807
+ }
808
+ async deserialize(buffer) {
809
+ const data = JSON.parse(buffer.toString());
810
+ function assign(target, source) {
811
+ for(const key in source){
812
+ if (isObject(target[key]) && isObject(source[key])) {
813
+ assign(target[key], source[key]);
814
+ } else {
815
+ target[key] = source[key];
816
+ }
817
+ }
818
+ return target;
819
+ }
820
+ assign(this, data);
821
+ }
822
+ setFilePath(filePath) {
823
+ this.filePath = filePath;
824
+ }
825
+ clearUsedIds(filePath) {
826
+ if (filePath === undefined) {
827
+ return;
828
+ }
829
+ this.usedIds[filePath] = {};
830
+ }
831
+ addUsedIds(cacheType, identifiers) {
832
+ const { filePath } = this;
833
+ if (filePath === undefined) {
834
+ return;
835
+ }
836
+ if (this.usedIds[filePath] === undefined) {
837
+ this.usedIds[filePath] = {};
838
+ }
839
+ if (this.usedIds[filePath][cacheType] === undefined) {
840
+ this.usedIds[filePath][cacheType] = [];
841
+ }
842
+ this.usedIds[filePath][cacheType] = [
843
+ ...new Set([
844
+ ...this.usedIds[filePath][cacheType],
845
+ ...identifiers
846
+ ])
847
+ ];
848
+ }
849
+ getUsedCacheIds(filePaths = []) {
850
+ return filePaths.reduce((acc, filePath)=>({
851
+ ...acc,
852
+ ...Object.keys(this.usedIds[filePath] || []).reduce((cache, key)=>({
853
+ ...cache,
854
+ [key]: [
855
+ ...acc[key] || [],
856
+ ...this.usedIds[filePath][key] || []
857
+ ]
858
+ }), {})
859
+ }), Object.keys(this.caches).reduce((acc, key)=>({
860
+ ...acc,
861
+ [key]: []
862
+ }), {}));
863
+ }
864
+ }
865
+
866
+ export { ClassList, Engine, Static };