@tbela99/css-parser 0.0.1 → 0.2.0

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.
@@ -1,5 +1,10 @@
1
1
  import { getAngle, COLORS_NAMES, rgb2Hex, hsl2Hex, hwb2hex, cmyk2hex, NAMES_COLORS } from './utils/color.js';
2
+ import { EnumToken } from '../ast/types.js';
3
+ import '../ast/minify.js';
2
4
  import { expand } from '../ast/expand.js';
5
+ import { SourceMap } from './sourcemap/sourcemap.js';
6
+ import '../parser/parse.js';
7
+ import { isNewLine } from '../parser/utils/syntax.js';
3
8
 
4
9
  const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'];
5
10
  function reduceNumber(val) {
@@ -19,35 +24,86 @@ function reduceNumber(val) {
19
24
  }
20
25
  return val;
21
26
  }
22
- function render(data, opt = {}) {
27
+ function update(position, str) {
28
+ let i = 0;
29
+ for (; i < str.length; i++) {
30
+ if (isNewLine(str[i].charCodeAt(0))) {
31
+ position.lin++;
32
+ position.col = 0;
33
+ }
34
+ else {
35
+ position.col++;
36
+ }
37
+ }
38
+ }
39
+ function doRender(data, options = {}) {
40
+ options = {
41
+ ...(options.minify ?? true ? {
42
+ indent: '',
43
+ newLine: '',
44
+ removeComments: true
45
+ } : {
46
+ indent: ' ',
47
+ newLine: '\n',
48
+ compress: false,
49
+ removeComments: false,
50
+ }), sourcemap: false, colorConvert: true, expandNestingRules: false, preserveLicense: false, ...options
51
+ };
23
52
  const startTime = performance.now();
24
53
  const errors = [];
25
- const options = Object.assign(opt.minify ?? true ? {
26
- indent: '',
27
- newLine: '',
28
- removeComments: true
29
- } : {
30
- indent: ' ',
31
- newLine: '\n',
32
- compress: false,
33
- removeComments: false,
34
- }, { colorConvert: true, expandNestingRules: false, preserveLicense: false }, opt);
35
- return {
36
- code: doRender(options.expandNestingRules ? expand(data) : data, options, errors, function reducer(acc, curr) {
37
- if (curr.typ == 'Comment' && options.removeComments) {
54
+ const sourcemap = options.sourcemap ? new SourceMap : null;
55
+ const cache = Object.create(null);
56
+ const result = {
57
+ code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
58
+ ind: 0,
59
+ lin: 1,
60
+ col: 1
61
+ }, errors, function reducer(acc, curr) {
62
+ if (curr.typ == EnumToken.CommentTokenType && options.removeComments) {
38
63
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
39
64
  return acc;
40
65
  }
41
66
  return acc + curr.val;
42
67
  }
43
- return acc + renderToken(curr, options, reducer, errors);
44
- }, 0), errors, stats: {
68
+ return acc + renderToken(curr, options, cache, reducer, errors);
69
+ }, cache), errors, stats: {
45
70
  total: `${(performance.now() - startTime).toFixed(2)}ms`
46
71
  }
47
72
  };
73
+ if (options.output != null) {
74
+ // @ts-ignore
75
+ options.output = options.resolve(options.output, options.cwd).absolute;
76
+ }
77
+ if (sourcemap != null) {
78
+ result.map = sourcemap.toJSON();
79
+ }
80
+ return result;
81
+ }
82
+ function updateSourceMap(node, options, cache, sourcemap, position, str) {
83
+ if ([EnumToken.RuleNodeType, EnumToken.AtRuleNodeType].includes(node.typ)) {
84
+ let src = node.loc?.src ?? '';
85
+ let output = options.output ?? '';
86
+ // if (src !== '') {
87
+ if (!(src in cache)) {
88
+ // @ts-ignore
89
+ cache[src] = options.resolve(src, options.cwd ?? '').relative;
90
+ }
91
+ // }
92
+ if (!(output in cache)) {
93
+ // @ts-ignore
94
+ cache[output] = options.resolve(output, options.cwd).relative;
95
+ }
96
+ // @ts-ignore
97
+ sourcemap.add({ src: cache[output], sta: { ...position } }, {
98
+ ...node.loc,
99
+ // @ts-ignore
100
+ src: options.resolve(cache[src], options.cwd).relative
101
+ });
102
+ }
103
+ update(position, str);
48
104
  }
49
105
  // @ts-ignore
50
- function doRender(data, options, errors, reducer, level = 0, indents = []) {
106
+ function renderAstNode(data, options, sourcemap, position, errors, reducer, cache, level = 0, indents = []) {
51
107
  if (indents.length < level + 1) {
52
108
  indents.push(options.indent.repeat(level));
53
109
  }
@@ -57,46 +113,61 @@ function doRender(data, options, errors, reducer, level = 0, indents = []) {
57
113
  const indent = indents[level];
58
114
  const indentSub = indents[level + 1];
59
115
  switch (data.typ) {
60
- case 'Declaration':
116
+ case EnumToken.DeclarationNodeType:
61
117
  return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
62
- case 'Comment':
63
- case 'CDOCOMM':
118
+ case EnumToken.CommentNodeType:
119
+ case EnumToken.CDOCOMMNodeType:
120
+ if (data.val.startsWith('# sourceMappingURL=')) {
121
+ // ignore sourcemap
122
+ return '';
123
+ }
64
124
  return !options.removeComments || (options.preserveLicense && data.val.startsWith('/*!')) ? data.val : '';
65
- case 'StyleSheet':
125
+ case EnumToken.StyleSheetNodeType:
66
126
  return data.chi.reduce((css, node) => {
67
- const str = doRender(node, options, errors, reducer, level, indents);
127
+ const str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level, indents);
68
128
  if (str === '') {
69
129
  return css;
70
130
  }
71
131
  if (css === '') {
132
+ if (sourcemap != null) {
133
+ updateSourceMap(node, options, cache, sourcemap, position, str);
134
+ }
72
135
  return str;
73
136
  }
137
+ if (sourcemap != null) {
138
+ update(position, options.newLine);
139
+ updateSourceMap(node, options, cache, sourcemap, position, str);
140
+ }
74
141
  return `${css}${options.newLine}${str}`;
75
142
  }, '');
76
- case 'AtRule':
77
- case 'Rule':
78
- if (data.typ == 'AtRule' && !('chi' in data)) {
143
+ case EnumToken.AtRuleNodeType:
144
+ case EnumToken.RuleNodeType:
145
+ if (data.typ == EnumToken.AtRuleNodeType && !('chi' in data)) {
79
146
  return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
80
147
  }
81
148
  // @ts-ignore
82
149
  let children = data.chi.reduce((css, node) => {
83
150
  let str;
84
- if (node.typ == 'Comment') {
151
+ if (node.typ == EnumToken.CommentNodeType) {
85
152
  str = options.removeComments && (!options.preserveLicense || !node.val.startsWith('/*!')) ? '' : node.val;
86
153
  }
87
- else if (node.typ == 'Declaration') {
154
+ else if (node.typ == EnumToken.DeclarationNodeType) {
88
155
  if (node.val.length == 0) {
89
156
  // @ts-ignore
90
- errors.push({ action: 'ignore', message: `render: invalid declaration ${JSON.stringify(node)}`, location: node.loc });
157
+ errors.push({
158
+ action: 'ignore',
159
+ message: `render: invalid declaration ${JSON.stringify(node)}`,
160
+ location: node.loc
161
+ });
91
162
  return '';
92
163
  }
93
164
  str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
94
165
  }
95
- else if (node.typ == 'AtRule' && !('chi' in node)) {
166
+ else if (node.typ == EnumToken.AtRuleNodeType && !('chi' in node)) {
96
167
  str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
97
168
  }
98
169
  else {
99
- str = doRender(node, options, errors, reducer, level + 1, indents);
170
+ str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
100
171
  }
101
172
  if (css === '') {
102
173
  return str;
@@ -109,28 +180,68 @@ function doRender(data, options, errors, reducer, level = 0, indents = []) {
109
180
  if (children.endsWith(';')) {
110
181
  children = children.slice(0, -1);
111
182
  }
112
- if (data.typ == 'AtRule') {
183
+ if (data.typ == EnumToken.AtRuleNodeType) {
113
184
  return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
114
185
  }
115
186
  return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
116
187
  }
117
188
  return '';
118
189
  }
119
- function renderToken(token, options = {}, reducer, errors) {
190
+ function renderToken(token, options = {}, cache = Object.create(null), reducer, errors) {
120
191
  if (reducer == null) {
121
192
  reducer = function (acc, curr) {
122
- if (curr.typ == 'Comment' && options.removeComments) {
193
+ if (curr.typ == EnumToken.CommentTokenType && options.removeComments) {
123
194
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
124
195
  return acc;
125
196
  }
126
197
  return acc + curr.val;
127
198
  }
128
- return acc + renderToken(curr, options, reducer, errors);
199
+ return acc + renderToken(curr, options, cache, reducer, errors);
129
200
  };
130
201
  }
131
202
  switch (token.typ) {
132
- case 'Color':
133
- if (options.minify || options.colorConvert) {
203
+ case EnumToken.ListToken:
204
+ return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
205
+ case EnumToken.BinaryExpressionTokenType:
206
+ if ([EnumToken.Mul, EnumToken.Div].includes(token.op)) {
207
+ let result = '';
208
+ if (token.l.typ == EnumToken.BinaryExpressionTokenType &&
209
+ [EnumToken.Add, EnumToken.Sub].includes(token.l.op)) {
210
+ result = '(' + renderToken(token.l, options, cache) + ')';
211
+ }
212
+ else {
213
+ result = renderToken(token.l, options, cache);
214
+ }
215
+ result += token.op == EnumToken.Mul ? '*' : '/';
216
+ if (token.r.typ == EnumToken.BinaryExpressionTokenType &&
217
+ [EnumToken.Add, EnumToken.Sub].includes(token.r.op)) {
218
+ result += '(' + renderToken(token.r, options, cache) + ')';
219
+ }
220
+ else {
221
+ result += renderToken(token.r, options, cache);
222
+ }
223
+ return result;
224
+ }
225
+ return renderToken(token.l, options, cache) + (token.op == EnumToken.Add ? ' + ' : (token.op == EnumToken.Sub ? ' - ' : (token.op == EnumToken.Mul ? '*' : '/'))) + renderToken(token.r, options, cache);
226
+ case EnumToken.FractionTokenType:
227
+ const fraction = renderToken(token.l) + '/' + renderToken(token.r);
228
+ if (+token.r.val != 0) {
229
+ const value = reduceNumber(+token.l.val / +token.r.val);
230
+ if (value.length <= fraction.length) {
231
+ return value;
232
+ }
233
+ }
234
+ return fraction;
235
+ case EnumToken.Add:
236
+ return ' + ';
237
+ case EnumToken.Sub:
238
+ return ' - ';
239
+ case EnumToken.Mul:
240
+ return '*';
241
+ case EnumToken.Div:
242
+ return '/';
243
+ case EnumToken.ColorTokenType:
244
+ if (options.colorConvert) {
134
245
  if (token.kin == 'lit' && token.val.toLowerCase() == 'currentcolor') {
135
246
  return 'currentcolor';
136
247
  }
@@ -170,54 +281,85 @@ function renderToken(token, options = {}, reducer, errors) {
170
281
  if (token.kin == 'hex' || token.kin == 'lit') {
171
282
  return token.val;
172
283
  }
173
- case 'Start-parens':
174
- if (!('chi' in token)) {
175
- return '(';
284
+ case EnumToken.ParensTokenType:
285
+ case EnumToken.FunctionTokenType:
286
+ case EnumToken.UrlFunctionTokenType:
287
+ case EnumToken.ImageFunctionTokenType:
288
+ case EnumToken.PseudoClassFuncTokenType:
289
+ case EnumToken.TimingFunctionTokenType:
290
+ case EnumToken.TimelineFunctionTokenType:
291
+ if (token.typ == EnumToken.FunctionTokenType &&
292
+ token.val == 'calc' &&
293
+ token.chi.length == 1 &&
294
+ token.chi[0].typ != EnumToken.BinaryExpressionTokenType &&
295
+ token.chi[0].typ != EnumToken.FractionTokenType &&
296
+ token.chi[0].val?.typ != EnumToken.FractionTokenType) {
297
+ // calc(200px) => 200px
298
+ return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache, reducer), '');
176
299
  }
177
- case 'Func':
178
- case 'UrlFunc':
179
- case 'Pseudo-class-func':
180
300
  // @ts-ignore
181
301
  return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce(reducer, '') + ')';
182
- case 'Includes':
302
+ case EnumToken.MatchExpressionTokenType:
303
+ return renderToken(token.l, options, cache, reducer, errors) +
304
+ renderToken({ typ: token.op }, options, cache, reducer, errors) +
305
+ renderToken(token.r, options, cache, reducer, errors) +
306
+ (token.attr ? ' ' + token.attr : '');
307
+ case EnumToken.NameSpaceAttributeTokenType:
308
+ return (token.l == null ? '' : renderToken(token.l, options, cache, reducer, errors) + '|') +
309
+ renderToken(token.r, options, cache, reducer, errors);
310
+ case EnumToken.BlockStartTokenType:
311
+ return '{';
312
+ case EnumToken.BlockEndTokenType:
313
+ return '}';
314
+ case EnumToken.StartParensTokenType:
315
+ return '(';
316
+ case EnumToken.IncludeMatchTokenType:
183
317
  return '~=';
184
- case 'Dash-match':
318
+ case EnumToken.DashMatchTokenType:
185
319
  return '|=';
186
- case 'Lt':
320
+ case EnumToken.StartMatchTokenType:
321
+ return '^=';
322
+ case EnumToken.EndMatchTokenType:
323
+ return '$=';
324
+ case EnumToken.ContainMatchTokenType:
325
+ return '*=';
326
+ case EnumToken.LtTokenType:
187
327
  return '<';
188
- case 'Lte':
328
+ case EnumToken.LteTokenType:
189
329
  return '<=';
190
- case 'Gt':
330
+ case EnumToken.GtTokenType:
191
331
  return '>';
192
- case 'Gte':
332
+ case EnumToken.GteTokenType:
193
333
  return '>=';
194
- case 'End-parens':
334
+ case EnumToken.ColumnCombinatorTokenType:
335
+ return '||';
336
+ case EnumToken.EndParensTokenType:
195
337
  return ')';
196
- case 'Attr-start':
338
+ case EnumToken.AttrStartTokenType:
197
339
  return '[';
198
- case 'Attr-end':
340
+ case EnumToken.AttrEndTokenType:
199
341
  return ']';
200
- case 'Whitespace':
342
+ case EnumToken.WhitespaceTokenType:
201
343
  return ' ';
202
- case 'Colon':
344
+ case EnumToken.ColonTokenType:
203
345
  return ':';
204
- case 'Semi-colon':
346
+ case EnumToken.SemiColonTokenType:
205
347
  return ';';
206
- case 'Comma':
348
+ case EnumToken.CommaTokenType:
207
349
  return ',';
208
- case 'Important':
350
+ case EnumToken.ImportantTokenType:
209
351
  return '!important';
210
- case 'Attr':
352
+ case EnumToken.AttrTokenType:
211
353
  return '[' + token.chi.reduce(reducer, '') + ']';
212
- case 'Time':
213
- case 'Angle':
214
- case 'Length':
215
- case 'Dimension':
216
- case 'Frequency':
217
- case 'Resolution':
218
- let val = reduceNumber(token.val);
354
+ case EnumToken.TimeTokenType:
355
+ case EnumToken.AngleTokenType:
356
+ case EnumToken.LengthTokenType:
357
+ case EnumToken.DimensionTokenType:
358
+ case EnumToken.FrequencyTokenType:
359
+ case EnumToken.ResolutionTokenType:
360
+ let val = token.val.typ == EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
219
361
  let unit = token.unit;
220
- if (token.typ == 'Angle') {
362
+ if (token.typ == EnumToken.AngleTokenType && !val.includes('/')) {
221
363
  const angle = getAngle(token);
222
364
  let v;
223
365
  let value = val + unit;
@@ -262,40 +404,67 @@ function renderToken(token, options = {}, reducer, errors) {
262
404
  }
263
405
  }
264
406
  if (val === '0') {
265
- if (token.typ == 'Time') {
407
+ if (token.typ == EnumToken.TimeTokenType) {
266
408
  return '0s';
267
409
  }
268
- if (token.typ == 'Frequency') {
410
+ if (token.typ == EnumToken.FrequencyTokenType) {
269
411
  return '0Hz';
270
412
  }
271
413
  // @ts-ignore
272
- if (token.typ == 'Resolution') {
414
+ if (token.typ == EnumToken.ResolutionTokenType) {
273
415
  return '0x';
274
416
  }
275
417
  return '0';
276
418
  }
277
- return val + unit;
278
- case 'Perc':
279
- const perc = reduceNumber(token.val);
280
- return options.minify && perc == '0' ? '0' : perc + '%';
281
- case 'Number':
282
- return reduceNumber(token.val);
283
- case 'Comment':
419
+ return val.includes('/') ? val.replace('/', unit + '/') : val + unit;
420
+ case EnumToken.PercentageTokenType:
421
+ const perc = token.val.typ == EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
422
+ return options.minify && perc == '0' ? '0' : (perc.includes('/') ? perc.replace('/', '%/') : perc + '%');
423
+ case EnumToken.NumberTokenType:
424
+ return token.val.typ == EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
425
+ case EnumToken.CommentTokenType:
284
426
  if (options.removeComments && (!options.preserveLicense || !token.val.startsWith('/*!'))) {
285
427
  return '';
286
428
  }
287
- case 'Url-token':
288
- case 'At-rule':
289
- case 'Hash':
290
- case 'Pseudo-class':
291
- case 'Literal':
292
- case 'String':
293
- case 'Iden':
294
- case 'Delim':
429
+ case EnumToken.PseudoClassTokenType:
430
+ // https://www.w3.org/TR/selectors-4/#single-colon-pseudos
431
+ if (token.typ == EnumToken.PseudoClassTokenType && ['::before', '::after', '::first-line', '::first-letter'].includes(token.val)) {
432
+ return token.val.slice(1);
433
+ }
434
+ case EnumToken.UrlTokenTokenType:
435
+ if (token.typ == EnumToken.UrlTokenTokenType) {
436
+ if (options.output != null) {
437
+ if (!('original' in token)) {
438
+ // do not modify original token
439
+ token = { ...token };
440
+ Object.defineProperty(token, 'original', { enumerable: false, writable: false, value: token.val });
441
+ }
442
+ // @ts-ignore
443
+ if (!(token.original in cache)) {
444
+ let output = options.output ?? '';
445
+ const key = output + 'abs';
446
+ if (!(key in cache)) {
447
+ // @ts-ignore
448
+ cache[key] = options.dirname(options.resolve(output, options.cwd).absolute);
449
+ }
450
+ // @ts-ignore
451
+ cache[token.original] = options.resolve(token.original, cache[key]).relative;
452
+ }
453
+ // @ts-ignore
454
+ token.val = cache[token.original];
455
+ }
456
+ }
457
+ case EnumToken.HashTokenType:
458
+ case EnumToken.IdenTokenType:
459
+ case EnumToken.DelimTokenType:
460
+ case EnumToken.AtRuleTokenType:
461
+ case EnumToken.StringTokenType:
462
+ case EnumToken.LiteralTokenType:
463
+ case EnumToken.DashedIdenTokenType:
295
464
  return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
296
465
  }
297
466
  errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
298
467
  return '';
299
468
  }
300
469
 
301
- export { colorsFunc, render, renderToken };
470
+ export { colorsFunc, doRender, reduceNumber, renderToken };
@@ -0,0 +1,37 @@
1
+ // from https://github.com/Rich-Harris/vlq/tree/master
2
+ // credit: Rich Harris
3
+ const integer_to_char = {};
4
+ let i = 0;
5
+ for (const char of 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') {
6
+ integer_to_char[i++] = char;
7
+ }
8
+ function encode(value) {
9
+ if (typeof value === 'number') {
10
+ return encode_integer(value);
11
+ }
12
+ let result = '';
13
+ for (let i = 0; i < value.length; i += 1) {
14
+ result += encode_integer(value[i]);
15
+ }
16
+ return result;
17
+ }
18
+ function encode_integer(num) {
19
+ let result = '';
20
+ if (num < 0) {
21
+ num = (-num << 1) | 1;
22
+ }
23
+ else {
24
+ num <<= 1;
25
+ }
26
+ do {
27
+ let clamped = num & 31;
28
+ num >>>= 5;
29
+ if (num > 0) {
30
+ clamped |= 32;
31
+ }
32
+ result += integer_to_char[clamped];
33
+ } while (num > 0);
34
+ return result;
35
+ }
36
+
37
+ export { encode };
@@ -0,0 +1,58 @@
1
+ import { encode } from './lib/encode.js';
2
+
3
+ class SourceMap {
4
+ #version = 3;
5
+ #sources = [];
6
+ #map = new Map;
7
+ #line = -1;
8
+ lastLocation = null;
9
+ add(source, original) {
10
+ if (original.src !== '') {
11
+ if (!this.#sources.includes(original.src)) {
12
+ this.#sources.push(original.src);
13
+ }
14
+ const line = source.sta.lin - 1;
15
+ let record;
16
+ if (line > this.#line) {
17
+ this.#line = line;
18
+ }
19
+ if (!this.#map.has(line)) {
20
+ record = [Math.max(0, source.sta.col - 1), this.#sources.indexOf(original.src), original.sta.lin - 1, original.sta.col - 1];
21
+ this.#map.set(line, [record]);
22
+ }
23
+ else {
24
+ const arr = this.#map.get(line);
25
+ record = [Math.max(0, source.sta.col - 1 - arr[0][0]), this.#sources.indexOf(original.src) - arr[0][1], original.sta.lin - 1, original.sta.col - 1];
26
+ arr.push(record);
27
+ }
28
+ if (this.lastLocation != null) {
29
+ record[2] -= this.lastLocation.sta.lin - 1;
30
+ record[3] -= this.lastLocation.sta.col - 1;
31
+ }
32
+ this.lastLocation = original;
33
+ }
34
+ }
35
+ toUrl() {
36
+ // /*# sourceMappingURL = ${url} */
37
+ return `data:application/json,${encodeURIComponent(JSON.stringify(this.toJSON()))}`;
38
+ }
39
+ toJSON() {
40
+ const mappings = [];
41
+ let i = 0;
42
+ for (; i <= this.#line; i++) {
43
+ if (!this.#map.has(i)) {
44
+ mappings.push('');
45
+ }
46
+ else {
47
+ mappings.push(this.#map.get(i).reduce((acc, curr) => acc + (acc === '' ? '' : ',') + encode(curr), ''));
48
+ }
49
+ }
50
+ return {
51
+ version: this.#version,
52
+ sources: this.#sources.slice(),
53
+ mappings: mappings.join(';')
54
+ };
55
+ }
56
+ }
57
+
58
+ export { SourceMap };