@tbela99/css-parser 0.0.1-rc6 → 0.0.1

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 CHANGED
@@ -10,19 +10,15 @@ CSS parser for node and the browser
10
10
  $ npm install @tbela99/css-parser
11
11
  ```
12
12
 
13
- ### Features
13
+ ## Features
14
14
 
15
15
  - fault tolerant parser, will try to fix invalid tokens according to the CSS syntax module 3 recommendations.
16
16
  - efficient minification, see [benchmark](https://tbela99.github.io/css-parser/benchmark/index.html)
17
- - replace @import at-rules with actual css content of the imported rule
18
17
  - automatically generate nested css rules
18
+ - compute css shorthands. see the list below
19
19
  - expand nested css
20
20
  - works the same way in node and web browser
21
21
 
22
- ### Performance
23
-
24
- - flatten @import
25
-
26
22
  ## Transform
27
23
 
28
24
  Parse and render css in a single pass.
@@ -131,7 +127,7 @@ import as a CommonJS module
131
127
 
132
128
  ```javascript
133
129
 
134
- import {transform} from '@tbela99/css-parser/cjs';
130
+ const {transform} = require('@tbela99/css-parser/cjs');
135
131
 
136
132
  // ...
137
133
  ```
@@ -303,3 +299,42 @@ table.colortable th {
303
299
 
304
300
  - typ: string 'Stylesheet'
305
301
  - chi: array of children
302
+
303
+ ## Minification
304
+
305
+ - [x] merge identical rules
306
+ - [x] merge adjacent rules
307
+ - [x] minify colors
308
+ - [x] minify numbers and Dimensions tokens
309
+ - [x] compute shorthand: see the list below
310
+ - [x] remove redundant declarations
311
+ - [x] conditionally unwrap :is()
312
+ - [x] automatic css nesting
313
+ - [x] automatically wrap selectors using :is()
314
+ - [x] multi-level shorthand properties (border - [border-width, border-color, border-style, etc.]) https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties
315
+ - [x] avoid reparsing (declarations, selectors, at-rule)
316
+ - [x] node and browser versions
317
+ - [x] decode and replace utf-8 escape sequence
318
+
319
+ ## Computed shorthands
320
+ - [x] background
321
+ - [x] border
322
+ - [x] border-bottom
323
+ - [x] border-color
324
+ - [x] border-left
325
+ - [x] border-radius
326
+ - [x] border-right
327
+ - [x] border-style
328
+ - [x] border-top
329
+ - [x] border-width
330
+ - [x] font
331
+ - [x] inset
332
+ - [x] margin
333
+ - [x] outline
334
+ - [x] overflow
335
+ - [x] padding
336
+ - [x] text-decoration
337
+
338
+ ## Performance
339
+
340
+ - [x] flatten @import
@@ -772,7 +772,8 @@
772
772
  }
773
773
  return val + unit;
774
774
  case 'Perc':
775
- return token.val + '%';
775
+ const perc = reduceNumber(token.val);
776
+ return options.minify && perc == '0' ? '0' : perc + '%';
776
777
  case 'Number':
777
778
  return reduceNumber(token.val);
778
779
  case 'Comment':
@@ -829,7 +830,7 @@
829
830
  if (token.typ == 'Func' && token.chi.length > 0 && colorsFunc.includes(token.val)) {
830
831
  // @ts-ignore
831
832
  for (const v of token.chi) {
832
- if (!['Number', 'Perc', 'Comma', 'Whitespace'].includes(v.typ)) {
833
+ if (!['Number', 'Angle', 'Perc', 'Comma', 'Whitespace', 'Literal'].includes(v.typ)) {
833
834
  return false;
834
835
  }
835
836
  }
@@ -1949,7 +1950,7 @@
1949
1950
  }
1950
1951
  let key;
1951
1952
  for (key of k1) {
1952
- if (!eq(a[key], b[key])) {
1953
+ if (!(key in b) || !eq(a[key], b[key])) {
1953
1954
  return false;
1954
1955
  }
1955
1956
  }
@@ -2244,12 +2245,16 @@
2244
2245
  }
2245
2246
  function next(count = 1) {
2246
2247
  let char = '';
2247
- while (count-- > 0 && ind < iterator.length) {
2248
+ let chr = '';
2249
+ if (count < 0) {
2250
+ return '';
2251
+ }
2252
+ while (count-- && (chr = iterator.charAt(ind + 1))) {
2253
+ char += chr;
2248
2254
  const codepoint = iterator.charCodeAt(++ind);
2249
2255
  if (isNaN(codepoint)) {
2250
2256
  return char;
2251
2257
  }
2252
- char += iterator.charAt(ind);
2253
2258
  if (isNewLine(codepoint)) {
2254
2259
  lin++;
2255
2260
  col = 0;
@@ -2816,7 +2821,7 @@
2816
2821
  if (delim.typ == 'Block-start') {
2817
2822
  const position = map.get(tokens[0]);
2818
2823
  const uniq = new Map;
2819
- parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
2824
+ parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
2820
2825
  if (curr.typ == 'Whitespace') {
2821
2826
  if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
2822
2827
  trimWhiteSpace.includes(array[index + 1]?.typ) ||
@@ -2825,7 +2830,7 @@
2825
2830
  return acc;
2826
2831
  }
2827
2832
  }
2828
- let t = renderToken(curr, { minify: true });
2833
+ let t = renderToken(curr, { minify: false });
2829
2834
  if (t == ',') {
2830
2835
  acc.push([]);
2831
2836
  }
@@ -3826,10 +3831,174 @@
3826
3831
  }
3827
3832
  }
3828
3833
 
3834
+ function* walk(node, parent, root) {
3835
+ yield { node, parent, root };
3836
+ if ('chi' in node) {
3837
+ for (const child of node.chi) {
3838
+ yield* walk(child, node, (root ?? node));
3839
+ }
3840
+ }
3841
+ }
3842
+ function* walkValues(values, parent) {
3843
+ for (const value of values) {
3844
+ // @ts-ignore
3845
+ yield { value, parent };
3846
+ if ('chi' in value) {
3847
+ yield* walkValues(value.chi, value);
3848
+ }
3849
+ }
3850
+ }
3851
+
3852
+ function expand(ast) {
3853
+ //
3854
+ if (!['Rule', 'StyleSheet', 'AtRule'].includes(ast.typ)) {
3855
+ return ast;
3856
+ }
3857
+ if ('Rule' == ast.typ) {
3858
+ return {
3859
+ typ: 'StyleSheet',
3860
+ chi: expandRule(ast)
3861
+ };
3862
+ }
3863
+ if (!('chi' in ast)) {
3864
+ return { ...ast };
3865
+ }
3866
+ const result = { ...ast, chi: [] };
3867
+ // @ts-ignore
3868
+ for (let i = 0; i < ast.chi.length; i++) {
3869
+ // @ts-ignore
3870
+ const node = ast.chi[i];
3871
+ if (node.typ == 'Rule') {
3872
+ // @ts-ignore
3873
+ result.chi.push(...expandRule(node));
3874
+ // i += expanded.length - 1;
3875
+ }
3876
+ else if (node.typ == 'AtRule' && 'chi' in node) {
3877
+ let hasRule = false;
3878
+ let j = node.chi.length;
3879
+ while (j--) {
3880
+ if (node.chi[j].typ == 'Rule' || node.chi[j].typ == 'AtRule') {
3881
+ hasRule = true;
3882
+ break;
3883
+ }
3884
+ }
3885
+ // @ts-ignore
3886
+ result.chi.push({ ...(hasRule ? expand(node) : node) });
3887
+ }
3888
+ else {
3889
+ // @ts-ignore
3890
+ result.chi.push(node);
3891
+ }
3892
+ }
3893
+ return result;
3894
+ }
3895
+ function expandRule(node) {
3896
+ const ast = { ...node, chi: node.chi.slice() };
3897
+ const result = [];
3898
+ if (ast.typ == 'Rule') {
3899
+ let i = 0;
3900
+ for (; i < ast.chi.length; i++) {
3901
+ if (ast.chi[i].typ == 'Rule') {
3902
+ const rule = ast.chi[i];
3903
+ if (!rule.sel.includes('&')) {
3904
+ const selRule = splitRule(rule.sel);
3905
+ selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
3906
+ rule.sel = selRule.reduce((acc, curr) => {
3907
+ acc.push(curr.join(''));
3908
+ return acc;
3909
+ }, []).join(',');
3910
+ }
3911
+ else {
3912
+ rule.sel = replaceCompound(rule.sel, ast.sel);
3913
+ }
3914
+ ast.chi.splice(i--, 1);
3915
+ result.push(...expandRule(rule));
3916
+ }
3917
+ else if (ast.chi[i].typ == 'AtRule') {
3918
+ let astAtRule = ast.chi[i];
3919
+ const values = [];
3920
+ if (astAtRule.nam == 'scope') {
3921
+ if (astAtRule.val.includes('&')) {
3922
+ astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
3923
+ }
3924
+ // @ts-ignore
3925
+ astAtRule = expand(astAtRule);
3926
+ }
3927
+ else {
3928
+ // @ts-ignore
3929
+ const clone = { ...ast, chi: astAtRule.chi.slice() };
3930
+ // @ts-ignore
3931
+ astAtRule.chi.length = 0;
3932
+ for (const r of expandRule(clone)) {
3933
+ if (r.typ == 'AtRule' && 'chi' in r) {
3934
+ if (astAtRule.val !== '' && r.val !== '') {
3935
+ if (astAtRule.nam == 'media' && r.nam == 'media') {
3936
+ r.val = astAtRule.val + ' and ' + r.val;
3937
+ }
3938
+ else if (astAtRule.nam == 'layer' && r.nam == 'layer') {
3939
+ r.val = astAtRule.val + '.' + r.val;
3940
+ }
3941
+ }
3942
+ // @ts-ignore
3943
+ values.push(r);
3944
+ }
3945
+ else if (r.typ == 'Rule') {
3946
+ // @ts-ignore
3947
+ astAtRule.chi.push(...expandRule(r));
3948
+ }
3949
+ else {
3950
+ // @ts-ignore
3951
+ astAtRule.chi.push(r);
3952
+ }
3953
+ }
3954
+ }
3955
+ // @ts-ignore
3956
+ result.push(...(astAtRule.chi.length > 0 ? [astAtRule].concat(values) : values));
3957
+ ast.chi.splice(i--, 1);
3958
+ }
3959
+ }
3960
+ }
3961
+ // @ts-ignore
3962
+ return ast.chi.length > 0 ? [ast].concat(result) : result;
3963
+ }
3964
+ function replaceCompound(input, replace) {
3965
+ const tokens = parseString(input);
3966
+ for (const t of walkValues(tokens)) {
3967
+ if (t.value.typ == 'Literal') {
3968
+ if (t.value.val == '&') {
3969
+ t.value.val = replace;
3970
+ }
3971
+ else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
3972
+ t.value.val = replaceCompoundLiteral(t.value.val, replace);
3973
+ }
3974
+ }
3975
+ }
3976
+ return tokens.reduce((acc, curr) => acc + renderToken(curr), '');
3977
+ }
3978
+ function replaceCompoundLiteral(selector, replace) {
3979
+ const tokens = [''];
3980
+ let i = 0;
3981
+ for (; i < selector.length; i++) {
3982
+ if (selector.charAt(i) == '&') {
3983
+ tokens.push('&');
3984
+ tokens.push('');
3985
+ }
3986
+ else {
3987
+ tokens[tokens.length - 1] += selector.charAt(i);
3988
+ }
3989
+ }
3990
+ return tokens.sort((a, b) => {
3991
+ if (a == '&') {
3992
+ return 1;
3993
+ }
3994
+ return b == '&' ? -1 : 0;
3995
+ }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
3996
+ }
3997
+
3829
3998
  const combinators = ['+', '>', '~'];
3830
3999
  const notEndingWith = ['(', '['].concat(combinators);
3831
4000
  const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
3832
- function minify(ast, options = {}, recursive = false, errors) {
4001
+ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
3833
4002
  function wrapNodes(previous, node, match, ast, i, nodeIndex) {
3834
4003
  // @ts-ignore
3835
4004
  let pSel = match.selector1.reduce(reducer, []).join(',');
@@ -4118,8 +4287,28 @@
4118
4287
  selector2
4119
4288
  };
4120
4289
  }
4290
+ function fixSelector(node) {
4291
+ // @ts-ignore
4292
+ if (node.sel.includes('&')) {
4293
+ const attributes = parseString(node.sel);
4294
+ for (const attr of walkValues(attributes)) {
4295
+ if (attr.value.typ == 'Pseudo-class-func' && attr.value.val == ':is') {
4296
+ let i = attr.value.chi.length;
4297
+ while (i--) {
4298
+ if (attr.value.chi[i].typ == 'Literal' && attr.value.chi[i].val == '&') {
4299
+ attr.value.chi.splice(i, 1);
4300
+ }
4301
+ }
4302
+ }
4303
+ }
4304
+ node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
4305
+ }
4306
+ }
4121
4307
  // @ts-ignore
4122
4308
  if (('chi' in ast) && ast.chi?.length > 0) {
4309
+ if (!nestingContent) {
4310
+ nestingContent = options.nestingRules && ast.typ == 'Rule';
4311
+ }
4123
4312
  let i = 0;
4124
4313
  let previous;
4125
4314
  let node;
@@ -4134,7 +4323,6 @@
4134
4323
  node = ast.chi[i];
4135
4324
  // @ts-ignore
4136
4325
  if (previous == node) {
4137
- // console.error('idem!');
4138
4326
  // @ts-ignore
4139
4327
  ast.chi.splice(i, 1);
4140
4328
  i--;
@@ -4150,7 +4338,6 @@
4150
4338
  i--;
4151
4339
  continue;
4152
4340
  }
4153
- // console.debug({previous, node});
4154
4341
  // @ts-ignore
4155
4342
  if (previous?.typ == 'AtRule' &&
4156
4343
  previous.nam == node.nam &&
@@ -4170,7 +4357,7 @@
4170
4357
  minifyRule(node);
4171
4358
  }
4172
4359
  else {
4173
- minify(node, options, recursive, errors);
4360
+ minify(node, options, recursive, errors, nestingContent);
4174
4361
  }
4175
4362
  previous = node;
4176
4363
  nodeIndex = i;
@@ -4224,7 +4411,7 @@
4224
4411
  nodeIndex = --i;
4225
4412
  // @ts-ignore
4226
4413
  previous = ast.chi[nodeIndex];
4227
- minify(wrapper, options, recursive, errors);
4414
+ minify(wrapper, options, recursive, errors, nestingContent);
4228
4415
  continue;
4229
4416
  }
4230
4417
  // @ts-ignore
@@ -4257,7 +4444,7 @@
4257
4444
  let wrap = true;
4258
4445
  // @ts-ignore
4259
4446
  const selector = node.optimized.selector.reduce((acc, curr) => {
4260
- if (curr[0] == '&') {
4447
+ if (curr[0] == '&' && curr.length > 1) {
4261
4448
  if (curr[1] == ' ') {
4262
4449
  curr.splice(0, 2);
4263
4450
  }
@@ -4281,7 +4468,7 @@
4281
4468
  if (!wrap) {
4282
4469
  wrap = selector.some(s => s[0] != '&');
4283
4470
  }
4284
- const rule = selector.map(s => {
4471
+ let rule = selector.map(s => {
4285
4472
  if (s[0] == '&') {
4286
4473
  // @ts-ignore
4287
4474
  s[0] = node.optimized.optimized[0];
@@ -4289,7 +4476,14 @@
4289
4476
  return s.join('');
4290
4477
  }).join(',');
4291
4478
  // @ts-ignore
4292
- node.sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
4479
+ let sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
4480
+ if (rule.includes('&')) {
4481
+ // @ts-ignore
4482
+ rule = replaceCompound(rule, node.optimized.optimized[0]);
4483
+ }
4484
+ if (sel.length < node.sel.length) {
4485
+ node.sel = sel;
4486
+ }
4293
4487
  }
4294
4488
  }
4295
4489
  // @ts-ignore
@@ -4325,7 +4519,7 @@
4325
4519
  minifyRule(node);
4326
4520
  }
4327
4521
  else {
4328
- minify(node, options, recursive, errors);
4522
+ minify(node, options, recursive, errors, nestingContent);
4329
4523
  }
4330
4524
  i--;
4331
4525
  previous = node;
@@ -4370,7 +4564,7 @@
4370
4564
  minifyRule(previous);
4371
4565
  }
4372
4566
  else {
4373
- minify(previous, options, recursive, errors);
4567
+ minify(previous, options, recursive, errors, nestingContent);
4374
4568
  }
4375
4569
  }
4376
4570
  }
@@ -4382,11 +4576,19 @@
4382
4576
  minifyRule(previous);
4383
4577
  }
4384
4578
  else {
4385
- minify(previous, options, recursive, errors);
4579
+ minify(previous, options, recursive, errors, nestingContent);
4386
4580
  }
4387
4581
  }
4388
4582
  }
4389
4583
  }
4584
+ if (!nestingContent &&
4585
+ // @ts-ignore
4586
+ previous != null &&
4587
+ // previous.optimized != null &&
4588
+ previous.typ == 'Rule' &&
4589
+ previous.sel.includes('&')) {
4590
+ fixSelector(previous);
4591
+ }
4390
4592
  previous = node;
4391
4593
  nodeIndex = i;
4392
4594
  }
@@ -4399,10 +4601,18 @@
4399
4601
  else {
4400
4602
  // @ts-ignore
4401
4603
  if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
4402
- minify(node, options, recursive, errors);
4604
+ minify(node, options, recursive, errors, nestingContent);
4403
4605
  }
4404
4606
  }
4405
4607
  }
4608
+ if (!nestingContent &&
4609
+ // @ts-ignore
4610
+ node != null &&
4611
+ // previous.optimized != null &&
4612
+ node.typ == 'Rule' &&
4613
+ node.sel.includes('&')) {
4614
+ fixSelector(node);
4615
+ }
4406
4616
  }
4407
4617
  return ast;
4408
4618
  }
@@ -4641,181 +4851,6 @@
4641
4851
  Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: raw });
4642
4852
  }
4643
4853
  }
4644
- // }
4645
- }
4646
-
4647
- function* walk(node) {
4648
- // @ts-ignore
4649
- yield* doWalk(node, null, null);
4650
- }
4651
- function* doWalk(node, parent, root) {
4652
- yield { node, parent, root };
4653
- if ('chi' in node) {
4654
- for (const child of node.chi) {
4655
- yield* doWalk(child, node, (root ?? node));
4656
- }
4657
- }
4658
- }
4659
- function* walkValues(values, parent) {
4660
- for (const value of values) {
4661
- // @ts-ignore
4662
- yield { value, parent };
4663
- if ('chi' in value) {
4664
- yield* walkValues(value.chi, value);
4665
- }
4666
- }
4667
- }
4668
-
4669
- function expand(ast) {
4670
- //
4671
- if (!['Rule', 'StyleSheet', 'AtRule'].includes(ast.typ)) {
4672
- return ast;
4673
- }
4674
- if ('Rule' == ast.typ) {
4675
- return {
4676
- typ: 'StyleSheet',
4677
- chi: expandRule(ast)
4678
- };
4679
- }
4680
- if (!('chi' in ast)) {
4681
- return { ...ast };
4682
- }
4683
- const result = { ...ast, chi: [] };
4684
- // @ts-ignore
4685
- for (let i = 0; i < ast.chi.length; i++) {
4686
- // @ts-ignore
4687
- const node = ast.chi[i];
4688
- if (node.typ == 'Rule') {
4689
- // @ts-ignore
4690
- result.chi.push(...expandRule(node));
4691
- // i += expanded.length - 1;
4692
- }
4693
- else if (node.typ == 'AtRule' && 'chi' in node) {
4694
- let hasRule = false;
4695
- let j = node.chi.length;
4696
- while (j--) {
4697
- if (node.chi[j].typ == 'Rule' || node.chi[j].typ == 'AtRule') {
4698
- hasRule = true;
4699
- break;
4700
- }
4701
- }
4702
- // @ts-ignore
4703
- result.chi.push({ ...(hasRule ? expand(node) : node) });
4704
- }
4705
- else {
4706
- // @ts-ignore
4707
- result.chi.push(node);
4708
- }
4709
- }
4710
- return result;
4711
- }
4712
- function expandRule(node) {
4713
- const ast = { ...node, chi: node.chi.slice() };
4714
- const result = [];
4715
- if (ast.typ == 'Rule') {
4716
- let i = 0;
4717
- // @ts-ignore
4718
- delete ast.raw;
4719
- // @ts-ignore
4720
- delete ast.optimized;
4721
- for (; i < ast.chi.length; i++) {
4722
- if (ast.chi[i].typ == 'Rule') {
4723
- const rule = ast.chi[i];
4724
- if (!rule.sel.includes('&')) {
4725
- const selRule = splitRule(rule.sel);
4726
- selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
4727
- rule.sel = selRule.reduce((acc, curr) => {
4728
- acc.push(curr.join(''));
4729
- return acc;
4730
- }, []).join(',');
4731
- }
4732
- else {
4733
- rule.sel = replaceCompount(rule.sel, ast.sel);
4734
- }
4735
- delete rule.raw;
4736
- delete rule.optimized;
4737
- ast.chi.splice(i--, 1);
4738
- result.push(...expandRule(rule));
4739
- }
4740
- else if (ast.chi[i].typ == 'AtRule') {
4741
- let astAtRule = ast.chi[i];
4742
- const values = [];
4743
- if (astAtRule.nam == 'scope') {
4744
- if (astAtRule.val.includes('&')) {
4745
- astAtRule.val = replaceCompount(astAtRule.val, ast.sel);
4746
- }
4747
- // @ts-ignore
4748
- astAtRule = expand(astAtRule);
4749
- }
4750
- else {
4751
- // @ts-ignore
4752
- const clone = { ...ast, chi: astAtRule.chi.slice() };
4753
- // @ts-ignore
4754
- astAtRule.chi.length = 0;
4755
- for (const r of expandRule(clone)) {
4756
- if (r.typ == 'AtRule' && 'chi' in r) {
4757
- if (astAtRule.val !== '' && r.val !== '') {
4758
- if (astAtRule.nam == 'media' && r.nam == 'media') {
4759
- r.val = astAtRule.val + ' and ' + r.val;
4760
- }
4761
- else if (astAtRule.nam == 'layer' && r.nam == 'layer') {
4762
- r.val = astAtRule.val + '.' + r.val;
4763
- }
4764
- }
4765
- // @ts-ignore
4766
- values.push(r);
4767
- }
4768
- else if (r.typ == 'Rule') {
4769
- // @ts-ignore
4770
- astAtRule.chi.push(...expandRule(r));
4771
- }
4772
- else {
4773
- // @ts-ignore
4774
- astAtRule.chi.push(r);
4775
- }
4776
- }
4777
- }
4778
- // @ts-ignore
4779
- result.push(...(astAtRule.chi.length > 0 ? [astAtRule].concat(values) : values));
4780
- ast.chi.splice(i--, 1);
4781
- }
4782
- }
4783
- }
4784
- // @ts-ignore
4785
- return ast.chi.length > 0 ? [ast].concat(result) : result;
4786
- }
4787
- function replaceCompount(input, replace) {
4788
- const tokens = parseString(input);
4789
- for (const t of walkValues(tokens)) {
4790
- if (t.value.typ == 'Literal') {
4791
- if (t.value.val == '&') {
4792
- t.value.val = replace;
4793
- }
4794
- else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
4795
- t.value.val = replaceCompoundLiteral(t.value.val, replace);
4796
- }
4797
- }
4798
- }
4799
- return tokens.reduce((acc, curr) => acc + renderToken(curr), '');
4800
- }
4801
- function replaceCompoundLiteral(selector, replace) {
4802
- const tokens = [''];
4803
- let i = 0;
4804
- for (; i < selector.length; i++) {
4805
- if (selector.charAt(i) == '&') {
4806
- tokens.push('&');
4807
- tokens.push('');
4808
- }
4809
- else {
4810
- tokens[tokens.length - 1] += selector.charAt(i);
4811
- }
4812
- }
4813
- return tokens.sort((a, b) => {
4814
- if (a == '&') {
4815
- return 1;
4816
- }
4817
- return b == '&' ? -1 : 0;
4818
- }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
4819
4854
  }
4820
4855
 
4821
4856
  async function transform$1(css, options = {}) {
@@ -5007,6 +5042,7 @@
5007
5042
  exports.reduceSelector = reduceSelector;
5008
5043
  exports.render = render;
5009
5044
  exports.renderToken = renderToken;
5045
+ exports.replaceCompound = replaceCompound;
5010
5046
  exports.resolve = resolve;
5011
5047
  exports.splitRule = splitRule;
5012
5048
  exports.tokenize = tokenize;