@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.
@@ -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
- return { ast, errors, bytesIn };
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
- yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
41
- break;
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
- // drop '\\' at the end
87
- yield pushToken(buffer);
88
- break;
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 "'":
@@ -87,10 +87,7 @@ function isHash(name) {
87
87
  if (name.charAt(0) != '#') {
88
88
  return false;
89
89
  }
90
- if (isIdent(name.charAt(1))) {
91
- return true;
92
- }
93
- return true;
90
+ return isIdent(name.charAt(1));
94
91
  }
95
92
  function isNumber(name) {
96
93
  if (name.length == 0) {
@@ -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 = `@${node.nam} ${node.val};`;
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 ? ' ' + data.val + options.indent : ''}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
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
- throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
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 };
@@ -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
- const parseResult = await parse(css, options);
8
- const renderTime = performance.now();
9
- const rendered = render(parseResult.ast, options);
10
- const endTime = performance.now();
11
- return {
12
- ...parseResult, ...rendered, stats: {
13
- bytesIn: parseResult.bytesIn,
14
- bytesOut: rendered.code.length,
15
- parse: `${(renderTime - startTime).toFixed(2)}ms`,
16
- render: `${(endTime - renderTime).toFixed(2)}ms`,
17
- total: `${(endTime - startTime).toFixed(2)}ms`
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-rc1",
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.2",
44
+ "@rollup/plugin-commonjs": "^25.0.4",
44
45
  "@rollup/plugin-json": "^6.0.0",
45
- "@rollup/plugin-node-resolve": "^15.0.1",
46
+ "@rollup/plugin-node-resolve": "^15.1.0",
46
47
  "@rollup/plugin-terser": "^0.4.3",
47
- "@rollup/plugin-typescript": "^11.0.0",
48
+ "@rollup/plugin-typescript": "^11.1.2",
48
49
  "@types/chai": "^4.3.5",
49
50
  "@types/mocha": "^10.0.1",
50
- "@types/node": "^18.15.10",
51
- "@web/test-runner": "^0.16.1",
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.20.1",
56
- "rollup-plugin-dts": "^5.3.0",
57
- "tslib": "^2.5.0"
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
-