@tbela99/css-parser 0.0.1-rc3 → 0.0.1-rc4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -163,37 +163,30 @@ function isNumber(name) {
163
163
  return true;
164
164
  }
165
165
  function isDimension(name) {
166
- let index = 0;
167
- while (index++ < name.length) {
168
- if (isDigit(name.charCodeAt(name.length - index))) {
169
- index--;
170
- break;
171
- }
172
- if (index == 3) {
173
- break;
166
+ let index = name.length;
167
+ while (index--) {
168
+ if (isLetter(name.charCodeAt(index))) {
169
+ continue;
174
170
  }
171
+ index++;
172
+ break;
175
173
  }
176
- if (index == 0 || index > 3) {
177
- return false;
178
- }
179
- const number = name.slice(0, -index);
180
- return number.length > 0 && isIdentStart(name.charCodeAt(name.length - index)) && isNumber(number);
174
+ const number = name.slice(0, index);
175
+ return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
181
176
  }
182
177
  function isPercentage(name) {
183
178
  return name.endsWith('%') && isNumber(name.slice(0, -1));
184
179
  }
185
180
  function parseDimension(name) {
186
- let index = 0;
187
- while (index++ < name.length) {
188
- if (isDigit(name.charCodeAt(name.length - index))) {
189
- index--;
190
- break;
191
- }
192
- if (index == 3) {
193
- break;
181
+ let index = name.length;
182
+ while (index--) {
183
+ if (isLetter(name.charCodeAt(index))) {
184
+ continue;
194
185
  }
186
+ index++;
187
+ break;
195
188
  }
196
- const dimension = { typ: 'Dimension', val: name.slice(0, -index), unit: name.slice(-index) };
189
+ const dimension = { typ: 'Dimension', val: name.slice(0, index), unit: name.slice(index) };
197
190
  if (isAngle(dimension)) {
198
191
  // @ts-ignore
199
192
  dimension.typ = 'Angle';
@@ -1502,7 +1495,7 @@ function cmyk2hex(token) {
1502
1495
  return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
1503
1496
  }
1504
1497
  function getAngle(token) {
1505
- if (token.typ == 'Dimension') {
1498
+ if (token.typ == 'Angle') {
1506
1499
  switch (token.unit) {
1507
1500
  case 'deg':
1508
1501
  // @ts-ignore
@@ -1575,6 +1568,23 @@ function hsl2rgb(h, s, l, a = null) {
1575
1568
  return values;
1576
1569
  }
1577
1570
 
1571
+ function reduceNumber(val) {
1572
+ val = (+val).toString();
1573
+ if (val === '0') {
1574
+ return '0';
1575
+ }
1576
+ const chr = val.charAt(0);
1577
+ if (chr == '-') {
1578
+ const slice = val.slice(0, 2);
1579
+ if (slice == '-0') {
1580
+ return val.length == 2 ? '0' : '-' + val.slice(2);
1581
+ }
1582
+ }
1583
+ if (chr == '0') {
1584
+ return val.slice(1);
1585
+ }
1586
+ return val;
1587
+ }
1578
1588
  function render(data, opt = {}) {
1579
1589
  const startTime = performance.now();
1580
1590
  const options = Object.assign(opt.minify ?? true ? {
@@ -1587,17 +1597,19 @@ function render(data, opt = {}) {
1587
1597
  compress: false,
1588
1598
  removeComments: false,
1589
1599
  }, { colorConvert: true, preserveLicense: false }, opt);
1590
- function reducer(acc, curr, index, original) {
1591
- if (curr.typ == 'Comment' && options.removeComments) {
1592
- if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1593
- return acc;
1600
+ return {
1601
+ code: doRender(data, options, function reducer(acc, curr) {
1602
+ if (curr.typ == 'Comment' && options.removeComments) {
1603
+ if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1604
+ return acc;
1605
+ }
1606
+ return acc + curr.val;
1594
1607
  }
1595
- }
1596
- return acc + renderToken(curr, options);
1597
- }
1598
- return { code: doRender(data, options, reducer, 0), stats: {
1608
+ return acc + renderToken(curr, options, reducer);
1609
+ }, 0), stats: {
1599
1610
  total: `${(performance.now() - startTime).toFixed(2)}ms`
1600
- } };
1611
+ }
1612
+ };
1601
1613
  }
1602
1614
  // @ts-ignore
1603
1615
  function doRender(data, options, reducer, level = 0, indents = []) {
@@ -1611,9 +1623,9 @@ function doRender(data, options, reducer, level = 0, indents = []) {
1611
1623
  const indentSub = indents[level + 1];
1612
1624
  switch (data.typ) {
1613
1625
  case 'Declaration':
1614
- return `${data.nam}:${options.indent}${data.val.reduce((acc, curr) => acc + renderToken(curr), '')}`;
1626
+ return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
1615
1627
  case 'Comment':
1616
- return options.removeComments ? '' : data.val;
1628
+ return !options.removeComments || (options.preserveLicense && data.val.startsWith('/*!')) ? data.val : '';
1617
1629
  case 'StyleSheet':
1618
1630
  return data.chi.reduce((css, node) => {
1619
1631
  const str = doRender(node, options, reducer, level, indents);
@@ -1634,7 +1646,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
1634
1646
  let children = data.chi.reduce((css, node) => {
1635
1647
  let str;
1636
1648
  if (node.typ == 'Comment') {
1637
- str = options.removeComments ? '' : node.val;
1649
+ str = options.removeComments && (!options.preserveLicense || !node.val.startsWith('/*!')) ? '' : node.val;
1638
1650
  }
1639
1651
  else if (node.typ == 'Declaration') {
1640
1652
  if (node.val.length == 0) {
@@ -1667,7 +1679,18 @@ function doRender(data, options, reducer, level = 0, indents = []) {
1667
1679
  }
1668
1680
  return '';
1669
1681
  }
1670
- function renderToken(token, options = {}) {
1682
+ function renderToken(token, options = {}, reducer) {
1683
+ if (reducer == null) {
1684
+ reducer = function (acc, curr) {
1685
+ if (curr.typ == 'Comment' && options.removeComments) {
1686
+ if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1687
+ return acc;
1688
+ }
1689
+ return acc + curr.val;
1690
+ }
1691
+ return acc + renderToken(curr, options, reducer);
1692
+ };
1693
+ }
1671
1694
  switch (token.typ) {
1672
1695
  case 'Color':
1673
1696
  if (options.minify || options.colorConvert) {
@@ -1718,22 +1741,19 @@ function renderToken(token, options = {}) {
1718
1741
  case 'UrlFunc':
1719
1742
  case 'Pseudo-class-func':
1720
1743
  // @ts-ignore
1721
- return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce((acc, curr) => {
1722
- if (options.removeComments && curr.typ == 'Comment') {
1723
- if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1724
- return acc;
1725
- }
1726
- }
1727
- return acc + renderToken(curr, options);
1728
- }, '') + ')';
1744
+ return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce(reducer, '') + ')';
1729
1745
  case 'Includes':
1730
1746
  return '~=';
1731
1747
  case 'Dash-match':
1732
1748
  return '|=';
1733
1749
  case 'Lt':
1734
1750
  return '<';
1751
+ case 'Lte':
1752
+ return '<=';
1735
1753
  case 'Gt':
1736
1754
  return '>';
1755
+ case 'Gte':
1756
+ return '>=';
1737
1757
  case 'End-parens':
1738
1758
  return ')';
1739
1759
  case 'Attr-start':
@@ -1751,37 +1771,73 @@ function renderToken(token, options = {}) {
1751
1771
  case 'Important':
1752
1772
  return '!important';
1753
1773
  case 'Attr':
1754
- return '[' + token.chi.reduce((acc, curr) => acc + renderToken(curr, options), '') + ']';
1774
+ return '[' + token.chi.reduce(reducer, '') + ']';
1755
1775
  case 'Time':
1756
- case 'Frequency':
1757
1776
  case 'Angle':
1758
1777
  case 'Length':
1759
1778
  case 'Dimension':
1760
- const val = (+token.val).toString();
1779
+ case 'Frequency':
1780
+ case 'Resolution':
1781
+ let val = reduceNumber(token.val);
1782
+ let unit = token.unit;
1783
+ if (token.typ == 'Angle') {
1784
+ const angle = getAngle(token);
1785
+ let v;
1786
+ let value = val + unit;
1787
+ for (const u of ['turn', 'deg', 'rad', 'grad']) {
1788
+ if (token.unit == u) {
1789
+ continue;
1790
+ }
1791
+ switch (u) {
1792
+ case 'turn':
1793
+ v = reduceNumber(angle);
1794
+ if (v.length + 4 < value.length) {
1795
+ val = v;
1796
+ unit = u;
1797
+ value = v + u;
1798
+ }
1799
+ break;
1800
+ case 'deg':
1801
+ v = reduceNumber(angle * 360);
1802
+ if (v.length + 3 < value.length) {
1803
+ val = v;
1804
+ unit = u;
1805
+ value = v + u;
1806
+ }
1807
+ break;
1808
+ case 'rad':
1809
+ v = reduceNumber(angle * (2 * Math.PI));
1810
+ if (v.length + 3 < value.length) {
1811
+ val = v;
1812
+ unit = u;
1813
+ value = v + u;
1814
+ }
1815
+ break;
1816
+ case 'grad':
1817
+ v = reduceNumber(angle * 400);
1818
+ if (v.length + 4 < value.length) {
1819
+ val = v;
1820
+ unit = u;
1821
+ value = v + u;
1822
+ }
1823
+ break;
1824
+ }
1825
+ }
1826
+ }
1761
1827
  if (val === '0') {
1762
- if (token.typ == 'Time') {
1828
+ if (unit == 'Time') {
1763
1829
  return '0s';
1764
1830
  }
1765
- if (token.typ == 'Frequency') {
1831
+ if (unit == 'Frequency') {
1766
1832
  return '0Hz';
1767
1833
  }
1768
1834
  // @ts-ignore
1769
- if (token.typ == 'Resolution') {
1835
+ if (unit == 'Resolution') {
1770
1836
  return '0x';
1771
1837
  }
1772
1838
  return '0';
1773
1839
  }
1774
- const chr = val.charAt(0);
1775
- if (chr == '-') {
1776
- const slice = val.slice(0, 2);
1777
- if (slice == '-0') {
1778
- return (val.length == 2 ? '0' : '-' + val.slice(2)) + token.unit;
1779
- }
1780
- }
1781
- else if (chr == '0') {
1782
- return val.slice(1) + token.unit;
1783
- }
1784
- return val + token.unit;
1840
+ return val + unit;
1785
1841
  case 'Perc':
1786
1842
  return token.val + '%';
1787
1843
  case 'Number':
@@ -1798,7 +1854,7 @@ function renderToken(token, options = {}) {
1798
1854
  }
1799
1855
  return num;
1800
1856
  case 'Comment':
1801
- if (options.removeComments) {
1857
+ if (options.removeComments && (!options.preserveLicense || !token.val.startsWith('/*!'))) {
1802
1858
  return '';
1803
1859
  }
1804
1860
  case 'Url-token':
@@ -2069,6 +2125,7 @@ class PropertyMap {
2069
2125
  i--;
2070
2126
  continue;
2071
2127
  }
2128
+ // @ts-ignore
2072
2129
  if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
2073
2130
  if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
2074
2131
  return acc;
@@ -2234,17 +2291,18 @@ class PropertyMap {
2234
2291
  if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2235
2292
  continue;
2236
2293
  }
2237
- match = matchType(val, curr[1]);
2294
+ // @ts-ignore
2295
+ match = val.typ == 'Comment' || matchType(val, curr[1]);
2238
2296
  if (isShorthand) {
2239
2297
  isShorthand = match;
2240
2298
  }
2299
+ // @ts-ignore
2241
2300
  if (('propertyName' in val && val.propertyName == property) || match) {
2242
2301
  if (!(curr[0] in tokens)) {
2243
2302
  tokens[curr[0]] = [[]];
2244
2303
  }
2245
2304
  // is default value
2246
2305
  tokens[curr[0]][current].push(val);
2247
- // continue;
2248
2306
  }
2249
2307
  else {
2250
2308
  acc.push(curr[0]);
@@ -2261,7 +2319,9 @@ class PropertyMap {
2261
2319
  if (!isShorthand || Object.entries(this.config.properties).some(entry => {
2262
2320
  // missing required property
2263
2321
  return entry[1].required && !(entry[0] in tokens);
2264
- }) || !Object.values(tokens).every(v => v.length == count)) {
2322
+ }) ||
2323
+ // @ts-ignore
2324
+ !Object.values(tokens).every(v => v.filter(t => t.typ != 'Comment').length == count)) {
2265
2325
  // @ts-ignore
2266
2326
  iterable = this.declarations.values();
2267
2327
  }
@@ -2814,6 +2874,17 @@ function minify(ast, options = {}, recursive = false) {
2814
2874
  continue;
2815
2875
  // }
2816
2876
  }
2877
+ // @ts-ignore
2878
+ if (hasDeclaration(node)) {
2879
+ // @ts-ignore
2880
+ minifyRule(node);
2881
+ }
2882
+ else {
2883
+ minify(node, options, recursive);
2884
+ }
2885
+ previous = node;
2886
+ nodeIndex = i;
2887
+ continue;
2817
2888
  }
2818
2889
  // @ts-ignore
2819
2890
  if (node.typ == 'Rule') {
@@ -3328,11 +3399,6 @@ function* tokenize(iterator) {
3328
3399
  }
3329
3400
  buffer += quoteStr;
3330
3401
  while (value = peek()) {
3331
- // if (ind >= iterator.length) {
3332
- //
3333
- // yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
3334
- // break;
3335
- // }
3336
3402
  if (value == '\\') {
3337
3403
  const sequence = peek(6);
3338
3404
  let escapeSequence = '';
@@ -3352,9 +3418,23 @@ function* tokenize(iterator) {
3352
3418
  }
3353
3419
  break;
3354
3420
  }
3421
+ // @ts-ignore
3422
+ if (isNewLine(codepoint)) {
3423
+ if (i == 1) {
3424
+ buffer += value + escapeSequence.slice(0, i);
3425
+ next(i + 1);
3426
+ continue;
3427
+ }
3428
+ // else {
3429
+ yield pushToken(buffer + value + escapeSequence.slice(0, i), 'Bad-string');
3430
+ buffer = '';
3431
+ // }
3432
+ next(i + 1);
3433
+ break;
3434
+ }
3355
3435
  // not hex or new line
3356
3436
  // @ts-ignore
3357
- if (i == 1 && !isNewLine(codepoint)) {
3437
+ else if (i == 1) {
3358
3438
  buffer += value + sequence[i];
3359
3439
  next(2);
3360
3440
  continue;
@@ -3374,13 +3454,6 @@ function* tokenize(iterator) {
3374
3454
  next(escapeSequence.length + 1);
3375
3455
  continue;
3376
3456
  }
3377
- // buffer += value;
3378
- // if (ind >= iterator.length) {
3379
- //
3380
- // // drop '\\' at the end
3381
- // yield pushToken(buffer);
3382
- // break;
3383
- // }
3384
3457
  buffer += next(2);
3385
3458
  continue;
3386
3459
  }
@@ -3390,20 +3463,28 @@ function* tokenize(iterator) {
3390
3463
  next();
3391
3464
  // i += value.length;
3392
3465
  buffer = '';
3393
- break;
3466
+ return;
3394
3467
  }
3395
3468
  if (isNewLine(value.charCodeAt(0))) {
3396
3469
  hasNewLine = true;
3397
3470
  }
3398
3471
  if (hasNewLine && value == ';') {
3399
- yield pushToken(buffer, 'Bad-string');
3472
+ yield pushToken(buffer + value, 'Bad-string');
3400
3473
  buffer = '';
3474
+ next();
3401
3475
  break;
3402
3476
  }
3403
3477
  buffer += value;
3404
- // i += value.length;
3405
3478
  next();
3406
3479
  }
3480
+ if (hasNewLine) {
3481
+ yield pushToken(buffer, 'Bad-string');
3482
+ }
3483
+ else {
3484
+ // EOF - 'Unclosed-string' fixed
3485
+ yield pushToken(buffer + quote, 'String');
3486
+ }
3487
+ buffer = '';
3407
3488
  }
3408
3489
  function peek(count = 1) {
3409
3490
  if (count == 1) {
@@ -3517,6 +3598,11 @@ function* tokenize(iterator) {
3517
3598
  yield pushToken(buffer);
3518
3599
  buffer = '';
3519
3600
  }
3601
+ if (peek() == '=') {
3602
+ yield pushToken('', 'Lte');
3603
+ next();
3604
+ break;
3605
+ }
3520
3606
  buffer += value;
3521
3607
  value = next();
3522
3608
  if (ind >= iterator.length) {
@@ -3585,7 +3671,13 @@ function* tokenize(iterator) {
3585
3671
  yield pushToken(buffer);
3586
3672
  buffer = '';
3587
3673
  }
3588
- yield pushToken('', 'Gt');
3674
+ if (peek() == '=') {
3675
+ yield pushToken('', 'Gte');
3676
+ next();
3677
+ }
3678
+ else {
3679
+ yield pushToken('', 'Gt');
3680
+ }
3589
3681
  consumeWhiteSpace();
3590
3682
  break;
3591
3683
  case '.':
@@ -3627,7 +3719,7 @@ function* tokenize(iterator) {
3627
3719
  break;
3628
3720
  case '(':
3629
3721
  if (buffer.length == 0) {
3630
- yield pushToken('', 'Start-parens');
3722
+ yield pushToken(value);
3631
3723
  break;
3632
3724
  }
3633
3725
  buffer += value;
@@ -3741,9 +3833,11 @@ function* tokenize(iterator) {
3741
3833
  if (buffer.length > 0) {
3742
3834
  yield pushToken(buffer);
3743
3835
  }
3836
+ // yield pushToken('', 'EOF');
3744
3837
  }
3745
3838
 
3746
3839
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
3840
+ const trimWhiteSpace = ['Gt', 'Gte', 'Lt', 'Lte'];
3747
3841
  const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
3748
3842
  /**
3749
3843
  *
@@ -3790,6 +3884,10 @@ async function parse$1(iterator, opt = {}) {
3790
3884
  let tokens = results.map(mapToken);
3791
3885
  let i;
3792
3886
  let loc;
3887
+ // if ((<Token>tokens.at(-1))?.typ == 'EOF') {
3888
+ //
3889
+ // tokens.pop();
3890
+ // }
3793
3891
  for (i = 0; i < tokens.length; i++) {
3794
3892
  if (tokens[i].typ == 'Comment') {
3795
3893
  // @ts-ignore
@@ -3908,7 +4006,7 @@ async function parse$1(iterator, opt = {}) {
3908
4006
  // https://www.w3.org/TR/css-nesting-1/#conditionals
3909
4007
  // allowed nesting at-rules
3910
4008
  // there must be a top level rule in the stack
3911
- const raw = tokens.reduce((acc, curr) => {
4009
+ const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
3912
4010
  acc.push(renderToken(curr, { removeComments: true }));
3913
4011
  return acc;
3914
4012
  }, []);
@@ -3939,8 +4037,8 @@ async function parse$1(iterator, opt = {}) {
3939
4037
  const uniq = new Map;
3940
4038
  parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
3941
4039
  if (curr.typ == 'Whitespace') {
3942
- if (array[index - 1]?.typ == 'Gt' ||
3943
- array[index + 1]?.typ == 'Gt' ||
4040
+ if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
4041
+ trimWhiteSpace.includes(array[index + 1]?.typ) ||
3944
4042
  combinators.includes(array[index - 1]?.val) ||
3945
4043
  combinators.includes(array[index + 1]?.val)) {
3946
4044
  return acc;
@@ -4144,7 +4242,7 @@ function getTokenType(val, hint) {
4144
4242
  return ([
4145
4243
  'Whitespace', 'Semi-colon', 'Colon', 'Block-start',
4146
4244
  'Block-start', 'Attr-start', 'Attr-end', 'Start-parens', 'End-parens',
4147
- 'Comma', 'Gt', 'Lt'
4245
+ 'Comma', 'Gt', 'Lt', 'Gte', 'Lte', 'EOF'
4148
4246
  ].includes(hint) ? { typ: hint } : { typ: hint, val });
4149
4247
  }
4150
4248
  if (val == ' ') {
@@ -4272,11 +4370,12 @@ function parseTokens(tokens, options = {}) {
4272
4370
  const t = tokens[i];
4273
4371
  if (t.typ == 'Whitespace' && ((i == 0 ||
4274
4372
  i + 1 == tokens.length ||
4275
- ['Comma'].includes(tokens[i + 1].typ) ||
4373
+ ['Comma', 'Gte', 'Lte'].includes(tokens[i + 1].typ)) ||
4276
4374
  (i > 0 &&
4277
- tokens[i + 1]?.typ != 'Literal' &&
4278
- funcLike.includes(tokens[i - 1].typ) &&
4279
- !['var', 'calc'].includes(tokens[i - 1].val))))) {
4375
+ // tokens[i + 1]?.typ != 'Literal' ||
4376
+ // funcLike.includes(tokens[i - 1].typ) &&
4377
+ // !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
4378
+ trimWhiteSpace.includes(tokens[i - 1].typ)))) {
4280
4379
  tokens.splice(i--, 1);
4281
4380
  continue;
4282
4381
  }
@@ -4393,7 +4492,7 @@ function parseTokens(tokens, options = {}) {
4393
4492
  let m = t.chi.length;
4394
4493
  while (m-- > 0) {
4395
4494
  // @ts-ignore
4396
- if (t.chi[m].typ == 'Literal') {
4495
+ if (['Literal'].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
4397
4496
  // @ts-ignore
4398
4497
  if (t.chi[m + 1]?.typ == 'Whitespace') {
4399
4498
  // @ts-ignore
package/dist/index.d.ts CHANGED
@@ -91,12 +91,14 @@ interface BlockEndToken {
91
91
  }
92
92
  interface AttrStartToken {
93
93
  typ: 'Attr-start';
94
+ chi?: Token[];
94
95
  }
95
96
  interface AttrEndToken {
96
97
  typ: 'Attr-end';
97
98
  }
98
99
  interface ParensStartToken {
99
100
  typ: 'Start-parens';
101
+ chi?: Token[];
100
102
  }
101
103
  interface ParensEndToken {
102
104
  typ: 'End-parens';
@@ -131,9 +133,15 @@ interface DashMatchToken {
131
133
  interface LessThanToken {
132
134
  typ: 'Lt';
133
135
  }
136
+ interface LessThanOrEqualToken {
137
+ typ: 'Lte';
138
+ }
134
139
  interface GreaterThanToken {
135
140
  typ: 'Gt';
136
141
  }
142
+ interface GreaterThanOrEqualToken {
143
+ typ: 'Gte';
144
+ }
137
145
  interface PseudoClassToken {
138
146
  typ: 'Pseudo-class';
139
147
  val: string;
@@ -171,7 +179,7 @@ interface AttrToken {
171
179
  typ: 'Attr';
172
180
  chi: Token[];
173
181
  }
174
- declare type Token = LiteralToken | IdentToken | CommaToken | ColonToken | SemiColonToken | NumberToken | AtRuleToken | PercentageToken | FunctionURLToken | FunctionToken | DimensionToken | LengthToken | AngleToken | StringToken | TimeToken | FrequencyToken | ResolutionToken | UnclosedStringToken | HashToken | BadStringToken | BlockStartToken | BlockEndToken | AttrStartToken | AttrEndToken | ParensStartToken | ParensEndToken | CDOCommentToken | BadCDOCommentToken | CommentToken | BadCommentToken | WhitespaceToken | IncludesToken | DashMatchToken | LessThanToken | GreaterThanToken | PseudoClassToken | PseudoClassFunctionToken | DelimToken | BadUrlToken | UrlToken | ImportantToken | ColorToken | AttrToken | EOFToken;
182
+ declare type Token = LiteralToken | IdentToken | CommaToken | ColonToken | SemiColonToken | NumberToken | AtRuleToken | PercentageToken | FunctionURLToken | FunctionToken | DimensionToken | LengthToken | AngleToken | StringToken | TimeToken | FrequencyToken | ResolutionToken | UnclosedStringToken | HashToken | BadStringToken | BlockStartToken | BlockEndToken | AttrStartToken | AttrEndToken | ParensStartToken | ParensEndToken | CDOCommentToken | BadCDOCommentToken | CommentToken | BadCommentToken | WhitespaceToken | IncludesToken | DashMatchToken | LessThanToken | LessThanOrEqualToken | GreaterThanToken | GreaterThanOrEqualToken | PseudoClassToken | PseudoClassFunctionToken | DelimToken | BadUrlToken | UrlToken | ImportantToken | ColorToken | AttrToken | EOFToken;
175
183
 
176
184
  interface PropertyMapType {
177
185
  default: string[];
@@ -656,7 +664,7 @@ declare const getConfig: () => PropertiesConfig;
656
664
  declare function matchType(val: Token, properties: PropertyMapType): boolean;
657
665
 
658
666
  declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
659
- declare function renderToken(token: Token, options?: RenderOptions): string;
667
+ declare function renderToken(token: Token, options?: RenderOptions, reducer?: (acc: string, curr: Token) => string): string;
660
668
 
661
669
  declare const combinators: string[];
662
670
  declare function minify(ast: AstNode, options?: ParserOptions, recursive?: boolean): AstNode;
@@ -344,6 +344,17 @@ function minify(ast, options = {}, recursive = false) {
344
344
  continue;
345
345
  // }
346
346
  }
347
+ // @ts-ignore
348
+ if (hasDeclaration(node)) {
349
+ // @ts-ignore
350
+ minifyRule(node);
351
+ }
352
+ else {
353
+ minify(node, options, recursive);
354
+ }
355
+ previous = node;
356
+ nodeIndex = i;
357
+ continue;
347
358
  }
348
359
  // @ts-ignore
349
360
  if (node.typ == 'Rule') {
@@ -55,6 +55,7 @@ class PropertyMap {
55
55
  i--;
56
56
  continue;
57
57
  }
58
+ // @ts-ignore
58
59
  if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
59
60
  if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
60
61
  return acc;
@@ -220,17 +221,18 @@ class PropertyMap {
220
221
  if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
221
222
  continue;
222
223
  }
223
- match = matchType(val, curr[1]);
224
+ // @ts-ignore
225
+ match = val.typ == 'Comment' || matchType(val, curr[1]);
224
226
  if (isShorthand) {
225
227
  isShorthand = match;
226
228
  }
229
+ // @ts-ignore
227
230
  if (('propertyName' in val && val.propertyName == property) || match) {
228
231
  if (!(curr[0] in tokens)) {
229
232
  tokens[curr[0]] = [[]];
230
233
  }
231
234
  // is default value
232
235
  tokens[curr[0]][current].push(val);
233
- // continue;
234
236
  }
235
237
  else {
236
238
  acc.push(curr[0]);
@@ -247,7 +249,9 @@ class PropertyMap {
247
249
  if (!isShorthand || Object.entries(this.config.properties).some(entry => {
248
250
  // missing required property
249
251
  return entry[1].required && !(entry[0] in tokens);
250
- }) || !Object.values(tokens).every(v => v.length == count)) {
252
+ }) ||
253
+ // @ts-ignore
254
+ !Object.values(tokens).every(v => v.filter(t => t.typ != 'Comment').length == count)) {
251
255
  // @ts-ignore
252
256
  iterable = this.declarations.values();
253
257
  }