@tbela99/css-parser 0.0.1-alpha3

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.
@@ -0,0 +1,322 @@
1
+ import { PropertyList } from './declaration/list.js';
2
+ import { eq } from './utils/eq.js';
3
+ import { getConfig } from './utils/config.js';
4
+ import { render } from '../renderer/render.js';
5
+
6
+ const configuration = getConfig();
7
+ function deduplicate(ast, options = {}, recursive = false) {
8
+ // @ts-ignore
9
+ if (('chi' in ast) && ast.chi?.length > 0) {
10
+ let i = 0;
11
+ let previous;
12
+ let node;
13
+ let nodeIndex;
14
+ // @ts-ignore
15
+ for (; i < ast.chi.length; i++) {
16
+ // @ts-ignore
17
+ if (ast.chi[i].typ == 'Comment') {
18
+ continue;
19
+ }
20
+ // @ts-ignore
21
+ node = ast.chi[i];
22
+ if (node.typ == 'AtRule' && node.nam == 'font-face') {
23
+ continue;
24
+ }
25
+ if (node.typ == 'AtRule' && node.val == 'all') {
26
+ // @ts-ignore
27
+ ast.chi?.splice(i, 1, ...node.chi);
28
+ i--;
29
+ continue;
30
+ }
31
+ // @ts-ignore
32
+ if (previous != null && 'chi' in previous && ('chi' in node)) {
33
+ // @ts-ignore
34
+ if (previous.typ == node.typ) {
35
+ let shouldMerge = true;
36
+ // @ts-ignore
37
+ let k = previous.chi.length;
38
+ while (k-- > 0) {
39
+ // @ts-ignore
40
+ if (previous.chi[k].typ == 'Comment') {
41
+ continue;
42
+ }
43
+ // @ts-ignore
44
+ shouldMerge = previous.chi[k].typ == 'Declaration';
45
+ break;
46
+ }
47
+ if (shouldMerge) {
48
+ // @ts-ignore
49
+ if ((node.typ == 'Rule' && node.sel == previous.sel) ||
50
+ // @ts-ignore
51
+ (node.typ == 'AtRule') && node.val == previous.val) {
52
+ // @ts-ignore
53
+ node.chi.unshift(...previous.chi);
54
+ // @ts-ignore
55
+ ast.chi.splice(nodeIndex, 1);
56
+ // @ts-ignore
57
+ if (hasDeclaration(node)) {
58
+ deduplicateRule(node);
59
+ }
60
+ else {
61
+ deduplicate(node, options, recursive);
62
+ }
63
+ i--;
64
+ previous = node;
65
+ nodeIndex = i;
66
+ continue;
67
+ }
68
+ else if (node.typ == 'Rule' && previous?.typ == 'Rule') {
69
+ const intersect = diff(previous, node, options);
70
+ if (intersect != null) {
71
+ if (intersect.node1.chi.length == 0) {
72
+ // @ts-ignore
73
+ ast.chi.splice(i, 1);
74
+ }
75
+ else {
76
+ // @ts-ignore
77
+ ast.chi.splice(i, 1, intersect.node1);
78
+ }
79
+ if (intersect.node2.chi.length == 0) {
80
+ // @ts-ignore
81
+ ast.chi.splice(nodeIndex, 1, intersect.result);
82
+ }
83
+ else {
84
+ // @ts-ignore
85
+ ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ // @ts-ignore
92
+ if (recursive && previous != node) {
93
+ // @ts-ignore
94
+ if (hasDeclaration(previous)) {
95
+ deduplicateRule(previous);
96
+ }
97
+ else {
98
+ deduplicate(previous, options, recursive);
99
+ }
100
+ }
101
+ }
102
+ previous = node;
103
+ nodeIndex = i;
104
+ }
105
+ // @ts-ignore
106
+ if (recursive && node != null && ('chi' in node)) {
107
+ // @ts-ignore
108
+ if (node.chi.some(n => n.typ == 'Declaration')) {
109
+ deduplicateRule(node);
110
+ }
111
+ else {
112
+ deduplicate(node, options, recursive);
113
+ }
114
+ }
115
+ }
116
+ return ast;
117
+ }
118
+ function hasDeclaration(node) {
119
+ // @ts-ignore
120
+ for (let i = 0; i < node.chi?.length; i++) {
121
+ // @ts-ignore
122
+ if (node.chi[i].typ == 'Comment') {
123
+ continue;
124
+ }
125
+ // @ts-ignore
126
+ return node.chi[i].typ == 'Declaration';
127
+ }
128
+ return true;
129
+ }
130
+ function deduplicateRule(ast, options = {}) {
131
+ // @ts-ignore
132
+ if (!('chi' in ast) || ast.chi?.length <= 1) {
133
+ return ast;
134
+ }
135
+ // @ts-ignore
136
+ const j = ast.chi.length;
137
+ let k = 0;
138
+ let map = new Map;
139
+ // @ts-ignore
140
+ for (; k < j; k++) {
141
+ // @ts-ignore
142
+ const node = ast.chi[k];
143
+ if (node.typ == 'Comment') {
144
+ // @ts-ignore
145
+ map.set(node, node);
146
+ continue;
147
+ }
148
+ else if (node.typ != 'Declaration') {
149
+ break;
150
+ }
151
+ if (node.nam in configuration.map ||
152
+ node.nam in configuration.properties) {
153
+ // @ts-ignore
154
+ const shorthand = node.nam in configuration.map ? configuration.map[node.nam].shorthand : configuration.properties[node.nam].shorthand;
155
+ if (!map.has(shorthand)) {
156
+ map.set(shorthand, new PropertyList());
157
+ }
158
+ map.get(shorthand).add(node);
159
+ }
160
+ else {
161
+ map.set(node.nam, node);
162
+ }
163
+ }
164
+ const children = [];
165
+ for (let child of map.values()) {
166
+ if (child instanceof PropertyList) {
167
+ // @ts-ignore
168
+ children.push(...child);
169
+ }
170
+ else {
171
+ // @ts-ignore
172
+ children.push(child);
173
+ }
174
+ }
175
+ // @ts-ignore
176
+ ast.chi = children.concat(ast.chi?.slice(k));
177
+ /*
178
+ // @ts-ignore
179
+
180
+ const properties: PropertyList = new PropertyList();
181
+
182
+ for (; k < j; k++) {
183
+
184
+ // @ts-ignore
185
+ if ('Comment' == ast.chi[k].typ || 'Declaration' == ast.chi[k].typ) {
186
+
187
+ // @ts-ignore
188
+ properties.add(ast.chi[k]);
189
+ continue;
190
+ }
191
+
192
+ break;
193
+ }
194
+
195
+ // @ts-ignore
196
+ ast.chi = [...properties].concat(ast.chi.slice(k));
197
+ */
198
+ //
199
+ // @ts-ignore
200
+ // ast.chi.splice(0, k - 1, ...properties);
201
+ return ast;
202
+ }
203
+ function splitRule(buffer) {
204
+ const result = [];
205
+ let str = '';
206
+ for (let i = 0; i < buffer.length; i++) {
207
+ let chr = buffer.charAt(i);
208
+ if (chr == ',') {
209
+ if (str !== '') {
210
+ result.push(str);
211
+ str = '';
212
+ }
213
+ continue;
214
+ }
215
+ str += chr;
216
+ if (chr == '\\') {
217
+ str += buffer.charAt(++i);
218
+ continue;
219
+ }
220
+ if (chr == '"' || chr == "'") {
221
+ let k = i;
222
+ while (++k < buffer.length) {
223
+ chr = buffer.charAt(k);
224
+ str += chr;
225
+ if (chr == '//') {
226
+ str += buffer.charAt(++k);
227
+ continue;
228
+ }
229
+ if (chr == buffer.charAt(i)) {
230
+ break;
231
+ }
232
+ }
233
+ continue;
234
+ }
235
+ if (chr == '(' || chr == '[') {
236
+ const open = chr;
237
+ const close = chr == '(' ? ')' : ']';
238
+ let inParens = 1;
239
+ let k = i;
240
+ while (++k < buffer.length) {
241
+ chr = buffer.charAt(k);
242
+ if (chr == '\\') {
243
+ str += buffer.slice(k, k + 2);
244
+ k++;
245
+ continue;
246
+ }
247
+ str += chr;
248
+ if (chr == open) {
249
+ inParens++;
250
+ }
251
+ else if (chr == close) {
252
+ inParens--;
253
+ }
254
+ if (inParens == 0) {
255
+ break;
256
+ }
257
+ }
258
+ i = k;
259
+ continue;
260
+ }
261
+ }
262
+ if (str !== '') {
263
+ result.push(str);
264
+ }
265
+ return result;
266
+ }
267
+ function diff(n1, n2, options = {}) {
268
+ let node1 = n1;
269
+ let node2 = n2;
270
+ let exchanged = false;
271
+ if (node1.chi.length > node2.chi.length) {
272
+ const t = node1;
273
+ node1 = node2;
274
+ node2 = t;
275
+ exchanged = true;
276
+ }
277
+ let i = node1.chi.length;
278
+ let j = node2.chi.length;
279
+ if (i == 0 || j == 0) {
280
+ // @ts-ignore
281
+ return null;
282
+ }
283
+ node1 = { ...node1, chi: node1.chi.slice() };
284
+ node2 = { ...node2, chi: node2.chi.slice() };
285
+ const intersect = [];
286
+ while (i--) {
287
+ if (node1.chi[i].typ == 'Comment') {
288
+ continue;
289
+ }
290
+ j = node2.chi.length;
291
+ if (j == 0) {
292
+ break;
293
+ }
294
+ while (j--) {
295
+ if (node2.chi[j].typ == 'Comment') {
296
+ continue;
297
+ }
298
+ if (node1.chi[i].nam == node2.chi[j].nam) {
299
+ if (eq(node1.chi[i], node2.chi[j])) {
300
+ intersect.push(node1.chi[i]);
301
+ node1.chi.splice(i, 1);
302
+ node2.chi.splice(j, 1);
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ // @ts-ignore
309
+ const result = (intersect.length == 0 ? null : {
310
+ ...node1,
311
+ // @ts-ignore
312
+ sel: [...new Set([...(n1.raw || splitRule(n1.sel)).concat(n2.raw || splitRule(n2.sel))])].join(),
313
+ chi: intersect.reverse()
314
+ });
315
+ if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0)) {
316
+ // @ts-ignore
317
+ return null;
318
+ }
319
+ return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
320
+ }
321
+
322
+ export { deduplicate, deduplicateRule, hasDeclaration };