@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/dist/index.cjs
CHANGED
|
@@ -91,10 +91,7 @@ function isHash(name) {
|
|
|
91
91
|
if (name.charAt(0) != '#') {
|
|
92
92
|
return false;
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
return true;
|
|
94
|
+
return isIdent(name.charAt(1));
|
|
98
95
|
}
|
|
99
96
|
function isNumber(name) {
|
|
100
97
|
if (name.length == 0) {
|
|
@@ -1070,6 +1067,21 @@ var config$1 = {
|
|
|
1070
1067
|
|
|
1071
1068
|
const getConfig = () => config$1;
|
|
1072
1069
|
|
|
1070
|
+
const funcList = ['clamp', 'calc'];
|
|
1071
|
+
function matchType(val, properties) {
|
|
1072
|
+
if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
|
|
1073
|
+
(properties.types.includes(val.typ))) {
|
|
1074
|
+
return true;
|
|
1075
|
+
}
|
|
1076
|
+
if (val.typ == 'Number' && val.val == '0') {
|
|
1077
|
+
return properties.types.some(type => type == 'Length' || type == 'Angle');
|
|
1078
|
+
}
|
|
1079
|
+
if (val.typ == 'Func' && funcList.includes(val.val)) {
|
|
1080
|
+
return val.chi.every((t => ['Literal', 'Comma', 'Whitespace', 'Start-parens', 'End-parens'].includes(t.typ) || matchType(t, properties)));
|
|
1081
|
+
}
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1073
1085
|
// name to color
|
|
1074
1086
|
const COLORS_NAMES = Object.seal({
|
|
1075
1087
|
'aliceblue': '#f0f8ff',
|
|
@@ -1564,6 +1576,7 @@ function hsl2rgb(h, s, l, a = null) {
|
|
|
1564
1576
|
}
|
|
1565
1577
|
|
|
1566
1578
|
function render(data, opt = {}) {
|
|
1579
|
+
const startTime = performance.now();
|
|
1567
1580
|
const options = Object.assign(opt.minify ?? true ? {
|
|
1568
1581
|
indent: '',
|
|
1569
1582
|
newLine: '',
|
|
@@ -1582,7 +1595,9 @@ function render(data, opt = {}) {
|
|
|
1582
1595
|
}
|
|
1583
1596
|
return acc + renderToken(curr, options);
|
|
1584
1597
|
}
|
|
1585
|
-
return { code: doRender(data, options, reducer, 0)
|
|
1598
|
+
return { code: doRender(data, options, reducer, 0), stats: {
|
|
1599
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
1600
|
+
} };
|
|
1586
1601
|
}
|
|
1587
1602
|
// @ts-ignore
|
|
1588
1603
|
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
@@ -1595,6 +1610,8 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
1595
1610
|
const indent = indents[level];
|
|
1596
1611
|
const indentSub = indents[level + 1];
|
|
1597
1612
|
switch (data.typ) {
|
|
1613
|
+
case 'Declaration':
|
|
1614
|
+
return `${data.nam}:${options.indent}${data.val.reduce((acc, curr) => acc + renderToken(curr), '')}`;
|
|
1598
1615
|
case 'Comment':
|
|
1599
1616
|
return options.removeComments ? '' : data.val;
|
|
1600
1617
|
case 'StyleSheet':
|
|
@@ -1611,7 +1628,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
1611
1628
|
case 'AtRule':
|
|
1612
1629
|
case 'Rule':
|
|
1613
1630
|
if (data.typ == 'AtRule' && !('chi' in data)) {
|
|
1614
|
-
return `${indent}@${data.nam} ${data.val};`;
|
|
1631
|
+
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
1615
1632
|
}
|
|
1616
1633
|
// @ts-ignore
|
|
1617
1634
|
let children = data.chi.reduce((css, node) => {
|
|
@@ -1620,10 +1637,14 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
1620
1637
|
str = options.removeComments ? '' : node.val;
|
|
1621
1638
|
}
|
|
1622
1639
|
else if (node.typ == 'Declaration') {
|
|
1640
|
+
if (node.val.length == 0) {
|
|
1641
|
+
console.error(`invalid declaration`, node);
|
|
1642
|
+
return '';
|
|
1643
|
+
}
|
|
1623
1644
|
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
|
1624
1645
|
}
|
|
1625
1646
|
else if (node.typ == 'AtRule' && !('chi' in node)) {
|
|
1626
|
-
str =
|
|
1647
|
+
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
1627
1648
|
}
|
|
1628
1649
|
else {
|
|
1629
1650
|
str = doRender(node, options, reducer, level + 1, indents);
|
|
@@ -1640,7 +1661,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
1640
1661
|
children = children.slice(0, -1);
|
|
1641
1662
|
}
|
|
1642
1663
|
if (data.typ == 'AtRule') {
|
|
1643
|
-
return `@${data.nam}${data.val
|
|
1664
|
+
return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
1644
1665
|
}
|
|
1645
1666
|
return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
1646
1667
|
}
|
|
@@ -1790,7 +1811,9 @@ function renderToken(token, options = {}) {
|
|
|
1790
1811
|
case 'Delim':
|
|
1791
1812
|
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
1792
1813
|
}
|
|
1793
|
-
|
|
1814
|
+
console.error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1815
|
+
// throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1816
|
+
return '';
|
|
1794
1817
|
}
|
|
1795
1818
|
|
|
1796
1819
|
function eq(a, b) {
|
|
@@ -1996,17 +2019,6 @@ class PropertySet {
|
|
|
1996
2019
|
}
|
|
1997
2020
|
}
|
|
1998
2021
|
|
|
1999
|
-
function matchType(val, properties) {
|
|
2000
|
-
if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
|
|
2001
|
-
(properties.types.includes(val.typ))) {
|
|
2002
|
-
return true;
|
|
2003
|
-
}
|
|
2004
|
-
if (val.typ == 'Number' && val.val == '0') {
|
|
2005
|
-
return properties.types.some(type => type == 'Length' || type == 'Angle');
|
|
2006
|
-
}
|
|
2007
|
-
return false;
|
|
2008
|
-
}
|
|
2009
|
-
|
|
2010
2022
|
const propertiesConfig = getConfig();
|
|
2011
2023
|
class PropertyMap {
|
|
2012
2024
|
config;
|
|
@@ -2021,6 +2033,9 @@ class PropertyMap {
|
|
|
2021
2033
|
this.pattern = config.pattern.split(/\s/);
|
|
2022
2034
|
}
|
|
2023
2035
|
add(declaration) {
|
|
2036
|
+
for (const val of declaration.val) {
|
|
2037
|
+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
|
|
2038
|
+
}
|
|
2024
2039
|
if (declaration.nam == this.config.shorthand) {
|
|
2025
2040
|
this.declarations = new Map;
|
|
2026
2041
|
this.declarations.set(declaration.nam, declaration);
|
|
@@ -2054,7 +2069,7 @@ class PropertyMap {
|
|
|
2054
2069
|
i--;
|
|
2055
2070
|
continue;
|
|
2056
2071
|
}
|
|
2057
|
-
if (matchType(acc[i], props)) {
|
|
2072
|
+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
|
|
2058
2073
|
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
|
|
2059
2074
|
return acc;
|
|
2060
2075
|
}
|
|
@@ -2188,10 +2203,12 @@ class PropertyMap {
|
|
|
2188
2203
|
}
|
|
2189
2204
|
else {
|
|
2190
2205
|
let count = 0;
|
|
2206
|
+
let match;
|
|
2191
2207
|
const separator = this.config.separator;
|
|
2192
2208
|
const tokens = {};
|
|
2193
2209
|
// @ts-ignore
|
|
2194
|
-
/* const valid: string[] =*/
|
|
2210
|
+
/* const valid: string[] =*/
|
|
2211
|
+
Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
2195
2212
|
if (!this.declarations.has(curr[0])) {
|
|
2196
2213
|
if (curr[1].required) {
|
|
2197
2214
|
acc.push(curr[0]);
|
|
@@ -2200,33 +2217,39 @@ class PropertyMap {
|
|
|
2200
2217
|
}
|
|
2201
2218
|
let current = 0;
|
|
2202
2219
|
const props = this.config.properties[curr[0]];
|
|
2203
|
-
const
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
tokens[curr[0]].
|
|
2220
|
+
const properties = this.declarations.get(curr[0]);
|
|
2221
|
+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
|
|
2222
|
+
// @ts-ignore
|
|
2223
|
+
for (const val of declaration.val) {
|
|
2224
|
+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
2225
|
+
current++;
|
|
2226
|
+
if (tokens[curr[0]].length == current) {
|
|
2227
|
+
tokens[curr[0]].push([]);
|
|
2228
|
+
}
|
|
2229
|
+
continue;
|
|
2210
2230
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2231
|
+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2232
|
+
continue;
|
|
2233
|
+
}
|
|
2234
|
+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
|
|
2235
|
+
continue;
|
|
2236
|
+
}
|
|
2237
|
+
match = matchType(val, curr[1]);
|
|
2238
|
+
if (isShorthand) {
|
|
2239
|
+
isShorthand = match;
|
|
2240
|
+
}
|
|
2241
|
+
if (('propertyName' in val && val.propertyName == property) || match) {
|
|
2242
|
+
if (!(curr[0] in tokens)) {
|
|
2243
|
+
tokens[curr[0]] = [[]];
|
|
2244
|
+
}
|
|
2245
|
+
// is default value
|
|
2246
|
+
tokens[curr[0]][current].push(val);
|
|
2247
|
+
// continue;
|
|
2248
|
+
}
|
|
2249
|
+
else {
|
|
2250
|
+
acc.push(curr[0]);
|
|
2251
|
+
break;
|
|
2222
2252
|
}
|
|
2223
|
-
// is default value
|
|
2224
|
-
tokens[curr[0]][current].push(val);
|
|
2225
|
-
// continue;
|
|
2226
|
-
}
|
|
2227
|
-
else {
|
|
2228
|
-
acc.push(curr[0]);
|
|
2229
|
-
break;
|
|
2230
2253
|
}
|
|
2231
2254
|
}
|
|
2232
2255
|
if (count == 0) {
|
|
@@ -2235,7 +2258,10 @@ class PropertyMap {
|
|
|
2235
2258
|
return acc;
|
|
2236
2259
|
}, []);
|
|
2237
2260
|
count++;
|
|
2238
|
-
if (!Object.
|
|
2261
|
+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
|
|
2262
|
+
// missing required property
|
|
2263
|
+
return entry[1].required && !(entry[0] in tokens);
|
|
2264
|
+
}) || !Object.values(tokens).every(v => v.length == count)) {
|
|
2239
2265
|
// @ts-ignore
|
|
2240
2266
|
iterable = this.declarations.values();
|
|
2241
2267
|
}
|
|
@@ -2579,7 +2605,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
2579
2605
|
// @ts-ignore
|
|
2580
2606
|
return null;
|
|
2581
2607
|
}
|
|
2582
|
-
return { result, node1: exchanged ? node2 : node1, node2: exchanged ?
|
|
2608
|
+
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
|
|
2583
2609
|
}
|
|
2584
2610
|
function matchSelectors(selector1, selector2, parentType) {
|
|
2585
2611
|
let match = [[]];
|
|
@@ -2767,11 +2793,27 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
2767
2793
|
if (node.typ == 'AtRule' && node.nam == 'font-face') {
|
|
2768
2794
|
continue;
|
|
2769
2795
|
}
|
|
2770
|
-
if (node.typ == 'AtRule'
|
|
2796
|
+
if (node.typ == 'AtRule') {
|
|
2797
|
+
if (node.nam == 'media' && node.val == 'all') {
|
|
2798
|
+
// @ts-ignore
|
|
2799
|
+
ast.chi?.splice(i, 1, ...node.chi);
|
|
2800
|
+
i--;
|
|
2801
|
+
continue;
|
|
2802
|
+
}
|
|
2803
|
+
// console.debug({previous, node});
|
|
2771
2804
|
// @ts-ignore
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2805
|
+
if (previous?.typ == 'AtRule' &&
|
|
2806
|
+
previous.nam == node.nam &&
|
|
2807
|
+
previous.val == node.val) {
|
|
2808
|
+
if ('chi' in node) {
|
|
2809
|
+
// @ts-ignore
|
|
2810
|
+
previous.chi.push(...node.chi);
|
|
2811
|
+
}
|
|
2812
|
+
// else {
|
|
2813
|
+
ast?.chi?.splice(i--, 1);
|
|
2814
|
+
continue;
|
|
2815
|
+
// }
|
|
2816
|
+
}
|
|
2775
2817
|
}
|
|
2776
2818
|
// @ts-ignore
|
|
2777
2819
|
if (node.typ == 'Rule') {
|
|
@@ -3286,10 +3328,11 @@ function* tokenize(iterator) {
|
|
|
3286
3328
|
}
|
|
3287
3329
|
buffer += quoteStr;
|
|
3288
3330
|
while (value = peek()) {
|
|
3289
|
-
if (ind >= iterator.length) {
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3331
|
+
// if (ind >= iterator.length) {
|
|
3332
|
+
//
|
|
3333
|
+
// yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
3334
|
+
// break;
|
|
3335
|
+
// }
|
|
3293
3336
|
if (value == '\\') {
|
|
3294
3337
|
const sequence = peek(6);
|
|
3295
3338
|
let escapeSequence = '';
|
|
@@ -3312,7 +3355,7 @@ function* tokenize(iterator) {
|
|
|
3312
3355
|
// not hex or new line
|
|
3313
3356
|
// @ts-ignore
|
|
3314
3357
|
if (i == 1 && !isNewLine(codepoint)) {
|
|
3315
|
-
buffer += sequence[i];
|
|
3358
|
+
buffer += value + sequence[i];
|
|
3316
3359
|
next(2);
|
|
3317
3360
|
continue;
|
|
3318
3361
|
}
|
|
@@ -3332,11 +3375,12 @@ function* tokenize(iterator) {
|
|
|
3332
3375
|
continue;
|
|
3333
3376
|
}
|
|
3334
3377
|
// buffer += value;
|
|
3335
|
-
if (ind >= iterator.length) {
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3378
|
+
// if (ind >= iterator.length) {
|
|
3379
|
+
//
|
|
3380
|
+
// // drop '\\' at the end
|
|
3381
|
+
// yield pushToken(buffer);
|
|
3382
|
+
// break;
|
|
3383
|
+
// }
|
|
3340
3384
|
buffer += next(2);
|
|
3341
3385
|
continue;
|
|
3342
3386
|
}
|
|
@@ -3505,7 +3549,7 @@ function* tokenize(iterator) {
|
|
|
3505
3549
|
buffer = '';
|
|
3506
3550
|
break;
|
|
3507
3551
|
}
|
|
3508
|
-
buffer += value;
|
|
3552
|
+
buffer += prev() + value;
|
|
3509
3553
|
break;
|
|
3510
3554
|
case '"':
|
|
3511
3555
|
case "'":
|
|
@@ -3707,6 +3751,7 @@ const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
|
3707
3751
|
* @param opt
|
|
3708
3752
|
*/
|
|
3709
3753
|
async function parse$1(iterator, opt = {}) {
|
|
3754
|
+
const startTime = performance.now();
|
|
3710
3755
|
const errors = [];
|
|
3711
3756
|
const options = {
|
|
3712
3757
|
src: '',
|
|
@@ -3845,7 +3890,7 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3845
3890
|
src: options.resolve(url, options.src).absolute
|
|
3846
3891
|
}));
|
|
3847
3892
|
});
|
|
3848
|
-
bytesIn += root.bytesIn;
|
|
3893
|
+
bytesIn += root.stats.bytesIn;
|
|
3849
3894
|
if (root.ast.chi.length > 0) {
|
|
3850
3895
|
context.chi.push(...root.ast.chi);
|
|
3851
3896
|
}
|
|
@@ -3891,13 +3936,6 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3891
3936
|
// rule
|
|
3892
3937
|
if (delim.typ == 'Block-start') {
|
|
3893
3938
|
const position = map.get(tokens[0]);
|
|
3894
|
-
// if (context.typ == 'Rule') {
|
|
3895
|
-
//
|
|
3896
|
-
// if (tokens[0]?.typ == 'Iden') {
|
|
3897
|
-
// errors.push({action: 'drop', message: 'invalid nesting rule', location: {src, ...position}});
|
|
3898
|
-
// return null;
|
|
3899
|
-
// }
|
|
3900
|
-
// }
|
|
3901
3939
|
const uniq = new Map;
|
|
3902
3940
|
parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
|
3903
3941
|
if (curr.typ == 'Whitespace') {
|
|
@@ -4073,21 +4111,30 @@ async function parse$1(iterator, opt = {}) {
|
|
|
4073
4111
|
if (tokens.length > 0) {
|
|
4074
4112
|
await parseNode(tokens);
|
|
4075
4113
|
}
|
|
4114
|
+
const endParseTime = performance.now();
|
|
4076
4115
|
if (options.minify) {
|
|
4077
4116
|
if (ast.chi.length > 0) {
|
|
4078
4117
|
minify(ast, options, true);
|
|
4079
4118
|
}
|
|
4080
4119
|
}
|
|
4081
|
-
|
|
4120
|
+
const endTime = performance.now();
|
|
4121
|
+
return {
|
|
4122
|
+
ast, errors, stats: {
|
|
4123
|
+
bytesIn,
|
|
4124
|
+
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
4125
|
+
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
4126
|
+
total: `${(endTime - startTime).toFixed(2)}ms`
|
|
4127
|
+
}
|
|
4128
|
+
};
|
|
4082
4129
|
}
|
|
4083
4130
|
function parseString(src, options = { location: false }) {
|
|
4084
|
-
return [...tokenize(src)].map(t => {
|
|
4131
|
+
return parseTokens([...tokenize(src)].map(t => {
|
|
4085
4132
|
const token = getTokenType(t.token, t.hint);
|
|
4086
4133
|
if (options.location) {
|
|
4087
4134
|
Object.assign(token, { loc: t.position });
|
|
4088
4135
|
}
|
|
4089
4136
|
return token;
|
|
4090
|
-
});
|
|
4137
|
+
}));
|
|
4091
4138
|
}
|
|
4092
4139
|
function getTokenType(val, hint) {
|
|
4093
4140
|
if (val === '' && hint == null) {
|
|
@@ -4429,19 +4476,17 @@ function parseTokens(tokens, options = {}) {
|
|
|
4429
4476
|
async function transform$1(css, options = {}) {
|
|
4430
4477
|
options = { minify: true, removeEmpty: true, ...options };
|
|
4431
4478
|
const startTime = performance.now();
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
}
|
|
4444
|
-
};
|
|
4479
|
+
return parse$1(css, options).then((parseResult) => {
|
|
4480
|
+
const rendered = render(parseResult.ast, options);
|
|
4481
|
+
return {
|
|
4482
|
+
...parseResult, ...rendered, stats: {
|
|
4483
|
+
bytesOut: rendered.code.length,
|
|
4484
|
+
...parseResult.stats,
|
|
4485
|
+
render: rendered.stats.total,
|
|
4486
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
4487
|
+
}
|
|
4488
|
+
};
|
|
4489
|
+
});
|
|
4445
4490
|
}
|
|
4446
4491
|
|
|
4447
4492
|
const matchUrl = /^(https?:)?\/\//;
|
|
@@ -4586,6 +4631,7 @@ exports.isResolution = isResolution;
|
|
|
4586
4631
|
exports.isTime = isTime;
|
|
4587
4632
|
exports.isWhiteSpace = isWhiteSpace;
|
|
4588
4633
|
exports.load = load;
|
|
4634
|
+
exports.matchType = matchType;
|
|
4589
4635
|
exports.matchUrl = matchUrl;
|
|
4590
4636
|
exports.minify = minify;
|
|
4591
4637
|
exports.minifyRule = minifyRule;
|
package/dist/index.d.ts
CHANGED
|
@@ -173,6 +173,30 @@ interface AttrToken {
|
|
|
173
173
|
}
|
|
174
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;
|
|
175
175
|
|
|
176
|
+
interface PropertyMapType {
|
|
177
|
+
default: string[];
|
|
178
|
+
types: string[];
|
|
179
|
+
keywords: string[];
|
|
180
|
+
required?: boolean;
|
|
181
|
+
multiple?: boolean;
|
|
182
|
+
prefix?: {
|
|
183
|
+
typ: 'Literal';
|
|
184
|
+
val: string;
|
|
185
|
+
};
|
|
186
|
+
previous?: string;
|
|
187
|
+
separator?: {
|
|
188
|
+
typ: 'Comma';
|
|
189
|
+
};
|
|
190
|
+
constraints?: {
|
|
191
|
+
[key: string]: {
|
|
192
|
+
[key: string]: any;
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
mapping?: {
|
|
196
|
+
[key: string]: any;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
176
200
|
interface PropertiesConfig {
|
|
177
201
|
properties: PropertiesConfigProperties;
|
|
178
202
|
map: Map;
|
|
@@ -487,11 +511,19 @@ interface TransformOptions extends ParserOptions, RenderOptions {
|
|
|
487
511
|
interface ParseResult {
|
|
488
512
|
ast: AstRuleStyleSheet;
|
|
489
513
|
errors: ErrorDescription[];
|
|
490
|
-
|
|
514
|
+
stats: {
|
|
515
|
+
bytesIn: number;
|
|
516
|
+
parse: string;
|
|
517
|
+
minify: string;
|
|
518
|
+
total: string;
|
|
519
|
+
}
|
|
491
520
|
}
|
|
492
521
|
|
|
493
522
|
interface RenderResult {
|
|
494
523
|
code: string ;
|
|
524
|
+
stats: {
|
|
525
|
+
total: string;
|
|
526
|
+
}
|
|
495
527
|
}
|
|
496
528
|
|
|
497
529
|
interface TransformResult extends ParseResult, RenderResult {
|
|
@@ -500,6 +532,7 @@ interface TransformResult extends ParseResult, RenderResult {
|
|
|
500
532
|
bytesIn: number;
|
|
501
533
|
bytesOut: number;
|
|
502
534
|
parse: string;
|
|
535
|
+
minify: string;
|
|
503
536
|
render: string;
|
|
504
537
|
total: string;
|
|
505
538
|
}
|
|
@@ -620,6 +653,8 @@ declare function isWhiteSpace(codepoint: number): boolean;
|
|
|
620
653
|
|
|
621
654
|
declare const getConfig: () => PropertiesConfig;
|
|
622
655
|
|
|
656
|
+
declare function matchType(val: Token, properties: PropertyMapType): boolean;
|
|
657
|
+
|
|
623
658
|
declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
|
|
624
659
|
declare function renderToken(token: Token, options?: RenderOptions): string;
|
|
625
660
|
|
|
@@ -652,4 +687,4 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
|
|
|
652
687
|
declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
|
|
653
688
|
declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
|
|
654
689
|
|
|
655
|
-
export { combinators, dirname, getConfig, hasDeclaration, isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, load, matchUrl, minify, minifyRule, parse, parseDimension, parseString, reduceSelector, render, renderToken, resolve, tokenize, transform, urlTokenMatcher, walk };
|
|
690
|
+
export { combinators, dirname, getConfig, hasDeclaration, isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, load, matchType, matchUrl, minify, minifyRule, parse, parseDimension, parseString, reduceSelector, render, renderToken, resolve, tokenize, transform, urlTokenMatcher, walk };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { parseString, urlTokenMatcher } from './lib/parser/parse.js';
|
|
|
3
3
|
export { tokenize } from './lib/parser/tokenize.js';
|
|
4
4
|
export { isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension } from './lib/parser/utils/syntax.js';
|
|
5
5
|
export { getConfig } from './lib/parser/utils/config.js';
|
|
6
|
+
export { matchType } from './lib/parser/utils/type.js';
|
|
6
7
|
export { render, renderToken } from './lib/renderer/render.js';
|
|
7
8
|
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector } from './lib/ast/minify.js';
|
|
8
9
|
export { walk } from './lib/ast/walk.js';
|
package/dist/lib/ast/minify.js
CHANGED
|
@@ -135,7 +135,7 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
135
135
|
// @ts-ignore
|
|
136
136
|
return null;
|
|
137
137
|
}
|
|
138
|
-
return { result, node1: exchanged ? node2 : node1, node2: exchanged ?
|
|
138
|
+
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
|
|
139
139
|
}
|
|
140
140
|
function matchSelectors(selector1, selector2, parentType) {
|
|
141
141
|
let match = [[]];
|
|
@@ -323,11 +323,27 @@ function minify(ast, options = {}, recursive = false) {
|
|
|
323
323
|
if (node.typ == 'AtRule' && node.nam == 'font-face') {
|
|
324
324
|
continue;
|
|
325
325
|
}
|
|
326
|
-
if (node.typ == 'AtRule'
|
|
326
|
+
if (node.typ == 'AtRule') {
|
|
327
|
+
if (node.nam == 'media' && node.val == 'all') {
|
|
328
|
+
// @ts-ignore
|
|
329
|
+
ast.chi?.splice(i, 1, ...node.chi);
|
|
330
|
+
i--;
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
// console.debug({previous, node});
|
|
327
334
|
// @ts-ignore
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
335
|
+
if (previous?.typ == 'AtRule' &&
|
|
336
|
+
previous.nam == node.nam &&
|
|
337
|
+
previous.val == node.val) {
|
|
338
|
+
if ('chi' in node) {
|
|
339
|
+
// @ts-ignore
|
|
340
|
+
previous.chi.push(...node.chi);
|
|
341
|
+
}
|
|
342
|
+
// else {
|
|
343
|
+
ast?.chi?.splice(i--, 1);
|
|
344
|
+
continue;
|
|
345
|
+
// }
|
|
346
|
+
}
|
|
331
347
|
}
|
|
332
348
|
// @ts-ignore
|
|
333
349
|
if (node.typ == 'Rule') {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { eq } from '../utils/eq.js';
|
|
2
2
|
import { getConfig } from '../utils/config.js';
|
|
3
|
-
import { renderToken } from '../../renderer/render.js';
|
|
4
3
|
import { matchType } from '../utils/type.js';
|
|
4
|
+
import { renderToken } from '../../renderer/render.js';
|
|
5
5
|
import { parseString } from '../parse.js';
|
|
6
6
|
import { PropertySet } from './set.js';
|
|
7
7
|
|
|
@@ -19,6 +19,9 @@ class PropertyMap {
|
|
|
19
19
|
this.pattern = config.pattern.split(/\s/);
|
|
20
20
|
}
|
|
21
21
|
add(declaration) {
|
|
22
|
+
for (const val of declaration.val) {
|
|
23
|
+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
|
|
24
|
+
}
|
|
22
25
|
if (declaration.nam == this.config.shorthand) {
|
|
23
26
|
this.declarations = new Map;
|
|
24
27
|
this.declarations.set(declaration.nam, declaration);
|
|
@@ -52,7 +55,7 @@ class PropertyMap {
|
|
|
52
55
|
i--;
|
|
53
56
|
continue;
|
|
54
57
|
}
|
|
55
|
-
if (matchType(acc[i], props)) {
|
|
58
|
+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
|
|
56
59
|
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
|
|
57
60
|
return acc;
|
|
58
61
|
}
|
|
@@ -186,10 +189,12 @@ class PropertyMap {
|
|
|
186
189
|
}
|
|
187
190
|
else {
|
|
188
191
|
let count = 0;
|
|
192
|
+
let match;
|
|
189
193
|
const separator = this.config.separator;
|
|
190
194
|
const tokens = {};
|
|
191
195
|
// @ts-ignore
|
|
192
|
-
/* const valid: string[] =*/
|
|
196
|
+
/* const valid: string[] =*/
|
|
197
|
+
Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
193
198
|
if (!this.declarations.has(curr[0])) {
|
|
194
199
|
if (curr[1].required) {
|
|
195
200
|
acc.push(curr[0]);
|
|
@@ -198,33 +203,39 @@ class PropertyMap {
|
|
|
198
203
|
}
|
|
199
204
|
let current = 0;
|
|
200
205
|
const props = this.config.properties[curr[0]];
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
tokens[curr[0]].
|
|
206
|
+
const properties = this.declarations.get(curr[0]);
|
|
207
|
+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
|
|
208
|
+
// @ts-ignore
|
|
209
|
+
for (const val of declaration.val) {
|
|
210
|
+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
211
|
+
current++;
|
|
212
|
+
if (tokens[curr[0]].length == current) {
|
|
213
|
+
tokens[curr[0]].push([]);
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
208
216
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
match = matchType(val, curr[1]);
|
|
224
|
+
if (isShorthand) {
|
|
225
|
+
isShorthand = match;
|
|
226
|
+
}
|
|
227
|
+
if (('propertyName' in val && val.propertyName == property) || match) {
|
|
228
|
+
if (!(curr[0] in tokens)) {
|
|
229
|
+
tokens[curr[0]] = [[]];
|
|
230
|
+
}
|
|
231
|
+
// is default value
|
|
232
|
+
tokens[curr[0]][current].push(val);
|
|
233
|
+
// continue;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
acc.push(curr[0]);
|
|
237
|
+
break;
|
|
220
238
|
}
|
|
221
|
-
// is default value
|
|
222
|
-
tokens[curr[0]][current].push(val);
|
|
223
|
-
// continue;
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
acc.push(curr[0]);
|
|
227
|
-
break;
|
|
228
239
|
}
|
|
229
240
|
}
|
|
230
241
|
if (count == 0) {
|
|
@@ -233,7 +244,10 @@ class PropertyMap {
|
|
|
233
244
|
return acc;
|
|
234
245
|
}, []);
|
|
235
246
|
count++;
|
|
236
|
-
if (!Object.
|
|
247
|
+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
|
|
248
|
+
// missing required property
|
|
249
|
+
return entry[1].required && !(entry[0] in tokens);
|
|
250
|
+
}) || !Object.values(tokens).every(v => v.length == count)) {
|
|
237
251
|
// @ts-ignore
|
|
238
252
|
iterable = this.declarations.values();
|
|
239
253
|
}
|