@tbela99/css-parser 0.0.1-rc2 → 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.
@@ -165,37 +165,30 @@
165
165
  return true;
166
166
  }
167
167
  function isDimension(name) {
168
- let index = 0;
169
- while (index++ < name.length) {
170
- if (isDigit(name.charCodeAt(name.length - index))) {
171
- index--;
172
- break;
173
- }
174
- if (index == 3) {
175
- break;
168
+ let index = name.length;
169
+ while (index--) {
170
+ if (isLetter(name.charCodeAt(index))) {
171
+ continue;
176
172
  }
173
+ index++;
174
+ break;
177
175
  }
178
- if (index == 0 || index > 3) {
179
- return false;
180
- }
181
- const number = name.slice(0, -index);
182
- return number.length > 0 && isIdentStart(name.charCodeAt(name.length - index)) && isNumber(number);
176
+ const number = name.slice(0, index);
177
+ return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
183
178
  }
184
179
  function isPercentage(name) {
185
180
  return name.endsWith('%') && isNumber(name.slice(0, -1));
186
181
  }
187
182
  function parseDimension(name) {
188
- let index = 0;
189
- while (index++ < name.length) {
190
- if (isDigit(name.charCodeAt(name.length - index))) {
191
- index--;
192
- break;
193
- }
194
- if (index == 3) {
195
- break;
183
+ let index = name.length;
184
+ while (index--) {
185
+ if (isLetter(name.charCodeAt(index))) {
186
+ continue;
196
187
  }
188
+ index++;
189
+ break;
197
190
  }
198
- const dimension = { typ: 'Dimension', val: name.slice(0, -index), unit: name.slice(-index) };
191
+ const dimension = { typ: 'Dimension', val: name.slice(0, index), unit: name.slice(index) };
199
192
  if (isAngle(dimension)) {
200
193
  // @ts-ignore
201
194
  dimension.typ = 'Angle';
@@ -1069,6 +1062,21 @@
1069
1062
 
1070
1063
  const getConfig = () => config$1;
1071
1064
 
1065
+ const funcList = ['clamp', 'calc'];
1066
+ function matchType(val, properties) {
1067
+ if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
1068
+ (properties.types.includes(val.typ))) {
1069
+ return true;
1070
+ }
1071
+ if (val.typ == 'Number' && val.val == '0') {
1072
+ return properties.types.some(type => type == 'Length' || type == 'Angle');
1073
+ }
1074
+ if (val.typ == 'Func' && funcList.includes(val.val)) {
1075
+ return val.chi.every((t => ['Literal', 'Comma', 'Whitespace', 'Start-parens', 'End-parens'].includes(t.typ) || matchType(t, properties)));
1076
+ }
1077
+ return false;
1078
+ }
1079
+
1072
1080
  // name to color
1073
1081
  const COLORS_NAMES = Object.seal({
1074
1082
  'aliceblue': '#f0f8ff',
@@ -1489,7 +1497,7 @@
1489
1497
  return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
1490
1498
  }
1491
1499
  function getAngle(token) {
1492
- if (token.typ == 'Dimension') {
1500
+ if (token.typ == 'Angle') {
1493
1501
  switch (token.unit) {
1494
1502
  case 'deg':
1495
1503
  // @ts-ignore
@@ -1562,6 +1570,23 @@
1562
1570
  return values;
1563
1571
  }
1564
1572
 
1573
+ function reduceNumber(val) {
1574
+ val = (+val).toString();
1575
+ if (val === '0') {
1576
+ return '0';
1577
+ }
1578
+ const chr = val.charAt(0);
1579
+ if (chr == '-') {
1580
+ const slice = val.slice(0, 2);
1581
+ if (slice == '-0') {
1582
+ return val.length == 2 ? '0' : '-' + val.slice(2);
1583
+ }
1584
+ }
1585
+ if (chr == '0') {
1586
+ return val.slice(1);
1587
+ }
1588
+ return val;
1589
+ }
1565
1590
  function render(data, opt = {}) {
1566
1591
  const startTime = performance.now();
1567
1592
  const options = Object.assign(opt.minify ?? true ? {
@@ -1574,17 +1599,19 @@
1574
1599
  compress: false,
1575
1600
  removeComments: false,
1576
1601
  }, { colorConvert: true, preserveLicense: false }, opt);
1577
- function reducer(acc, curr, index, original) {
1578
- if (curr.typ == 'Comment' && options.removeComments) {
1579
- if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1580
- return acc;
1602
+ return {
1603
+ code: doRender(data, options, function reducer(acc, curr) {
1604
+ if (curr.typ == 'Comment' && options.removeComments) {
1605
+ if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1606
+ return acc;
1607
+ }
1608
+ return acc + curr.val;
1581
1609
  }
1582
- }
1583
- return acc + renderToken(curr, options);
1584
- }
1585
- return { code: doRender(data, options, reducer, 0), stats: {
1610
+ return acc + renderToken(curr, options, reducer);
1611
+ }, 0), stats: {
1586
1612
  total: `${(performance.now() - startTime).toFixed(2)}ms`
1587
- } };
1613
+ }
1614
+ };
1588
1615
  }
1589
1616
  // @ts-ignore
1590
1617
  function doRender(data, options, reducer, level = 0, indents = []) {
@@ -1597,8 +1624,10 @@
1597
1624
  const indent = indents[level];
1598
1625
  const indentSub = indents[level + 1];
1599
1626
  switch (data.typ) {
1627
+ case 'Declaration':
1628
+ return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
1600
1629
  case 'Comment':
1601
- return options.removeComments ? '' : data.val;
1630
+ return !options.removeComments || (options.preserveLicense && data.val.startsWith('/*!')) ? data.val : '';
1602
1631
  case 'StyleSheet':
1603
1632
  return data.chi.reduce((css, node) => {
1604
1633
  const str = doRender(node, options, reducer, level, indents);
@@ -1619,9 +1648,13 @@
1619
1648
  let children = data.chi.reduce((css, node) => {
1620
1649
  let str;
1621
1650
  if (node.typ == 'Comment') {
1622
- str = options.removeComments ? '' : node.val;
1651
+ str = options.removeComments && (!options.preserveLicense || !node.val.startsWith('/*!')) ? '' : node.val;
1623
1652
  }
1624
1653
  else if (node.typ == 'Declaration') {
1654
+ if (node.val.length == 0) {
1655
+ console.error(`invalid declaration`, node);
1656
+ return '';
1657
+ }
1625
1658
  str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
1626
1659
  }
1627
1660
  else if (node.typ == 'AtRule' && !('chi' in node)) {
@@ -1648,7 +1681,18 @@
1648
1681
  }
1649
1682
  return '';
1650
1683
  }
1651
- function renderToken(token, options = {}) {
1684
+ function renderToken(token, options = {}, reducer) {
1685
+ if (reducer == null) {
1686
+ reducer = function (acc, curr) {
1687
+ if (curr.typ == 'Comment' && options.removeComments) {
1688
+ if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1689
+ return acc;
1690
+ }
1691
+ return acc + curr.val;
1692
+ }
1693
+ return acc + renderToken(curr, options, reducer);
1694
+ };
1695
+ }
1652
1696
  switch (token.typ) {
1653
1697
  case 'Color':
1654
1698
  if (options.minify || options.colorConvert) {
@@ -1699,22 +1743,19 @@
1699
1743
  case 'UrlFunc':
1700
1744
  case 'Pseudo-class-func':
1701
1745
  // @ts-ignore
1702
- return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce((acc, curr) => {
1703
- if (options.removeComments && curr.typ == 'Comment') {
1704
- if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1705
- return acc;
1706
- }
1707
- }
1708
- return acc + renderToken(curr, options);
1709
- }, '') + ')';
1746
+ return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce(reducer, '') + ')';
1710
1747
  case 'Includes':
1711
1748
  return '~=';
1712
1749
  case 'Dash-match':
1713
1750
  return '|=';
1714
1751
  case 'Lt':
1715
1752
  return '<';
1753
+ case 'Lte':
1754
+ return '<=';
1716
1755
  case 'Gt':
1717
1756
  return '>';
1757
+ case 'Gte':
1758
+ return '>=';
1718
1759
  case 'End-parens':
1719
1760
  return ')';
1720
1761
  case 'Attr-start':
@@ -1732,37 +1773,73 @@
1732
1773
  case 'Important':
1733
1774
  return '!important';
1734
1775
  case 'Attr':
1735
- return '[' + token.chi.reduce((acc, curr) => acc + renderToken(curr, options), '') + ']';
1776
+ return '[' + token.chi.reduce(reducer, '') + ']';
1736
1777
  case 'Time':
1737
- case 'Frequency':
1738
1778
  case 'Angle':
1739
1779
  case 'Length':
1740
1780
  case 'Dimension':
1741
- const val = (+token.val).toString();
1781
+ case 'Frequency':
1782
+ case 'Resolution':
1783
+ let val = reduceNumber(token.val);
1784
+ let unit = token.unit;
1785
+ if (token.typ == 'Angle') {
1786
+ const angle = getAngle(token);
1787
+ let v;
1788
+ let value = val + unit;
1789
+ for (const u of ['turn', 'deg', 'rad', 'grad']) {
1790
+ if (token.unit == u) {
1791
+ continue;
1792
+ }
1793
+ switch (u) {
1794
+ case 'turn':
1795
+ v = reduceNumber(angle);
1796
+ if (v.length + 4 < value.length) {
1797
+ val = v;
1798
+ unit = u;
1799
+ value = v + u;
1800
+ }
1801
+ break;
1802
+ case 'deg':
1803
+ v = reduceNumber(angle * 360);
1804
+ if (v.length + 3 < value.length) {
1805
+ val = v;
1806
+ unit = u;
1807
+ value = v + u;
1808
+ }
1809
+ break;
1810
+ case 'rad':
1811
+ v = reduceNumber(angle * (2 * Math.PI));
1812
+ if (v.length + 3 < value.length) {
1813
+ val = v;
1814
+ unit = u;
1815
+ value = v + u;
1816
+ }
1817
+ break;
1818
+ case 'grad':
1819
+ v = reduceNumber(angle * 400);
1820
+ if (v.length + 4 < value.length) {
1821
+ val = v;
1822
+ unit = u;
1823
+ value = v + u;
1824
+ }
1825
+ break;
1826
+ }
1827
+ }
1828
+ }
1742
1829
  if (val === '0') {
1743
- if (token.typ == 'Time') {
1830
+ if (unit == 'Time') {
1744
1831
  return '0s';
1745
1832
  }
1746
- if (token.typ == 'Frequency') {
1833
+ if (unit == 'Frequency') {
1747
1834
  return '0Hz';
1748
1835
  }
1749
1836
  // @ts-ignore
1750
- if (token.typ == 'Resolution') {
1837
+ if (unit == 'Resolution') {
1751
1838
  return '0x';
1752
1839
  }
1753
1840
  return '0';
1754
1841
  }
1755
- const chr = val.charAt(0);
1756
- if (chr == '-') {
1757
- const slice = val.slice(0, 2);
1758
- if (slice == '-0') {
1759
- return (val.length == 2 ? '0' : '-' + val.slice(2)) + token.unit;
1760
- }
1761
- }
1762
- else if (chr == '0') {
1763
- return val.slice(1) + token.unit;
1764
- }
1765
- return val + token.unit;
1842
+ return val + unit;
1766
1843
  case 'Perc':
1767
1844
  return token.val + '%';
1768
1845
  case 'Number':
@@ -1779,7 +1856,7 @@
1779
1856
  }
1780
1857
  return num;
1781
1858
  case 'Comment':
1782
- if (options.removeComments) {
1859
+ if (options.removeComments && (!options.preserveLicense || !token.val.startsWith('/*!'))) {
1783
1860
  return '';
1784
1861
  }
1785
1862
  case 'Url-token':
@@ -2000,17 +2077,6 @@
2000
2077
  }
2001
2078
  }
2002
2079
 
2003
- function matchType(val, properties) {
2004
- if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
2005
- (properties.types.includes(val.typ))) {
2006
- return true;
2007
- }
2008
- if (val.typ == 'Number' && val.val == '0') {
2009
- return properties.types.some(type => type == 'Length' || type == 'Angle');
2010
- }
2011
- return false;
2012
- }
2013
-
2014
2080
  const propertiesConfig = getConfig();
2015
2081
  class PropertyMap {
2016
2082
  config;
@@ -2025,6 +2091,9 @@
2025
2091
  this.pattern = config.pattern.split(/\s/);
2026
2092
  }
2027
2093
  add(declaration) {
2094
+ for (const val of declaration.val) {
2095
+ Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
2096
+ }
2028
2097
  if (declaration.nam == this.config.shorthand) {
2029
2098
  this.declarations = new Map;
2030
2099
  this.declarations.set(declaration.nam, declaration);
@@ -2058,7 +2127,8 @@
2058
2127
  i--;
2059
2128
  continue;
2060
2129
  }
2061
- if (matchType(acc[i], props)) {
2130
+ // @ts-ignore
2131
+ if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
2062
2132
  if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
2063
2133
  return acc;
2064
2134
  }
@@ -2192,10 +2262,12 @@
2192
2262
  }
2193
2263
  else {
2194
2264
  let count = 0;
2265
+ let match;
2195
2266
  const separator = this.config.separator;
2196
2267
  const tokens = {};
2197
2268
  // @ts-ignore
2198
- /* const valid: string[] =*/ Object.entries(this.config.properties).reduce((acc, curr) => {
2269
+ /* const valid: string[] =*/
2270
+ Object.entries(this.config.properties).reduce((acc, curr) => {
2199
2271
  if (!this.declarations.has(curr[0])) {
2200
2272
  if (curr[1].required) {
2201
2273
  acc.push(curr[0]);
@@ -2204,33 +2276,40 @@
2204
2276
  }
2205
2277
  let current = 0;
2206
2278
  const props = this.config.properties[curr[0]];
2207
- const declaration = this.declarations.get(curr[0]);
2208
- // @ts-ignore
2209
- for (const val of (declaration instanceof PropertySet ? [...declaration][0] : declaration).val) {
2210
- if (separator != null && separator.typ == val.typ && eq(separator, val)) {
2211
- current++;
2212
- if (tokens[curr[0]].length == current) {
2213
- tokens[curr[0]].push([]);
2279
+ const properties = this.declarations.get(curr[0]);
2280
+ for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
2281
+ // @ts-ignore
2282
+ for (const val of declaration.val) {
2283
+ if (separator != null && separator.typ == val.typ && eq(separator, val)) {
2284
+ current++;
2285
+ if (tokens[curr[0]].length == current) {
2286
+ tokens[curr[0]].push([]);
2287
+ }
2288
+ continue;
2214
2289
  }
2215
- continue;
2216
- }
2217
- if (val.typ == 'Whitespace' || val.typ == 'Comment') {
2218
- continue;
2219
- }
2220
- if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2221
- continue;
2222
- }
2223
- if (matchType(val, curr[1])) {
2224
- if (!(curr[0] in tokens)) {
2225
- tokens[curr[0]] = [[]];
2290
+ if (val.typ == 'Whitespace' || val.typ == 'Comment') {
2291
+ continue;
2292
+ }
2293
+ if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2294
+ continue;
2295
+ }
2296
+ // @ts-ignore
2297
+ match = val.typ == 'Comment' || matchType(val, curr[1]);
2298
+ if (isShorthand) {
2299
+ isShorthand = match;
2300
+ }
2301
+ // @ts-ignore
2302
+ if (('propertyName' in val && val.propertyName == property) || match) {
2303
+ if (!(curr[0] in tokens)) {
2304
+ tokens[curr[0]] = [[]];
2305
+ }
2306
+ // is default value
2307
+ tokens[curr[0]][current].push(val);
2308
+ }
2309
+ else {
2310
+ acc.push(curr[0]);
2311
+ break;
2226
2312
  }
2227
- // is default value
2228
- tokens[curr[0]][current].push(val);
2229
- // continue;
2230
- }
2231
- else {
2232
- acc.push(curr[0]);
2233
- break;
2234
2313
  }
2235
2314
  }
2236
2315
  if (count == 0) {
@@ -2239,7 +2318,12 @@
2239
2318
  return acc;
2240
2319
  }, []);
2241
2320
  count++;
2242
- if (!Object.values(tokens).every(v => v.length == count)) {
2321
+ if (!isShorthand || Object.entries(this.config.properties).some(entry => {
2322
+ // missing required property
2323
+ return entry[1].required && !(entry[0] in tokens);
2324
+ }) ||
2325
+ // @ts-ignore
2326
+ !Object.values(tokens).every(v => v.filter(t => t.typ != 'Comment').length == count)) {
2243
2327
  // @ts-ignore
2244
2328
  iterable = this.declarations.values();
2245
2329
  }
@@ -2792,6 +2876,17 @@
2792
2876
  continue;
2793
2877
  // }
2794
2878
  }
2879
+ // @ts-ignore
2880
+ if (hasDeclaration(node)) {
2881
+ // @ts-ignore
2882
+ minifyRule(node);
2883
+ }
2884
+ else {
2885
+ minify(node, options, recursive);
2886
+ }
2887
+ previous = node;
2888
+ nodeIndex = i;
2889
+ continue;
2795
2890
  }
2796
2891
  // @ts-ignore
2797
2892
  if (node.typ == 'Rule') {
@@ -3306,11 +3401,6 @@
3306
3401
  }
3307
3402
  buffer += quoteStr;
3308
3403
  while (value = peek()) {
3309
- // if (ind >= iterator.length) {
3310
- //
3311
- // yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
3312
- // break;
3313
- // }
3314
3404
  if (value == '\\') {
3315
3405
  const sequence = peek(6);
3316
3406
  let escapeSequence = '';
@@ -3330,9 +3420,23 @@
3330
3420
  }
3331
3421
  break;
3332
3422
  }
3423
+ // @ts-ignore
3424
+ if (isNewLine(codepoint)) {
3425
+ if (i == 1) {
3426
+ buffer += value + escapeSequence.slice(0, i);
3427
+ next(i + 1);
3428
+ continue;
3429
+ }
3430
+ // else {
3431
+ yield pushToken(buffer + value + escapeSequence.slice(0, i), 'Bad-string');
3432
+ buffer = '';
3433
+ // }
3434
+ next(i + 1);
3435
+ break;
3436
+ }
3333
3437
  // not hex or new line
3334
3438
  // @ts-ignore
3335
- if (i == 1 && !isNewLine(codepoint)) {
3439
+ else if (i == 1) {
3336
3440
  buffer += value + sequence[i];
3337
3441
  next(2);
3338
3442
  continue;
@@ -3352,13 +3456,6 @@
3352
3456
  next(escapeSequence.length + 1);
3353
3457
  continue;
3354
3458
  }
3355
- // buffer += value;
3356
- // if (ind >= iterator.length) {
3357
- //
3358
- // // drop '\\' at the end
3359
- // yield pushToken(buffer);
3360
- // break;
3361
- // }
3362
3459
  buffer += next(2);
3363
3460
  continue;
3364
3461
  }
@@ -3368,20 +3465,28 @@
3368
3465
  next();
3369
3466
  // i += value.length;
3370
3467
  buffer = '';
3371
- break;
3468
+ return;
3372
3469
  }
3373
3470
  if (isNewLine(value.charCodeAt(0))) {
3374
3471
  hasNewLine = true;
3375
3472
  }
3376
3473
  if (hasNewLine && value == ';') {
3377
- yield pushToken(buffer, 'Bad-string');
3474
+ yield pushToken(buffer + value, 'Bad-string');
3378
3475
  buffer = '';
3476
+ next();
3379
3477
  break;
3380
3478
  }
3381
3479
  buffer += value;
3382
- // i += value.length;
3383
3480
  next();
3384
3481
  }
3482
+ if (hasNewLine) {
3483
+ yield pushToken(buffer, 'Bad-string');
3484
+ }
3485
+ else {
3486
+ // EOF - 'Unclosed-string' fixed
3487
+ yield pushToken(buffer + quote, 'String');
3488
+ }
3489
+ buffer = '';
3385
3490
  }
3386
3491
  function peek(count = 1) {
3387
3492
  if (count == 1) {
@@ -3495,6 +3600,11 @@
3495
3600
  yield pushToken(buffer);
3496
3601
  buffer = '';
3497
3602
  }
3603
+ if (peek() == '=') {
3604
+ yield pushToken('', 'Lte');
3605
+ next();
3606
+ break;
3607
+ }
3498
3608
  buffer += value;
3499
3609
  value = next();
3500
3610
  if (ind >= iterator.length) {
@@ -3563,7 +3673,13 @@
3563
3673
  yield pushToken(buffer);
3564
3674
  buffer = '';
3565
3675
  }
3566
- yield pushToken('', 'Gt');
3676
+ if (peek() == '=') {
3677
+ yield pushToken('', 'Gte');
3678
+ next();
3679
+ }
3680
+ else {
3681
+ yield pushToken('', 'Gt');
3682
+ }
3567
3683
  consumeWhiteSpace();
3568
3684
  break;
3569
3685
  case '.':
@@ -3605,7 +3721,7 @@
3605
3721
  break;
3606
3722
  case '(':
3607
3723
  if (buffer.length == 0) {
3608
- yield pushToken('', 'Start-parens');
3724
+ yield pushToken(value);
3609
3725
  break;
3610
3726
  }
3611
3727
  buffer += value;
@@ -3719,9 +3835,11 @@
3719
3835
  if (buffer.length > 0) {
3720
3836
  yield pushToken(buffer);
3721
3837
  }
3838
+ // yield pushToken('', 'EOF');
3722
3839
  }
3723
3840
 
3724
3841
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
3842
+ const trimWhiteSpace = ['Gt', 'Gte', 'Lt', 'Lte'];
3725
3843
  const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
3726
3844
  /**
3727
3845
  *
@@ -3768,6 +3886,10 @@
3768
3886
  let tokens = results.map(mapToken);
3769
3887
  let i;
3770
3888
  let loc;
3889
+ // if ((<Token>tokens.at(-1))?.typ == 'EOF') {
3890
+ //
3891
+ // tokens.pop();
3892
+ // }
3771
3893
  for (i = 0; i < tokens.length; i++) {
3772
3894
  if (tokens[i].typ == 'Comment') {
3773
3895
  // @ts-ignore
@@ -3886,7 +4008,7 @@
3886
4008
  // https://www.w3.org/TR/css-nesting-1/#conditionals
3887
4009
  // allowed nesting at-rules
3888
4010
  // there must be a top level rule in the stack
3889
- const raw = tokens.reduce((acc, curr) => {
4011
+ const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
3890
4012
  acc.push(renderToken(curr, { removeComments: true }));
3891
4013
  return acc;
3892
4014
  }, []);
@@ -3917,8 +4039,8 @@
3917
4039
  const uniq = new Map;
3918
4040
  parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
3919
4041
  if (curr.typ == 'Whitespace') {
3920
- if (array[index - 1]?.typ == 'Gt' ||
3921
- array[index + 1]?.typ == 'Gt' ||
4042
+ if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
4043
+ trimWhiteSpace.includes(array[index + 1]?.typ) ||
3922
4044
  combinators.includes(array[index - 1]?.val) ||
3923
4045
  combinators.includes(array[index + 1]?.val)) {
3924
4046
  return acc;
@@ -4106,13 +4228,13 @@
4106
4228
  };
4107
4229
  }
4108
4230
  function parseString(src, options = { location: false }) {
4109
- return [...tokenize(src)].map(t => {
4231
+ return parseTokens([...tokenize(src)].map(t => {
4110
4232
  const token = getTokenType(t.token, t.hint);
4111
4233
  if (options.location) {
4112
4234
  Object.assign(token, { loc: t.position });
4113
4235
  }
4114
4236
  return token;
4115
- });
4237
+ }));
4116
4238
  }
4117
4239
  function getTokenType(val, hint) {
4118
4240
  if (val === '' && hint == null) {
@@ -4122,7 +4244,7 @@
4122
4244
  return ([
4123
4245
  'Whitespace', 'Semi-colon', 'Colon', 'Block-start',
4124
4246
  'Block-start', 'Attr-start', 'Attr-end', 'Start-parens', 'End-parens',
4125
- 'Comma', 'Gt', 'Lt'
4247
+ 'Comma', 'Gt', 'Lt', 'Gte', 'Lte', 'EOF'
4126
4248
  ].includes(hint) ? { typ: hint } : { typ: hint, val });
4127
4249
  }
4128
4250
  if (val == ' ') {
@@ -4250,11 +4372,12 @@
4250
4372
  const t = tokens[i];
4251
4373
  if (t.typ == 'Whitespace' && ((i == 0 ||
4252
4374
  i + 1 == tokens.length ||
4253
- ['Comma'].includes(tokens[i + 1].typ) ||
4375
+ ['Comma', 'Gte', 'Lte'].includes(tokens[i + 1].typ)) ||
4254
4376
  (i > 0 &&
4255
- tokens[i + 1]?.typ != 'Literal' &&
4256
- funcLike.includes(tokens[i - 1].typ) &&
4257
- !['var', 'calc'].includes(tokens[i - 1].val))))) {
4377
+ // tokens[i + 1]?.typ != 'Literal' ||
4378
+ // funcLike.includes(tokens[i - 1].typ) &&
4379
+ // !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
4380
+ trimWhiteSpace.includes(tokens[i - 1].typ)))) {
4258
4381
  tokens.splice(i--, 1);
4259
4382
  continue;
4260
4383
  }
@@ -4371,7 +4494,7 @@
4371
4494
  let m = t.chi.length;
4372
4495
  while (m-- > 0) {
4373
4496
  // @ts-ignore
4374
- if (t.chi[m].typ == 'Literal') {
4497
+ if (['Literal'].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
4375
4498
  // @ts-ignore
4376
4499
  if (t.chi[m + 1]?.typ == 'Whitespace') {
4377
4500
  // @ts-ignore
@@ -4623,6 +4746,7 @@
4623
4746
  exports.isTime = isTime;
4624
4747
  exports.isWhiteSpace = isWhiteSpace;
4625
4748
  exports.load = load;
4749
+ exports.matchType = matchType;
4626
4750
  exports.matchUrl = matchUrl;
4627
4751
  exports.minify = minify;
4628
4752
  exports.minifyRule = minifyRule;