@tbela99/css-parser 0.7.0 → 0.7.1

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 CHANGED
@@ -1,4 +1,5 @@
1
- [![npm](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Ftbela99%2Fcss-parser%2Fmaster%2Fpackage.json&query=version&logo=npm&label=npm&link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2F%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser) [![cov](https://tbela99.github.io/css-parser/badges/coverage.svg)](https://github.com/tbela99/css-parser/actions) [![NPM Downloads](https://img.shields.io/npm/dm/%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser)
1
+ [![npm](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Ftbela99%2Fcss-parser%2Fmaster%2Fpackage.json&query=version&logo=npm&label=npm&link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2F%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser) [![npm](https://img.shields.io/jsr/v/%40tbela99/css-parser?link=https%3A%2F%2Fjsr.io%2F%40tbela99%2Fcss-parser
2
+ )](https://jsr.io/@tbela99/css-parser) [![cov](https://tbela99.github.io/css-parser/badges/coverage.svg)](https://github.com/tbela99/css-parser/actions) [![NPM Downloads](https://img.shields.io/npm/dm/%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser)
2
3
 
3
4
  # css-parser
4
5
 
@@ -6,9 +7,15 @@ CSS parser and minifier for node and the browser
6
7
 
7
8
  ## Installation
8
9
 
10
+ From npm
9
11
  ```shell
10
12
  $ npm install @tbela99/css-parser
11
13
  ```
14
+ from jsr
15
+ ```shell
16
+ $ deno add @tbela99/css-parser
17
+ ```
18
+
12
19
 
13
20
  ## Features
14
21
 
@@ -5760,6 +5760,13 @@
5760
5760
  buffer = '';
5761
5761
  }
5762
5762
  break;
5763
+ case '&':
5764
+ if (buffer.length > 0) {
5765
+ yield pushToken(buffer, parseInfo);
5766
+ buffer = '';
5767
+ }
5768
+ yield pushToken(value, parseInfo);
5769
+ break;
5763
5770
  case '<':
5764
5771
  if (buffer.length > 0) {
5765
5772
  yield pushToken(buffer, parseInfo);
@@ -60872,7 +60879,67 @@
60872
60879
  }
60873
60880
  }
60874
60881
  else {
60875
- rule.sel = replaceCompound(rule.sel, ast.sel);
60882
+ let childSelectorCompund = [];
60883
+ let withCompound = [];
60884
+ let withoutCompound = [];
60885
+ const rules = splitRule(ast.sel);
60886
+ for (const sel of (rule.raw ?? splitRule(rule.sel))) {
60887
+ const s = sel.join('');
60888
+ if (s.includes('&')) {
60889
+ if (s.indexOf('&', 1) == -1) {
60890
+ if (s.at(0) == '&') {
60891
+ if (s.at(1) == ' ') {
60892
+ childSelectorCompund.push(s.slice(2));
60893
+ }
60894
+ else {
60895
+ if (s == '&') {
60896
+ withCompound.push(s);
60897
+ }
60898
+ else {
60899
+ withoutCompound.push(s.slice(1));
60900
+ }
60901
+ }
60902
+ }
60903
+ }
60904
+ else {
60905
+ withCompound.push(s);
60906
+ }
60907
+ }
60908
+ else {
60909
+ withoutCompound.push(s);
60910
+ }
60911
+ }
60912
+ const selectors = [];
60913
+ const selector = rules.length > 1 ? ':is(' + rules.map(a => a.join('')).join(',') + ')' : rules[0].join('');
60914
+ if (childSelectorCompund.length > 0) {
60915
+ if (childSelectorCompund.length == 1) {
60916
+ selectors.push(replaceCompound('& ' + childSelectorCompund[0].trim(), selector));
60917
+ }
60918
+ else {
60919
+ selectors.push(replaceCompound('& :is(' + childSelectorCompund.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
60920
+ }
60921
+ }
60922
+ if (withoutCompound.length > 0) {
60923
+ if (withoutCompound.length == 1) {
60924
+ const useIs = rules.length == 1 && selector.match(/^[a-zA-Z.:]/) != null && selector.includes(' ') && withoutCompound.length == 1 && withoutCompound[0].match(/^[a-zA-Z]+$/) != null;
60925
+ const compound = useIs ? ':is(&)' : '&';
60926
+ selectors.push(replaceCompound(rules.length == 1 ? (useIs ? withoutCompound[0] + ':is(&)' : (selector.match(/^[.:]/) && withoutCompound[0].match(/^[a-zA-Z]+$/) ? withoutCompound[0] + compound : compound + withoutCompound[0])) : (withoutCompound[0].match(/^[a-zA-Z:]+$/) ? withoutCompound[0].trim() + compound : '&' + (withoutCompound[0].match(/^\S+$/) ? withoutCompound[0].trim() : ':is(' + withoutCompound[0].trim() + ')')), selector));
60927
+ }
60928
+ else {
60929
+ selectors.push(replaceCompound('&:is(' + withoutCompound.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
60930
+ }
60931
+ }
60932
+ if (withCompound.length > 0) {
60933
+ if (withCompound.length == 1) {
60934
+ selectors.push(replaceCompound(withCompound[0], selector));
60935
+ }
60936
+ else {
60937
+ for (const w of withCompound) {
60938
+ selectors.push(replaceCompound(w, selector));
60939
+ }
60940
+ }
60941
+ }
60942
+ rule.sel = selectors.reduce((acc, curr) => curr.length == 0 ? acc : acc + (acc.length > 0 ? ',' : '') + curr, '');
60876
60943
  }
60877
60944
  ast.chi.splice(i--, 1);
60878
60945
  result.push(...expandRule(rule));
@@ -63355,6 +63422,9 @@
63355
63422
  return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(parseResponse);
63356
63423
  }
63357
63424
 
63425
+ /**
63426
+ * render ast node
63427
+ */
63358
63428
  function render(data, options = {}) {
63359
63429
  return doRender(data, Object.assign(options, {
63360
63430
  load,
@@ -63363,6 +63433,9 @@
63363
63433
  cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
63364
63434
  }));
63365
63435
  }
63436
+ /**
63437
+ * parse css
63438
+ */
63366
63439
  async function parse(iterator, opt = {}) {
63367
63440
  return doParse(iterator, Object.assign(opt, {
63368
63441
  load,
@@ -63371,6 +63444,9 @@
63371
63444
  cwd: opt.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
63372
63445
  }));
63373
63446
  }
63447
+ /**
63448
+ * parse and render css
63449
+ */
63374
63450
  async function transform(css, options = {}) {
63375
63451
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
63376
63452
  const startTime = performance.now();
package/dist/index.cjs CHANGED
@@ -5759,6 +5759,13 @@ function* tokenize(stream) {
5759
5759
  buffer = '';
5760
5760
  }
5761
5761
  break;
5762
+ case '&':
5763
+ if (buffer.length > 0) {
5764
+ yield pushToken(buffer, parseInfo);
5765
+ buffer = '';
5766
+ }
5767
+ yield pushToken(value, parseInfo);
5768
+ break;
5762
5769
  case '<':
5763
5770
  if (buffer.length > 0) {
5764
5771
  yield pushToken(buffer, parseInfo);
@@ -60871,7 +60878,67 @@ function expandRule(node) {
60871
60878
  }
60872
60879
  }
60873
60880
  else {
60874
- rule.sel = replaceCompound(rule.sel, ast.sel);
60881
+ let childSelectorCompund = [];
60882
+ let withCompound = [];
60883
+ let withoutCompound = [];
60884
+ const rules = splitRule(ast.sel);
60885
+ for (const sel of (rule.raw ?? splitRule(rule.sel))) {
60886
+ const s = sel.join('');
60887
+ if (s.includes('&')) {
60888
+ if (s.indexOf('&', 1) == -1) {
60889
+ if (s.at(0) == '&') {
60890
+ if (s.at(1) == ' ') {
60891
+ childSelectorCompund.push(s.slice(2));
60892
+ }
60893
+ else {
60894
+ if (s == '&') {
60895
+ withCompound.push(s);
60896
+ }
60897
+ else {
60898
+ withoutCompound.push(s.slice(1));
60899
+ }
60900
+ }
60901
+ }
60902
+ }
60903
+ else {
60904
+ withCompound.push(s);
60905
+ }
60906
+ }
60907
+ else {
60908
+ withoutCompound.push(s);
60909
+ }
60910
+ }
60911
+ const selectors = [];
60912
+ const selector = rules.length > 1 ? ':is(' + rules.map(a => a.join('')).join(',') + ')' : rules[0].join('');
60913
+ if (childSelectorCompund.length > 0) {
60914
+ if (childSelectorCompund.length == 1) {
60915
+ selectors.push(replaceCompound('& ' + childSelectorCompund[0].trim(), selector));
60916
+ }
60917
+ else {
60918
+ selectors.push(replaceCompound('& :is(' + childSelectorCompund.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
60919
+ }
60920
+ }
60921
+ if (withoutCompound.length > 0) {
60922
+ if (withoutCompound.length == 1) {
60923
+ const useIs = rules.length == 1 && selector.match(/^[a-zA-Z.:]/) != null && selector.includes(' ') && withoutCompound.length == 1 && withoutCompound[0].match(/^[a-zA-Z]+$/) != null;
60924
+ const compound = useIs ? ':is(&)' : '&';
60925
+ selectors.push(replaceCompound(rules.length == 1 ? (useIs ? withoutCompound[0] + ':is(&)' : (selector.match(/^[.:]/) && withoutCompound[0].match(/^[a-zA-Z]+$/) ? withoutCompound[0] + compound : compound + withoutCompound[0])) : (withoutCompound[0].match(/^[a-zA-Z:]+$/) ? withoutCompound[0].trim() + compound : '&' + (withoutCompound[0].match(/^\S+$/) ? withoutCompound[0].trim() : ':is(' + withoutCompound[0].trim() + ')')), selector));
60926
+ }
60927
+ else {
60928
+ selectors.push(replaceCompound('&:is(' + withoutCompound.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
60929
+ }
60930
+ }
60931
+ if (withCompound.length > 0) {
60932
+ if (withCompound.length == 1) {
60933
+ selectors.push(replaceCompound(withCompound[0], selector));
60934
+ }
60935
+ else {
60936
+ for (const w of withCompound) {
60937
+ selectors.push(replaceCompound(w, selector));
60938
+ }
60939
+ }
60940
+ }
60941
+ rule.sel = selectors.reduce((acc, curr) => curr.length == 0 ? acc : acc + (acc.length > 0 ? ',' : '') + curr, '');
60875
60942
  }
60876
60943
  ast.chi.splice(i--, 1);
60877
60944
  result.push(...expandRule(rule));
@@ -63343,12 +63410,25 @@ async function load(url, currentFile) {
63343
63410
  return matchUrl.test(resolved.absolute) ? fetch(resolved.absolute).then(parseResponse) : promises.readFile(resolved.absolute, { encoding: 'utf-8' });
63344
63411
  }
63345
63412
 
63413
+ /**
63414
+ * entry point for node and other runtimes
63415
+ * @module
63416
+ */
63417
+ /**
63418
+ * render ast node
63419
+ */
63346
63420
  function render(data, options = {}) {
63347
63421
  return doRender(data, Object.assign(options, { load, resolve, dirname, cwd: options.cwd ?? process.cwd() }));
63348
63422
  }
63423
+ /**
63424
+ * parse css
63425
+ */
63349
63426
  async function parse(iterator, opt = {}) {
63350
63427
  return doParse(iterator, Object.assign(opt, { load, resolve, dirname, cwd: opt.cwd ?? process.cwd() }));
63351
63428
  }
63429
+ /**
63430
+ * parse and render css
63431
+ */
63352
63432
  async function transform(css, options = {}) {
63353
63433
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
63354
63434
  const startTime = performance.now();
package/dist/index.d.ts CHANGED
@@ -1013,8 +1013,22 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
1013
1013
 
1014
1014
  declare function load(url: string, currentFile: string): Promise<string>;
1015
1015
 
1016
+ /**
1017
+ * entry point for node and other runtimes
1018
+ * @module
1019
+ */
1020
+
1021
+ /**
1022
+ * render ast node
1023
+ */
1016
1024
  declare function render(data: AstNode, options?: RenderOptions): RenderResult;
1025
+ /**
1026
+ * parse css
1027
+ */
1017
1028
  declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
1029
+ /**
1030
+ * parse and render css
1031
+ */
1018
1032
  declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
1019
1033
 
1020
1034
  export { EnumToken, dirname, expand, load, minify, parse, parseString, parseTokens, render, renderToken, resolve, transform, walk, walkValues };
@@ -72,7 +72,67 @@ function expandRule(node) {
72
72
  }
73
73
  }
74
74
  else {
75
- rule.sel = replaceCompound(rule.sel, ast.sel);
75
+ let childSelectorCompund = [];
76
+ let withCompound = [];
77
+ let withoutCompound = [];
78
+ const rules = splitRule(ast.sel);
79
+ for (const sel of (rule.raw ?? splitRule(rule.sel))) {
80
+ const s = sel.join('');
81
+ if (s.includes('&')) {
82
+ if (s.indexOf('&', 1) == -1) {
83
+ if (s.at(0) == '&') {
84
+ if (s.at(1) == ' ') {
85
+ childSelectorCompund.push(s.slice(2));
86
+ }
87
+ else {
88
+ if (s == '&') {
89
+ withCompound.push(s);
90
+ }
91
+ else {
92
+ withoutCompound.push(s.slice(1));
93
+ }
94
+ }
95
+ }
96
+ }
97
+ else {
98
+ withCompound.push(s);
99
+ }
100
+ }
101
+ else {
102
+ withoutCompound.push(s);
103
+ }
104
+ }
105
+ const selectors = [];
106
+ const selector = rules.length > 1 ? ':is(' + rules.map(a => a.join('')).join(',') + ')' : rules[0].join('');
107
+ if (childSelectorCompund.length > 0) {
108
+ if (childSelectorCompund.length == 1) {
109
+ selectors.push(replaceCompound('& ' + childSelectorCompund[0].trim(), selector));
110
+ }
111
+ else {
112
+ selectors.push(replaceCompound('& :is(' + childSelectorCompund.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
113
+ }
114
+ }
115
+ if (withoutCompound.length > 0) {
116
+ if (withoutCompound.length == 1) {
117
+ const useIs = rules.length == 1 && selector.match(/^[a-zA-Z.:]/) != null && selector.includes(' ') && withoutCompound.length == 1 && withoutCompound[0].match(/^[a-zA-Z]+$/) != null;
118
+ const compound = useIs ? ':is(&)' : '&';
119
+ selectors.push(replaceCompound(rules.length == 1 ? (useIs ? withoutCompound[0] + ':is(&)' : (selector.match(/^[.:]/) && withoutCompound[0].match(/^[a-zA-Z]+$/) ? withoutCompound[0] + compound : compound + withoutCompound[0])) : (withoutCompound[0].match(/^[a-zA-Z:]+$/) ? withoutCompound[0].trim() + compound : '&' + (withoutCompound[0].match(/^\S+$/) ? withoutCompound[0].trim() : ':is(' + withoutCompound[0].trim() + ')')), selector));
120
+ }
121
+ else {
122
+ selectors.push(replaceCompound('&:is(' + withoutCompound.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
123
+ }
124
+ }
125
+ if (withCompound.length > 0) {
126
+ if (withCompound.length == 1) {
127
+ selectors.push(replaceCompound(withCompound[0], selector));
128
+ }
129
+ else {
130
+ for (const w of withCompound) {
131
+ selectors.push(replaceCompound(w, selector));
132
+ }
133
+ }
134
+ }
135
+ rule.sel = selectors.reduce((acc, curr) => curr.length == 0 ? acc : acc + (acc.length > 0 ? ',' : '') + curr, '');
76
136
  }
77
137
  ast.chi.splice(i--, 1);
78
138
  result.push(...expandRule(rule));
@@ -187,6 +187,13 @@ function* tokenize(stream) {
187
187
  buffer = '';
188
188
  }
189
189
  break;
190
+ case '&':
191
+ if (buffer.length > 0) {
192
+ yield pushToken(buffer, parseInfo);
193
+ buffer = '';
194
+ }
195
+ yield pushToken(value, parseInfo);
196
+ break;
190
197
  case '<':
191
198
  if (buffer.length > 0) {
192
199
  yield pushToken(buffer, parseInfo);
@@ -12,12 +12,25 @@ import '../lib/parser/utils/config.js';
12
12
  import { resolve, dirname } from '../lib/fs/resolve.js';
13
13
  import { load } from './load.js';
14
14
 
15
+ /**
16
+ * entry point for node and other runtimes
17
+ * @module
18
+ */
19
+ /**
20
+ * render ast node
21
+ */
15
22
  function render(data, options = {}) {
16
23
  return doRender(data, Object.assign(options, { load, resolve, dirname, cwd: options.cwd ?? process.cwd() }));
17
24
  }
25
+ /**
26
+ * parse css
27
+ */
18
28
  async function parse(iterator, opt = {}) {
19
29
  return doParse(iterator, Object.assign(opt, { load, resolve, dirname, cwd: opt.cwd ?? process.cwd() }));
20
30
  }
31
+ /**
32
+ * parse and render css
33
+ */
21
34
  async function transform(css, options = {}) {
22
35
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
23
36
  const startTime = performance.now();
package/dist/web/index.js CHANGED
@@ -11,6 +11,9 @@ import '../lib/parser/utils/config.js';
11
11
  import { resolve, dirname } from '../lib/fs/resolve.js';
12
12
  import { load } from './load.js';
13
13
 
14
+ /**
15
+ * render ast node
16
+ */
14
17
  function render(data, options = {}) {
15
18
  return doRender(data, Object.assign(options, {
16
19
  load,
@@ -19,6 +22,9 @@ function render(data, options = {}) {
19
22
  cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
20
23
  }));
21
24
  }
25
+ /**
26
+ * parse css
27
+ */
22
28
  async function parse(iterator, opt = {}) {
23
29
  return doParse(iterator, Object.assign(opt, {
24
30
  load,
@@ -27,6 +33,9 @@ async function parse(iterator, opt = {}) {
27
33
  cwd: opt.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
28
34
  }));
29
35
  }
36
+ /**
37
+ * parse and render css
38
+ */
30
39
  async function transform(css, options = {}) {
31
40
  options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
32
41
  const startTime = performance.now();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tbela99/css-parser",
3
3
  "description": "CSS parser for node and the browser",
4
- "version": "0.7.0",
4
+ "version": "0.7.1",
5
5
  "exports": {
6
6
  ".": "./dist/node/index.js",
7
7
  "./umd": "./dist/index-umd-web.js",
@@ -49,21 +49,21 @@
49
49
  "homepage": "https://github.com/tbela99/css-parser#readme",
50
50
  "devDependencies": {
51
51
  "@esm-bundle/chai": "^4.3.4-fix.0",
52
- "@rollup/plugin-commonjs": "^25.0.7",
52
+ "@rollup/plugin-commonjs": "^26.0.1",
53
53
  "@rollup/plugin-json": "^6.1.0",
54
54
  "@rollup/plugin-node-resolve": "^15.2.3",
55
55
  "@rollup/plugin-typescript": "^11.1.6",
56
- "@types/chai": "^4.3.12",
57
- "@types/mocha": "^10.0.6",
58
- "@types/node": "^20.14.11",
59
- "@types/web": "^0.0.151",
60
- "@web/test-runner": "^0.18.1",
56
+ "@types/chai": "^4.3.19",
57
+ "@types/mocha": "^10.0.8",
58
+ "@types/node": "^22.5.5",
59
+ "@types/web": "^0.0.163",
60
+ "@web/test-runner": "^0.19.0",
61
61
  "@web/test-runner-playwright": "^0.11.0",
62
- "c8": "^9.1.0",
63
- "mocha": "^10.4.0",
64
- "playwright": "^1.45.2",
65
- "rollup": "^4.13.0",
66
- "rollup-plugin-dts": "^6.1.0",
67
- "tslib": "^2.6.2"
62
+ "c8": "^10.1.2",
63
+ "mocha": "^10.7.3",
64
+ "playwright": "^1.47.1",
65
+ "rollup": "^4.21.3",
66
+ "rollup-plugin-dts": "^6.1.1",
67
+ "tslib": "^2.7.0"
68
68
  }
69
69
  }