@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/lib/parser/parse.js
CHANGED
|
@@ -12,6 +12,7 @@ const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
|
12
12
|
* @param opt
|
|
13
13
|
*/
|
|
14
14
|
async function parse(iterator, opt = {}) {
|
|
15
|
+
const startTime = performance.now();
|
|
15
16
|
const errors = [];
|
|
16
17
|
const options = {
|
|
17
18
|
src: '',
|
|
@@ -150,7 +151,7 @@ async function parse(iterator, opt = {}) {
|
|
|
150
151
|
src: options.resolve(url, options.src).absolute
|
|
151
152
|
}));
|
|
152
153
|
});
|
|
153
|
-
bytesIn += root.bytesIn;
|
|
154
|
+
bytesIn += root.stats.bytesIn;
|
|
154
155
|
if (root.ast.chi.length > 0) {
|
|
155
156
|
context.chi.push(...root.ast.chi);
|
|
156
157
|
}
|
|
@@ -196,13 +197,6 @@ async function parse(iterator, opt = {}) {
|
|
|
196
197
|
// rule
|
|
197
198
|
if (delim.typ == 'Block-start') {
|
|
198
199
|
const position = map.get(tokens[0]);
|
|
199
|
-
// if (context.typ == 'Rule') {
|
|
200
|
-
//
|
|
201
|
-
// if (tokens[0]?.typ == 'Iden') {
|
|
202
|
-
// errors.push({action: 'drop', message: 'invalid nesting rule', location: {src, ...position}});
|
|
203
|
-
// return null;
|
|
204
|
-
// }
|
|
205
|
-
// }
|
|
206
200
|
const uniq = new Map;
|
|
207
201
|
parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
|
208
202
|
if (curr.typ == 'Whitespace') {
|
|
@@ -378,21 +372,30 @@ async function parse(iterator, opt = {}) {
|
|
|
378
372
|
if (tokens.length > 0) {
|
|
379
373
|
await parseNode(tokens);
|
|
380
374
|
}
|
|
375
|
+
const endParseTime = performance.now();
|
|
381
376
|
if (options.minify) {
|
|
382
377
|
if (ast.chi.length > 0) {
|
|
383
378
|
minify(ast, options, true);
|
|
384
379
|
}
|
|
385
380
|
}
|
|
386
|
-
|
|
381
|
+
const endTime = performance.now();
|
|
382
|
+
return {
|
|
383
|
+
ast, errors, stats: {
|
|
384
|
+
bytesIn,
|
|
385
|
+
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
386
|
+
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
387
|
+
total: `${(endTime - startTime).toFixed(2)}ms`
|
|
388
|
+
}
|
|
389
|
+
};
|
|
387
390
|
}
|
|
388
391
|
function parseString(src, options = { location: false }) {
|
|
389
|
-
return [...tokenize(src)].map(t => {
|
|
392
|
+
return parseTokens([...tokenize(src)].map(t => {
|
|
390
393
|
const token = getTokenType(t.token, t.hint);
|
|
391
394
|
if (options.location) {
|
|
392
395
|
Object.assign(token, { loc: t.position });
|
|
393
396
|
}
|
|
394
397
|
return token;
|
|
395
|
-
});
|
|
398
|
+
}));
|
|
396
399
|
}
|
|
397
400
|
function getTokenType(val, hint) {
|
|
398
401
|
if (val === '' && hint == null) {
|
|
@@ -36,10 +36,11 @@ function* tokenize(iterator) {
|
|
|
36
36
|
}
|
|
37
37
|
buffer += quoteStr;
|
|
38
38
|
while (value = peek()) {
|
|
39
|
-
if (ind >= iterator.length) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
// if (ind >= iterator.length) {
|
|
40
|
+
//
|
|
41
|
+
// yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
42
|
+
// break;
|
|
43
|
+
// }
|
|
43
44
|
if (value == '\\') {
|
|
44
45
|
const sequence = peek(6);
|
|
45
46
|
let escapeSequence = '';
|
|
@@ -62,7 +63,7 @@ function* tokenize(iterator) {
|
|
|
62
63
|
// not hex or new line
|
|
63
64
|
// @ts-ignore
|
|
64
65
|
if (i == 1 && !isNewLine(codepoint)) {
|
|
65
|
-
buffer += sequence[i];
|
|
66
|
+
buffer += value + sequence[i];
|
|
66
67
|
next(2);
|
|
67
68
|
continue;
|
|
68
69
|
}
|
|
@@ -82,11 +83,12 @@ function* tokenize(iterator) {
|
|
|
82
83
|
continue;
|
|
83
84
|
}
|
|
84
85
|
// buffer += value;
|
|
85
|
-
if (ind >= iterator.length) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
// if (ind >= iterator.length) {
|
|
87
|
+
//
|
|
88
|
+
// // drop '\\' at the end
|
|
89
|
+
// yield pushToken(buffer);
|
|
90
|
+
// break;
|
|
91
|
+
// }
|
|
90
92
|
buffer += next(2);
|
|
91
93
|
continue;
|
|
92
94
|
}
|
|
@@ -255,7 +257,7 @@ function* tokenize(iterator) {
|
|
|
255
257
|
buffer = '';
|
|
256
258
|
break;
|
|
257
259
|
}
|
|
258
|
-
buffer += value;
|
|
260
|
+
buffer += prev() + value;
|
|
259
261
|
break;
|
|
260
262
|
case '"':
|
|
261
263
|
case "'":
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const funcList = ['clamp', 'calc'];
|
|
1
2
|
function matchType(val, properties) {
|
|
2
3
|
if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
|
|
3
4
|
(properties.types.includes(val.typ))) {
|
|
@@ -6,6 +7,9 @@ function matchType(val, properties) {
|
|
|
6
7
|
if (val.typ == 'Number' && val.val == '0') {
|
|
7
8
|
return properties.types.some(type => type == 'Length' || type == 'Angle');
|
|
8
9
|
}
|
|
10
|
+
if (val.typ == 'Func' && funcList.includes(val.val)) {
|
|
11
|
+
return val.chi.every((t => ['Literal', 'Comma', 'Whitespace', 'Start-parens', 'End-parens'].includes(t.typ) || matchType(t, properties)));
|
|
12
|
+
}
|
|
9
13
|
return false;
|
|
10
14
|
}
|
|
11
15
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { COLORS_NAMES, rgb2Hex, hsl2Hex, hwb2hex, cmyk2hex, NAMES_COLORS } from './utils/color.js';
|
|
2
2
|
|
|
3
3
|
function render(data, opt = {}) {
|
|
4
|
+
const startTime = performance.now();
|
|
4
5
|
const options = Object.assign(opt.minify ?? true ? {
|
|
5
6
|
indent: '',
|
|
6
7
|
newLine: '',
|
|
@@ -19,7 +20,9 @@ function render(data, opt = {}) {
|
|
|
19
20
|
}
|
|
20
21
|
return acc + renderToken(curr, options);
|
|
21
22
|
}
|
|
22
|
-
return { code: doRender(data, options, reducer, 0)
|
|
23
|
+
return { code: doRender(data, options, reducer, 0), stats: {
|
|
24
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
25
|
+
} };
|
|
23
26
|
}
|
|
24
27
|
// @ts-ignore
|
|
25
28
|
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
@@ -32,6 +35,8 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
32
35
|
const indent = indents[level];
|
|
33
36
|
const indentSub = indents[level + 1];
|
|
34
37
|
switch (data.typ) {
|
|
38
|
+
case 'Declaration':
|
|
39
|
+
return `${data.nam}:${options.indent}${data.val.reduce((acc, curr) => acc + renderToken(curr), '')}`;
|
|
35
40
|
case 'Comment':
|
|
36
41
|
return options.removeComments ? '' : data.val;
|
|
37
42
|
case 'StyleSheet':
|
|
@@ -48,7 +53,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
48
53
|
case 'AtRule':
|
|
49
54
|
case 'Rule':
|
|
50
55
|
if (data.typ == 'AtRule' && !('chi' in data)) {
|
|
51
|
-
return `${indent}@${data.nam} ${data.val};`;
|
|
56
|
+
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
52
57
|
}
|
|
53
58
|
// @ts-ignore
|
|
54
59
|
let children = data.chi.reduce((css, node) => {
|
|
@@ -57,10 +62,14 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
57
62
|
str = options.removeComments ? '' : node.val;
|
|
58
63
|
}
|
|
59
64
|
else if (node.typ == 'Declaration') {
|
|
65
|
+
if (node.val.length == 0) {
|
|
66
|
+
console.error(`invalid declaration`, node);
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
60
69
|
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
|
61
70
|
}
|
|
62
71
|
else if (node.typ == 'AtRule' && !('chi' in node)) {
|
|
63
|
-
str =
|
|
72
|
+
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
64
73
|
}
|
|
65
74
|
else {
|
|
66
75
|
str = doRender(node, options, reducer, level + 1, indents);
|
|
@@ -77,7 +86,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
77
86
|
children = children.slice(0, -1);
|
|
78
87
|
}
|
|
79
88
|
if (data.typ == 'AtRule') {
|
|
80
|
-
return `@${data.nam}${data.val
|
|
89
|
+
return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
81
90
|
}
|
|
82
91
|
return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
83
92
|
}
|
|
@@ -227,7 +236,9 @@ function renderToken(token, options = {}) {
|
|
|
227
236
|
case 'Delim':
|
|
228
237
|
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
229
238
|
}
|
|
230
|
-
|
|
239
|
+
console.error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
240
|
+
// throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
241
|
+
return '';
|
|
231
242
|
}
|
|
232
243
|
|
|
233
244
|
export { render, renderToken };
|
package/dist/lib/transform.js
CHANGED
|
@@ -4,19 +4,17 @@ import { render } from './renderer/render.js';
|
|
|
4
4
|
async function transform(css, options = {}) {
|
|
5
5
|
options = { minify: true, removeEmpty: true, ...options };
|
|
6
6
|
const startTime = performance.now();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
};
|
|
7
|
+
return parse(css, options).then((parseResult) => {
|
|
8
|
+
const rendered = render(parseResult.ast, options);
|
|
9
|
+
return {
|
|
10
|
+
...parseResult, ...rendered, stats: {
|
|
11
|
+
bytesOut: rendered.code.length,
|
|
12
|
+
...parseResult.stats,
|
|
13
|
+
render: rendered.stats.total,
|
|
14
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
});
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
export { transform };
|
package/dist/web/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
|
import { transform as transform$1 } from '../lib/transform.js';
|
|
8
9
|
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector } from '../lib/ast/minify.js';
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tbela99/css-parser",
|
|
3
3
|
"description": "CSS parser for node and the browser",
|
|
4
|
-
"version": "0.0.1-
|
|
4
|
+
"version": "0.0.1-rc3",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
7
|
+
"./umd": "./dist/index-umd-web.js",
|
|
7
8
|
"./web": "./dist/web/index.js",
|
|
8
9
|
"./cjs": "./dist/index.cjs"
|
|
9
10
|
},
|
|
@@ -40,20 +41,19 @@
|
|
|
40
41
|
"homepage": "https://github.com/tbela99/css-parser#readme",
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@esm-bundle/chai": "^4.3.4-fix.0",
|
|
43
|
-
"@rollup/plugin-commonjs": "^25.0.
|
|
44
|
+
"@rollup/plugin-commonjs": "^25.0.4",
|
|
44
45
|
"@rollup/plugin-json": "^6.0.0",
|
|
45
|
-
"@rollup/plugin-node-resolve": "^15.0
|
|
46
|
+
"@rollup/plugin-node-resolve": "^15.1.0",
|
|
46
47
|
"@rollup/plugin-terser": "^0.4.3",
|
|
47
|
-
"@rollup/plugin-typescript": "^11.
|
|
48
|
+
"@rollup/plugin-typescript": "^11.1.2",
|
|
48
49
|
"@types/chai": "^4.3.5",
|
|
49
50
|
"@types/mocha": "^10.0.1",
|
|
50
|
-
"@types/node": "^
|
|
51
|
-
"@web/test-runner": "^0.
|
|
52
|
-
"@webref/css": "^6.5.9",
|
|
51
|
+
"@types/node": "^20.4.10",
|
|
52
|
+
"@web/test-runner": "^0.17.0",
|
|
53
53
|
"c8": "^8.0.1",
|
|
54
54
|
"mocha": "^10.2.0",
|
|
55
|
-
"rollup": "^3.
|
|
56
|
-
"rollup-plugin-dts": "^5.3.
|
|
57
|
-
"tslib": "^2.
|
|
55
|
+
"rollup": "^3.28.0",
|
|
56
|
+
"rollup-plugin-dts": "^5.3.1",
|
|
57
|
+
"tslib": "^2.6.1"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/.gitattributes
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/test/ export-ignore
|
|
2
|
-
/docs/ export-ignore
|
|
3
|
-
/benchmark
|
|
4
|
-
/tools/ export-ignore
|
|
5
|
-
/package-lock.json export-ignore
|
|
6
|
-
/.gitignore export-ignore
|
|
7
|
-
/.gitattributes export-ignore
|
|
8
|
-
/coverage/ export-ignore
|
|
9
|
-
/rollup.config.mjs export-ignore
|
|
10
|
-
/tsconfig.json export-ignore
|
|
11
|
-
# exclude all files in test/ from stats
|
|
12
|
-
/test/** linguist-vendored
|
|
13
|
-
/docs/** linguist-vendored
|
|
14
|
-
/tools/** linguist-vendored
|
|
15
|
-
/dist/** linguist-vendored
|
|
16
|
-
/coverage/** linguist-vendored
|
|
17
|
-
#
|
|
18
|
-
# do not replace lf by crlf
|
|
19
|
-
*.css text
|
|
20
|
-
*.json text
|
|
21
|
-
text eol=lf
|
|
22
|
-
|