@tbela99/css-parser 0.0.1-rc1 → 0.0.1-rc3
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 +67 -11
- package/dist/index-umd-web.js +134 -88
- package/dist/index.cjs +134 -88
- package/dist/index.d.ts +37 -2
- package/dist/index.js +1 -0
- package/dist/lib/ast/minify.js +21 -5
- package/dist/lib/parser/declaration/map.js +43 -29
- package/dist/lib/parser/parse.js +14 -11
- package/dist/lib/parser/tokenize.js +13 -11
- package/dist/lib/parser/utils/syntax.js +1 -4
- package/dist/lib/parser/utils/type.js +4 -0
- package/dist/lib/renderer/render.js +16 -5
- package/dist/lib/transform.js +11 -13
- package/dist/web/index.js +1 -0
- package/package.json +10 -10
- package/.gitattributes +0 -22
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://github.com/tbela99/css-parser/actions)
|
|
1
|
+
[](https://www.npmjs.com/package/@tbela99/css-parser) [](https://github.com/tbela99/css-parser/actions)
|
|
2
2
|
|
|
3
3
|
# css-parser
|
|
4
4
|
|
|
@@ -12,15 +12,15 @@ $ npm install @tbela99/css-parser
|
|
|
12
12
|
|
|
13
13
|
### Features
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
15
|
+
- fault tolerant parser, will try to fix invalid tokens according to the CSS syntax module 3 recommendations.
|
|
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
|
+
- automatically generate nested css rules
|
|
19
|
+
- works the same way in node and web browser
|
|
20
20
|
|
|
21
21
|
### Performance
|
|
22
22
|
|
|
23
|
-
-
|
|
23
|
+
- flatten @import
|
|
24
24
|
|
|
25
25
|
## Transform
|
|
26
26
|
|
|
@@ -50,7 +50,7 @@ Include ParseOptions and RenderOptions
|
|
|
50
50
|
|
|
51
51
|
- src: string, optional. css file location to be used with sourcemap.
|
|
52
52
|
- minify: boolean, optional. default to _true_. optimize ast.
|
|
53
|
-
- nestingRules: boolean, optional. automatically
|
|
53
|
+
- nestingRules: boolean, optional. automatically generated nested rules.
|
|
54
54
|
- removeEmpty: boolean, remove empty nodes from the ast.
|
|
55
55
|
- location: boolean, optional. includes node location in the ast, required for sourcemap generation.
|
|
56
56
|
- cwd: string, optional. the current working directory. when specified url() are resolved using this value
|
|
@@ -79,7 +79,7 @@ parse(css, parseOptions = {})
|
|
|
79
79
|
|
|
80
80
|
````javascript
|
|
81
81
|
|
|
82
|
-
const {ast, errors} = await parse(css);
|
|
82
|
+
const {ast, errors, stats} = await parse(css);
|
|
83
83
|
````
|
|
84
84
|
|
|
85
85
|
## Rendering
|
|
@@ -96,7 +96,7 @@ render(ast, RenderOptions = {});
|
|
|
96
96
|
import {render} from '@tbela99/css-parser';
|
|
97
97
|
|
|
98
98
|
// minified
|
|
99
|
-
const {code} = render(ast, {minify: true});
|
|
99
|
+
const {code, stats} = render(ast, {minify: true});
|
|
100
100
|
|
|
101
101
|
console.log(code);
|
|
102
102
|
```
|
|
@@ -160,6 +160,62 @@ Single JavaScript file
|
|
|
160
160
|
<script src="dist/index-umd-web.js"></script>
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
## Example
|
|
164
|
+
|
|
165
|
+
### Automatic CSS Nesting
|
|
166
|
+
|
|
167
|
+
CSS
|
|
168
|
+
|
|
169
|
+
```css
|
|
170
|
+
|
|
171
|
+
table.colortable td {
|
|
172
|
+
text-align:center;
|
|
173
|
+
}
|
|
174
|
+
table.colortable td.c {
|
|
175
|
+
text-transform:uppercase;
|
|
176
|
+
}
|
|
177
|
+
table.colortable td:first-child, table.colortable td:first-child+td {
|
|
178
|
+
border:1px solid black;
|
|
179
|
+
}
|
|
180
|
+
table.colortable th {
|
|
181
|
+
text-align:center;
|
|
182
|
+
background:black;
|
|
183
|
+
color:white;
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Javascript
|
|
188
|
+
```javascript
|
|
189
|
+
import {parse, render} from '@tbela99/css-parser';
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
const options = {minify: true, nestingRules: true};
|
|
193
|
+
|
|
194
|
+
const {code} = await parse(css, options).then(result => render(result.ast, {minify: false}));
|
|
195
|
+
//
|
|
196
|
+
console.debug(code);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Result
|
|
200
|
+
```css
|
|
201
|
+
table.colortable {
|
|
202
|
+
& td {
|
|
203
|
+
text-align: center;
|
|
204
|
+
&.c {
|
|
205
|
+
text-transform: uppercase
|
|
206
|
+
}
|
|
207
|
+
&:first-child,&:first-child+td {
|
|
208
|
+
border: 1px solid #000
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
& th {
|
|
212
|
+
text-align: center;
|
|
213
|
+
background: #000;
|
|
214
|
+
color: #fff
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
163
219
|
## AST
|
|
164
220
|
|
|
165
221
|
### Comment
|
|
@@ -188,4 +244,4 @@ Single JavaScript file
|
|
|
188
244
|
### AtRuleStyleSheet
|
|
189
245
|
|
|
190
246
|
- typ: string 'Stylesheet'
|
|
191
|
-
- chi: array of children
|
|
247
|
+
- chi: array of children
|
package/dist/index-umd-web.js
CHANGED
|
@@ -93,10 +93,7 @@
|
|
|
93
93
|
if (name.charAt(0) != '#') {
|
|
94
94
|
return false;
|
|
95
95
|
}
|
|
96
|
-
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
return true;
|
|
96
|
+
return isIdent(name.charAt(1));
|
|
100
97
|
}
|
|
101
98
|
function isNumber(name) {
|
|
102
99
|
if (name.length == 0) {
|
|
@@ -1072,6 +1069,21 @@
|
|
|
1072
1069
|
|
|
1073
1070
|
const getConfig = () => config$1;
|
|
1074
1071
|
|
|
1072
|
+
const funcList = ['clamp', 'calc'];
|
|
1073
|
+
function matchType(val, properties) {
|
|
1074
|
+
if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
|
|
1075
|
+
(properties.types.includes(val.typ))) {
|
|
1076
|
+
return true;
|
|
1077
|
+
}
|
|
1078
|
+
if (val.typ == 'Number' && val.val == '0') {
|
|
1079
|
+
return properties.types.some(type => type == 'Length' || type == 'Angle');
|
|
1080
|
+
}
|
|
1081
|
+
if (val.typ == 'Func' && funcList.includes(val.val)) {
|
|
1082
|
+
return val.chi.every((t => ['Literal', 'Comma', 'Whitespace', 'Start-parens', 'End-parens'].includes(t.typ) || matchType(t, properties)));
|
|
1083
|
+
}
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1075
1087
|
// name to color
|
|
1076
1088
|
const COLORS_NAMES = Object.seal({
|
|
1077
1089
|
'aliceblue': '#f0f8ff',
|
|
@@ -1566,6 +1578,7 @@
|
|
|
1566
1578
|
}
|
|
1567
1579
|
|
|
1568
1580
|
function render(data, opt = {}) {
|
|
1581
|
+
const startTime = performance.now();
|
|
1569
1582
|
const options = Object.assign(opt.minify ?? true ? {
|
|
1570
1583
|
indent: '',
|
|
1571
1584
|
newLine: '',
|
|
@@ -1584,7 +1597,9 @@
|
|
|
1584
1597
|
}
|
|
1585
1598
|
return acc + renderToken(curr, options);
|
|
1586
1599
|
}
|
|
1587
|
-
return { code: doRender(data, options, reducer, 0)
|
|
1600
|
+
return { code: doRender(data, options, reducer, 0), stats: {
|
|
1601
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
1602
|
+
} };
|
|
1588
1603
|
}
|
|
1589
1604
|
// @ts-ignore
|
|
1590
1605
|
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
@@ -1597,6 +1612,8 @@
|
|
|
1597
1612
|
const indent = indents[level];
|
|
1598
1613
|
const indentSub = indents[level + 1];
|
|
1599
1614
|
switch (data.typ) {
|
|
1615
|
+
case 'Declaration':
|
|
1616
|
+
return `${data.nam}:${options.indent}${data.val.reduce((acc, curr) => acc + renderToken(curr), '')}`;
|
|
1600
1617
|
case 'Comment':
|
|
1601
1618
|
return options.removeComments ? '' : data.val;
|
|
1602
1619
|
case 'StyleSheet':
|
|
@@ -1613,7 +1630,7 @@
|
|
|
1613
1630
|
case 'AtRule':
|
|
1614
1631
|
case 'Rule':
|
|
1615
1632
|
if (data.typ == 'AtRule' && !('chi' in data)) {
|
|
1616
|
-
return `${indent}@${data.nam} ${data.val};`;
|
|
1633
|
+
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
1617
1634
|
}
|
|
1618
1635
|
// @ts-ignore
|
|
1619
1636
|
let children = data.chi.reduce((css, node) => {
|
|
@@ -1622,10 +1639,14 @@
|
|
|
1622
1639
|
str = options.removeComments ? '' : node.val;
|
|
1623
1640
|
}
|
|
1624
1641
|
else if (node.typ == 'Declaration') {
|
|
1642
|
+
if (node.val.length == 0) {
|
|
1643
|
+
console.error(`invalid declaration`, node);
|
|
1644
|
+
return '';
|
|
1645
|
+
}
|
|
1625
1646
|
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
|
1626
1647
|
}
|
|
1627
1648
|
else if (node.typ == 'AtRule' && !('chi' in node)) {
|
|
1628
|
-
str =
|
|
1649
|
+
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
1629
1650
|
}
|
|
1630
1651
|
else {
|
|
1631
1652
|
str = doRender(node, options, reducer, level + 1, indents);
|
|
@@ -1642,7 +1663,7 @@
|
|
|
1642
1663
|
children = children.slice(0, -1);
|
|
1643
1664
|
}
|
|
1644
1665
|
if (data.typ == 'AtRule') {
|
|
1645
|
-
return `@${data.nam}${data.val
|
|
1666
|
+
return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
1646
1667
|
}
|
|
1647
1668
|
return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
1648
1669
|
}
|
|
@@ -1792,7 +1813,9 @@
|
|
|
1792
1813
|
case 'Delim':
|
|
1793
1814
|
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
1794
1815
|
}
|
|
1795
|
-
|
|
1816
|
+
console.error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1817
|
+
// throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1818
|
+
return '';
|
|
1796
1819
|
}
|
|
1797
1820
|
|
|
1798
1821
|
function eq(a, b) {
|
|
@@ -1998,17 +2021,6 @@
|
|
|
1998
2021
|
}
|
|
1999
2022
|
}
|
|
2000
2023
|
|
|
2001
|
-
function matchType(val, properties) {
|
|
2002
|
-
if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
|
|
2003
|
-
(properties.types.includes(val.typ))) {
|
|
2004
|
-
return true;
|
|
2005
|
-
}
|
|
2006
|
-
if (val.typ == 'Number' && val.val == '0') {
|
|
2007
|
-
return properties.types.some(type => type == 'Length' || type == 'Angle');
|
|
2008
|
-
}
|
|
2009
|
-
return false;
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
2024
|
const propertiesConfig = getConfig();
|
|
2013
2025
|
class PropertyMap {
|
|
2014
2026
|
config;
|
|
@@ -2023,6 +2035,9 @@
|
|
|
2023
2035
|
this.pattern = config.pattern.split(/\s/);
|
|
2024
2036
|
}
|
|
2025
2037
|
add(declaration) {
|
|
2038
|
+
for (const val of declaration.val) {
|
|
2039
|
+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
|
|
2040
|
+
}
|
|
2026
2041
|
if (declaration.nam == this.config.shorthand) {
|
|
2027
2042
|
this.declarations = new Map;
|
|
2028
2043
|
this.declarations.set(declaration.nam, declaration);
|
|
@@ -2056,7 +2071,7 @@
|
|
|
2056
2071
|
i--;
|
|
2057
2072
|
continue;
|
|
2058
2073
|
}
|
|
2059
|
-
if (matchType(acc[i], props)) {
|
|
2074
|
+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
|
|
2060
2075
|
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
|
|
2061
2076
|
return acc;
|
|
2062
2077
|
}
|
|
@@ -2190,10 +2205,12 @@
|
|
|
2190
2205
|
}
|
|
2191
2206
|
else {
|
|
2192
2207
|
let count = 0;
|
|
2208
|
+
let match;
|
|
2193
2209
|
const separator = this.config.separator;
|
|
2194
2210
|
const tokens = {};
|
|
2195
2211
|
// @ts-ignore
|
|
2196
|
-
/* const valid: string[] =*/
|
|
2212
|
+
/* const valid: string[] =*/
|
|
2213
|
+
Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
2197
2214
|
if (!this.declarations.has(curr[0])) {
|
|
2198
2215
|
if (curr[1].required) {
|
|
2199
2216
|
acc.push(curr[0]);
|
|
@@ -2202,33 +2219,39 @@
|
|
|
2202
2219
|
}
|
|
2203
2220
|
let current = 0;
|
|
2204
2221
|
const props = this.config.properties[curr[0]];
|
|
2205
|
-
const
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
tokens[curr[0]].
|
|
2222
|
+
const properties = this.declarations.get(curr[0]);
|
|
2223
|
+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
|
|
2224
|
+
// @ts-ignore
|
|
2225
|
+
for (const val of declaration.val) {
|
|
2226
|
+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
2227
|
+
current++;
|
|
2228
|
+
if (tokens[curr[0]].length == current) {
|
|
2229
|
+
tokens[curr[0]].push([]);
|
|
2230
|
+
}
|
|
2231
|
+
continue;
|
|
2212
2232
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2233
|
+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2234
|
+
continue;
|
|
2235
|
+
}
|
|
2236
|
+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
|
|
2237
|
+
continue;
|
|
2238
|
+
}
|
|
2239
|
+
match = matchType(val, curr[1]);
|
|
2240
|
+
if (isShorthand) {
|
|
2241
|
+
isShorthand = match;
|
|
2242
|
+
}
|
|
2243
|
+
if (('propertyName' in val && val.propertyName == property) || match) {
|
|
2244
|
+
if (!(curr[0] in tokens)) {
|
|
2245
|
+
tokens[curr[0]] = [[]];
|
|
2246
|
+
}
|
|
2247
|
+
// is default value
|
|
2248
|
+
tokens[curr[0]][current].push(val);
|
|
2249
|
+
// continue;
|
|
2250
|
+
}
|
|
2251
|
+
else {
|
|
2252
|
+
acc.push(curr[0]);
|
|
2253
|
+
break;
|
|
2224
2254
|
}
|
|
2225
|
-
// is default value
|
|
2226
|
-
tokens[curr[0]][current].push(val);
|
|
2227
|
-
// continue;
|
|
2228
|
-
}
|
|
2229
|
-
else {
|
|
2230
|
-
acc.push(curr[0]);
|
|
2231
|
-
break;
|
|
2232
2255
|
}
|
|
2233
2256
|
}
|
|
2234
2257
|
if (count == 0) {
|
|
@@ -2237,7 +2260,10 @@
|
|
|
2237
2260
|
return acc;
|
|
2238
2261
|
}, []);
|
|
2239
2262
|
count++;
|
|
2240
|
-
if (!Object.
|
|
2263
|
+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
|
|
2264
|
+
// missing required property
|
|
2265
|
+
return entry[1].required && !(entry[0] in tokens);
|
|
2266
|
+
}) || !Object.values(tokens).every(v => v.length == count)) {
|
|
2241
2267
|
// @ts-ignore
|
|
2242
2268
|
iterable = this.declarations.values();
|
|
2243
2269
|
}
|
|
@@ -2581,7 +2607,7 @@
|
|
|
2581
2607
|
// @ts-ignore
|
|
2582
2608
|
return null;
|
|
2583
2609
|
}
|
|
2584
|
-
return { result, node1: exchanged ? node2 : node1, node2: exchanged ?
|
|
2610
|
+
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
|
|
2585
2611
|
}
|
|
2586
2612
|
function matchSelectors(selector1, selector2, parentType) {
|
|
2587
2613
|
let match = [[]];
|
|
@@ -2769,11 +2795,27 @@
|
|
|
2769
2795
|
if (node.typ == 'AtRule' && node.nam == 'font-face') {
|
|
2770
2796
|
continue;
|
|
2771
2797
|
}
|
|
2772
|
-
if (node.typ == 'AtRule'
|
|
2798
|
+
if (node.typ == 'AtRule') {
|
|
2799
|
+
if (node.nam == 'media' && node.val == 'all') {
|
|
2800
|
+
// @ts-ignore
|
|
2801
|
+
ast.chi?.splice(i, 1, ...node.chi);
|
|
2802
|
+
i--;
|
|
2803
|
+
continue;
|
|
2804
|
+
}
|
|
2805
|
+
// console.debug({previous, node});
|
|
2773
2806
|
// @ts-ignore
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2807
|
+
if (previous?.typ == 'AtRule' &&
|
|
2808
|
+
previous.nam == node.nam &&
|
|
2809
|
+
previous.val == node.val) {
|
|
2810
|
+
if ('chi' in node) {
|
|
2811
|
+
// @ts-ignore
|
|
2812
|
+
previous.chi.push(...node.chi);
|
|
2813
|
+
}
|
|
2814
|
+
// else {
|
|
2815
|
+
ast?.chi?.splice(i--, 1);
|
|
2816
|
+
continue;
|
|
2817
|
+
// }
|
|
2818
|
+
}
|
|
2777
2819
|
}
|
|
2778
2820
|
// @ts-ignore
|
|
2779
2821
|
if (node.typ == 'Rule') {
|
|
@@ -3288,10 +3330,11 @@
|
|
|
3288
3330
|
}
|
|
3289
3331
|
buffer += quoteStr;
|
|
3290
3332
|
while (value = peek()) {
|
|
3291
|
-
if (ind >= iterator.length) {
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3333
|
+
// if (ind >= iterator.length) {
|
|
3334
|
+
//
|
|
3335
|
+
// yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
3336
|
+
// break;
|
|
3337
|
+
// }
|
|
3295
3338
|
if (value == '\\') {
|
|
3296
3339
|
const sequence = peek(6);
|
|
3297
3340
|
let escapeSequence = '';
|
|
@@ -3314,7 +3357,7 @@
|
|
|
3314
3357
|
// not hex or new line
|
|
3315
3358
|
// @ts-ignore
|
|
3316
3359
|
if (i == 1 && !isNewLine(codepoint)) {
|
|
3317
|
-
buffer += sequence[i];
|
|
3360
|
+
buffer += value + sequence[i];
|
|
3318
3361
|
next(2);
|
|
3319
3362
|
continue;
|
|
3320
3363
|
}
|
|
@@ -3334,11 +3377,12 @@
|
|
|
3334
3377
|
continue;
|
|
3335
3378
|
}
|
|
3336
3379
|
// buffer += value;
|
|
3337
|
-
if (ind >= iterator.length) {
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3380
|
+
// if (ind >= iterator.length) {
|
|
3381
|
+
//
|
|
3382
|
+
// // drop '\\' at the end
|
|
3383
|
+
// yield pushToken(buffer);
|
|
3384
|
+
// break;
|
|
3385
|
+
// }
|
|
3342
3386
|
buffer += next(2);
|
|
3343
3387
|
continue;
|
|
3344
3388
|
}
|
|
@@ -3507,7 +3551,7 @@
|
|
|
3507
3551
|
buffer = '';
|
|
3508
3552
|
break;
|
|
3509
3553
|
}
|
|
3510
|
-
buffer += value;
|
|
3554
|
+
buffer += prev() + value;
|
|
3511
3555
|
break;
|
|
3512
3556
|
case '"':
|
|
3513
3557
|
case "'":
|
|
@@ -3709,6 +3753,7 @@
|
|
|
3709
3753
|
* @param opt
|
|
3710
3754
|
*/
|
|
3711
3755
|
async function parse$1(iterator, opt = {}) {
|
|
3756
|
+
const startTime = performance.now();
|
|
3712
3757
|
const errors = [];
|
|
3713
3758
|
const options = {
|
|
3714
3759
|
src: '',
|
|
@@ -3847,7 +3892,7 @@
|
|
|
3847
3892
|
src: options.resolve(url, options.src).absolute
|
|
3848
3893
|
}));
|
|
3849
3894
|
});
|
|
3850
|
-
bytesIn += root.bytesIn;
|
|
3895
|
+
bytesIn += root.stats.bytesIn;
|
|
3851
3896
|
if (root.ast.chi.length > 0) {
|
|
3852
3897
|
context.chi.push(...root.ast.chi);
|
|
3853
3898
|
}
|
|
@@ -3893,13 +3938,6 @@
|
|
|
3893
3938
|
// rule
|
|
3894
3939
|
if (delim.typ == 'Block-start') {
|
|
3895
3940
|
const position = map.get(tokens[0]);
|
|
3896
|
-
// if (context.typ == 'Rule') {
|
|
3897
|
-
//
|
|
3898
|
-
// if (tokens[0]?.typ == 'Iden') {
|
|
3899
|
-
// errors.push({action: 'drop', message: 'invalid nesting rule', location: {src, ...position}});
|
|
3900
|
-
// return null;
|
|
3901
|
-
// }
|
|
3902
|
-
// }
|
|
3903
3941
|
const uniq = new Map;
|
|
3904
3942
|
parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
|
3905
3943
|
if (curr.typ == 'Whitespace') {
|
|
@@ -4075,21 +4113,30 @@
|
|
|
4075
4113
|
if (tokens.length > 0) {
|
|
4076
4114
|
await parseNode(tokens);
|
|
4077
4115
|
}
|
|
4116
|
+
const endParseTime = performance.now();
|
|
4078
4117
|
if (options.minify) {
|
|
4079
4118
|
if (ast.chi.length > 0) {
|
|
4080
4119
|
minify(ast, options, true);
|
|
4081
4120
|
}
|
|
4082
4121
|
}
|
|
4083
|
-
|
|
4122
|
+
const endTime = performance.now();
|
|
4123
|
+
return {
|
|
4124
|
+
ast, errors, stats: {
|
|
4125
|
+
bytesIn,
|
|
4126
|
+
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
4127
|
+
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
4128
|
+
total: `${(endTime - startTime).toFixed(2)}ms`
|
|
4129
|
+
}
|
|
4130
|
+
};
|
|
4084
4131
|
}
|
|
4085
4132
|
function parseString(src, options = { location: false }) {
|
|
4086
|
-
return [...tokenize(src)].map(t => {
|
|
4133
|
+
return parseTokens([...tokenize(src)].map(t => {
|
|
4087
4134
|
const token = getTokenType(t.token, t.hint);
|
|
4088
4135
|
if (options.location) {
|
|
4089
4136
|
Object.assign(token, { loc: t.position });
|
|
4090
4137
|
}
|
|
4091
4138
|
return token;
|
|
4092
|
-
});
|
|
4139
|
+
}));
|
|
4093
4140
|
}
|
|
4094
4141
|
function getTokenType(val, hint) {
|
|
4095
4142
|
if (val === '' && hint == null) {
|
|
@@ -4431,19 +4478,17 @@
|
|
|
4431
4478
|
async function transform$1(css, options = {}) {
|
|
4432
4479
|
options = { minify: true, removeEmpty: true, ...options };
|
|
4433
4480
|
const startTime = performance.now();
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
}
|
|
4446
|
-
};
|
|
4481
|
+
return parse$1(css, options).then((parseResult) => {
|
|
4482
|
+
const rendered = render(parseResult.ast, options);
|
|
4483
|
+
return {
|
|
4484
|
+
...parseResult, ...rendered, stats: {
|
|
4485
|
+
bytesOut: rendered.code.length,
|
|
4486
|
+
...parseResult.stats,
|
|
4487
|
+
render: rendered.stats.total,
|
|
4488
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
4489
|
+
}
|
|
4490
|
+
};
|
|
4491
|
+
});
|
|
4447
4492
|
}
|
|
4448
4493
|
|
|
4449
4494
|
const matchUrl = /^(https?:)?\/\//;
|
|
@@ -4602,6 +4647,7 @@
|
|
|
4602
4647
|
exports.isTime = isTime;
|
|
4603
4648
|
exports.isWhiteSpace = isWhiteSpace;
|
|
4604
4649
|
exports.load = load;
|
|
4650
|
+
exports.matchType = matchType;
|
|
4605
4651
|
exports.matchUrl = matchUrl;
|
|
4606
4652
|
exports.minify = minify;
|
|
4607
4653
|
exports.minifyRule = minifyRule;
|