postcss-normalize-string 9.0.3 → 9.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postcss-normalize-string",
3
- "version": "9.0.3",
3
+ "version": "9.0.5",
4
4
  "description": "Normalize wrapping quotes for CSS string literals.",
5
5
  "exports": {
6
6
  ".": {
@@ -33,7 +33,7 @@
33
33
  "url": "git+https://github.com/cssnano/cssnano.git"
34
34
  },
35
35
  "dependencies": {
36
- "postcss-value-parser": "^4.2.0"
36
+ "@csstools/css-tokenizer": "^4.0.2"
37
37
  },
38
38
  "bugs": {
39
39
  "url": "https://github.com/cssnano/cssnano/issues"
package/src/index.js CHANGED
@@ -1,233 +1,311 @@
1
- import valueParser from 'postcss-value-parser';
2
-
3
- /*
4
- * Constants (parser usage)
5
- */
1
+ import { tokenize, TokenType } from '@csstools/css-tokenizer';
6
2
 
7
3
  const SINGLE_QUOTE = "'".charCodeAt(0);
8
4
  const DOUBLE_QUOTE = '"'.charCodeAt(0);
9
5
  const BACKSLASH = '\\'.charCodeAt(0);
10
6
  const NEWLINE = '\n'.charCodeAt(0);
11
- const SPACE = ' '.charCodeAt(0);
12
7
  const FEED = '\f'.charCodeAt(0);
13
- const TAB = '\t'.charCodeAt(0);
14
8
  const CR = '\r'.charCodeAt(0);
9
+ const SPACE = ' '.charCodeAt(0);
10
+ const TAB = '\t'.charCodeAt(0);
15
11
 
16
- const WORD_END = /[ \n\t\r\f'"\\]/g;
17
-
18
- /*
19
- * Constants (node type strings)
12
+ /**
13
+ * @param {number} code
14
+ * @return {boolean}
20
15
  */
16
+ function isHexDigit(code) {
17
+ return (
18
+ (code >= 0x30 && code <= 0x39) ||
19
+ (code >= 0x41 && code <= 0x46) ||
20
+ (code >= 0x61 && code <= 0x66)
21
+ );
22
+ }
21
23
 
22
- const C_STRING = 'string';
23
- const C_ESCAPED_SINGLE_QUOTE = 'escapedSingleQuote';
24
- const C_ESCAPED_DOUBLE_QUOTE = 'escapedDoubleQuote';
25
- const C_SINGLE_QUOTE = 'singleQuote';
26
- const C_DOUBLE_QUOTE = 'doubleQuote';
27
- const C_NEWLINE = 'newline';
28
- const C_SINGLE = 'single';
24
+ /**
25
+ * Return the index just past the hex digits of the escape whose backslash is at `pos`.
26
+ * CSS Syntax 3 allows one to six hex digits.
27
+ *
28
+ * @param {string} inner
29
+ * @param {number} pos
30
+ * @return {number}
31
+ */
32
+ function getHexDigitsEnd(inner, pos) {
33
+ const limit = Math.min(pos + 7, inner.length);
34
+ let end = pos + 2;
35
+ while (end < limit && isHexDigit(inner.charCodeAt(end))) {
36
+ end++;
37
+ }
38
+ return end;
39
+ }
29
40
 
30
- /*
31
- * Literals
41
+ /**
42
+ * Return the length of the whitespace at `pos` (CRLF counts as one newline), or 0.
43
+ *
44
+ * @param {string} inner
45
+ * @param {number} pos
46
+ * @return {number}
32
47
  */
48
+ function getWhitespaceLength(inner, pos) {
49
+ const code = inner.charCodeAt(pos);
50
+ if (code === CR) {
51
+ return inner.charCodeAt(pos + 1) === NEWLINE ? 2 : 1;
52
+ }
53
+ return code === SPACE || code === TAB || code === NEWLINE || code === FEED
54
+ ? 1
55
+ : 0;
56
+ }
33
57
 
34
- const L_SINGLE_QUOTE = `'`;
35
- const L_DOUBLE_QUOTE = `"`;
36
- const L_NEWLINE = `\\\n`;
58
+ /**
59
+ * Return the space that keeps an open hex escape from absorbing the code point at `pos`.
60
+ *
61
+ * @param {string} inner
62
+ * @param {number} pos
63
+ * @param {boolean} acceptsMoreDigits
64
+ * @return {string}
65
+ */
66
+ function getHexEscapeDelimiter(inner, pos, acceptsMoreDigits) {
67
+ return getWhitespaceLength(inner, pos) > 0 ||
68
+ (acceptsMoreDigits && isHexDigit(inner.charCodeAt(pos)))
69
+ ? ' '
70
+ : '';
71
+ }
37
72
 
38
- /*
39
- * Parser nodes
73
+ /**
74
+ * Verify whether a string token has matching delimiters and balanced trailing escapes.
75
+ *
76
+ * @param {string} value
77
+ * @return {boolean}
40
78
  */
79
+ function isClosedString(value) {
80
+ const len = value.length;
81
+ if (len < 2 || value.charCodeAt(len - 1) !== value.charCodeAt(0)) {
82
+ return false;
83
+ }
41
84
 
42
- const T_ESCAPED_SINGLE_QUOTE = { type: C_ESCAPED_SINGLE_QUOTE, value: `\\'` };
43
- const T_ESCAPED_DOUBLE_QUOTE = { type: C_ESCAPED_DOUBLE_QUOTE, value: `\\"` };
44
- const T_SINGLE_QUOTE = { type: C_SINGLE_QUOTE, value: L_SINGLE_QUOTE };
45
- const T_DOUBLE_QUOTE = { type: C_DOUBLE_QUOTE, value: L_DOUBLE_QUOTE };
46
- const T_NEWLINE = { type: C_NEWLINE, value: L_NEWLINE };
85
+ let backslashes = 0;
86
+ for (
87
+ let index = len - 2;
88
+ index >= 0 && value.charCodeAt(index) === BACKSLASH;
89
+ index--
90
+ ) {
91
+ backslashes++;
92
+ }
93
+
94
+ return backslashes % 2 === 0;
95
+ }
47
96
 
48
- /** @typedef {typeof T_ESCAPED_SINGLE_QUOTE | typeof T_ESCAPED_DOUBLE_QUOTE | typeof T_SINGLE_QUOTE | typeof T_NEWLINE} StringAstNode */
49
97
  /**
50
- * @typedef {{nodes: StringAstNode[],
51
- * types: {escapedSingleQuote: number, escapedDoubleQuote: number, singleQuote: number, doubleQuote: number},
52
- * quotes: boolean}} StringAst
98
+ * Return the length of an escaped line continuation, or 0 if not a newline escape.
99
+ *
100
+ * @param {string} inner
101
+ * @param {number} pos
102
+ * @param {number} len
103
+ * @return {number}
53
104
  */
105
+ function getEscapedNewlineLength(inner, pos, len) {
106
+ const next = inner.charCodeAt(pos + 1);
107
+ if (next === NEWLINE || next === FEED) {
108
+ return 2;
109
+ }
110
+ if (next === CR) {
111
+ return pos + 2 < len && inner.charCodeAt(pos + 2) === NEWLINE ? 3 : 2;
112
+ }
113
+ return 0;
114
+ }
54
115
 
55
116
  /**
56
- * @param {StringAst} ast
57
- * @return {string}
117
+ * Scan string contents to count quotes and detect escaped newlines or redundant escapes.
118
+ *
119
+ * @param {string} inner
120
+ * @param {string} currentQuote
121
+ * @return {{ singleCount: number, doubleCount: number, hasEscapedNewline: boolean, hasRedundantEscape: boolean }}
58
122
  */
59
- function stringify(ast) {
60
- let str = '';
61
- for (const { value } of ast.nodes) {
62
- // Collapse multiple line strings automatically
63
- if (value !== L_NEWLINE) {
64
- str += value;
123
+ function scanQuotes(inner, currentQuote) {
124
+ const len = inner.length;
125
+ let singleCount = 0;
126
+ let doubleCount = 0;
127
+ let hasEscapedNewline = false;
128
+ let hasRedundantEscape = false;
129
+ let pos = 0;
130
+
131
+ while (pos < len) {
132
+ const code = inner.charCodeAt(pos);
133
+ if (code !== BACKSLASH) {
134
+ if (code === SINGLE_QUOTE) {
135
+ singleCount++;
136
+ } else if (code === DOUBLE_QUOTE) {
137
+ doubleCount++;
138
+ }
139
+ pos++;
140
+ continue;
141
+ }
142
+ const newlineLen = getEscapedNewlineLength(inner, pos, len);
143
+ if (newlineLen > 0) {
144
+ hasEscapedNewline = true;
145
+ pos += newlineLen;
146
+ continue;
65
147
  }
148
+ const next = inner.charCodeAt(pos + 1);
149
+ if (next === SINGLE_QUOTE) {
150
+ singleCount++;
151
+ hasRedundantEscape ||= currentQuote === '"';
152
+ } else if (next === DOUBLE_QUOTE) {
153
+ doubleCount++;
154
+ hasRedundantEscape ||= currentQuote === "'";
155
+ }
156
+ pos += 2;
157
+ }
158
+
159
+ return { singleCount, doubleCount, hasEscapedNewline, hasRedundantEscape };
160
+ }
161
+
162
+ /**
163
+ * Determine the optimal wrapping quote delimiter.
164
+ *
165
+ * @param {number} singleCount
166
+ * @param {number} doubleCount
167
+ * @param {'single' | 'double'} preferredQuote
168
+ * @param {string} currentQuote
169
+ * @return {string}
170
+ */
171
+ function selectTargetQuote(
172
+ singleCount,
173
+ doubleCount,
174
+ preferredQuote,
175
+ currentQuote
176
+ ) {
177
+ if (singleCount > doubleCount) {
178
+ return '"';
179
+ }
180
+ if (doubleCount > singleCount) {
181
+ return "'";
182
+ }
183
+ if (singleCount === 0 && doubleCount === 0) {
184
+ return preferredQuote === 'single' ? "'" : '"';
66
185
  }
67
- return str;
186
+ return currentQuote;
68
187
  }
69
188
 
70
189
  /**
71
- * @param {string} str
72
- * @return {StringAst}
190
+ * Reconstruct string with the target quote, collapsing newlines and updating escapes.
191
+ *
192
+ * @param {string} inner
193
+ * @param {string} targetQuote
194
+ * @return {string}
73
195
  */
74
- function parse(str) {
75
- let code, next, value;
196
+ function reconstructString(inner, targetQuote) {
197
+ const len = inner.length;
198
+ const targetCode = targetQuote.charCodeAt(0);
199
+ const otherQuote = targetQuote === "'" ? '"' : "'";
200
+ const otherCode = otherQuote.charCodeAt(0);
201
+ const escapedTargetQuote = '\\' + targetQuote;
202
+ const chunks = [targetQuote];
203
+ let cursor = 0;
76
204
  let pos = 0;
77
- const len = str.length;
78
-
79
- /** @type StringAst */
80
- const ast = {
81
- nodes: [],
82
- types: {
83
- escapedSingleQuote: 0,
84
- escapedDoubleQuote: 0,
85
- singleQuote: 0,
86
- doubleQuote: 0,
87
- },
88
- quotes: false,
89
- };
205
+ // A hex escape without a whitespace terminator would absorb a following hex
206
+ // digit or whitespace once the line continuations after it are removed.
207
+ let openHexEnd = -1;
208
+ let openHexIsShort = false;
90
209
 
91
210
  while (pos < len) {
92
- code = str.charCodeAt(pos);
93
-
94
- switch (code) {
95
- case SPACE:
96
- case TAB:
97
- case CR:
98
- case FEED:
99
- next = pos;
100
-
101
- do {
102
- next += 1;
103
- code = str.charCodeAt(next);
104
- } while (
105
- code === SPACE ||
106
- code === NEWLINE ||
107
- code === TAB ||
108
- code === CR ||
109
- code === FEED
110
- );
111
-
112
- ast.nodes.push({
113
- type: 'space',
114
- value: str.slice(pos, next),
115
- });
116
- pos = next - 1;
117
- break;
118
- case SINGLE_QUOTE:
119
- ast.nodes.push(T_SINGLE_QUOTE);
120
- ast.types[C_SINGLE_QUOTE]++;
121
- ast.quotes = true;
122
- break;
123
- case DOUBLE_QUOTE:
124
- ast.nodes.push(T_DOUBLE_QUOTE);
125
- ast.types[C_DOUBLE_QUOTE]++;
126
- ast.quotes = true;
127
- break;
128
- case BACKSLASH:
129
- next = pos + 1;
130
-
131
- if (str.charCodeAt(next) === SINGLE_QUOTE) {
132
- ast.nodes.push(T_ESCAPED_SINGLE_QUOTE);
133
- ast.types[C_ESCAPED_SINGLE_QUOTE]++;
134
- ast.quotes = true;
135
- pos = next;
136
- break;
137
- } else if (str.charCodeAt(next) === DOUBLE_QUOTE) {
138
- ast.nodes.push(T_ESCAPED_DOUBLE_QUOTE);
139
- ast.types[C_ESCAPED_DOUBLE_QUOTE]++;
140
- ast.quotes = true;
141
- pos = next;
142
- break;
143
- } else if (str.charCodeAt(next) === NEWLINE) {
144
- ast.nodes.push(T_NEWLINE);
145
- pos = next;
146
- break;
211
+ const code = inner.charCodeAt(pos);
212
+ if (code === BACKSLASH) {
213
+ const newlineLen = getEscapedNewlineLength(inner, pos, len);
214
+ if (newlineLen > 0) {
215
+ if (pos > cursor) {
216
+ chunks.push(inner.slice(cursor, pos));
147
217
  }
148
- /*
149
- * We need to fall through here to handle the token as
150
- * a whole word. The missing 'break' is intentional.
151
- */
152
- // oxlint-disable-next-line no-fallthrough
153
- default:
154
- WORD_END.lastIndex = pos + 1;
155
- WORD_END.test(str);
156
-
157
- if (WORD_END.lastIndex === 0) {
158
- next = len - 1;
159
- } else {
160
- next = WORD_END.lastIndex - 2;
218
+ const followsOpenHex = pos === openHexEnd;
219
+ pos += newlineLen;
220
+ cursor = pos;
221
+ if (followsOpenHex) {
222
+ openHexEnd = pos;
223
+ chunks.push(getHexEscapeDelimiter(inner, pos, openHexIsShort));
161
224
  }
225
+ continue;
226
+ }
162
227
 
163
- value = str.slice(pos, next + 1);
228
+ const next = inner.charCodeAt(pos + 1);
229
+ if (next === otherCode) {
230
+ if (pos > cursor) {
231
+ chunks.push(inner.slice(cursor, pos));
232
+ }
233
+ chunks.push(otherQuote);
234
+ pos += 2;
235
+ cursor = pos;
236
+ continue;
237
+ }
164
238
 
165
- ast.nodes.push({
166
- type: C_STRING,
167
- value,
168
- });
239
+ if (isHexDigit(next)) {
240
+ const digitsEnd = getHexDigitsEnd(inner, pos);
241
+ const terminatorLen = getWhitespaceLength(inner, digitsEnd);
242
+ if (terminatorLen === 0) {
243
+ openHexEnd = digitsEnd;
244
+ openHexIsShort = digitsEnd - pos < 7;
245
+ }
246
+ pos = digitsEnd + terminatorLen;
247
+ continue;
248
+ }
249
+
250
+ pos += 2;
251
+ continue;
252
+ }
169
253
 
170
- pos = next;
254
+ if (code === targetCode) {
255
+ if (pos > cursor) {
256
+ chunks.push(inner.slice(cursor, pos));
257
+ }
258
+ chunks.push(escapedTargetQuote);
259
+ pos++;
260
+ cursor = pos;
261
+ continue;
171
262
  }
263
+
172
264
  pos++;
173
265
  }
174
266
 
175
- return ast;
267
+ if (cursor < len) {
268
+ chunks.push(inner.slice(cursor));
269
+ }
270
+ chunks.push(targetQuote);
271
+ return chunks.join('');
176
272
  }
177
273
 
178
274
  /**
179
- * @param {valueParser.StringNode} node
180
- * @param {StringAst} ast
181
- * @return {void}
275
+ * Normalizes quotes and line continuations in a single closed CSS string token.
276
+ *
277
+ * @param {string} raw
278
+ * @param {'single' | 'double'} preferredQuote
279
+ * @return {string}
182
280
  */
183
- function changeWrappingQuotes(node, ast) {
184
- const { types } = ast;
281
+ function normalizeString(raw, preferredQuote) {
282
+ const currentQuote = raw[0];
283
+ const targetDelimiter = preferredQuote === 'single' ? "'" : '"';
284
+ const inner = raw.slice(1, -1);
185
285
 
186
- if (types[C_SINGLE_QUOTE] || types[C_DOUBLE_QUOTE]) {
187
- return;
286
+ if (currentQuote === targetDelimiter && !inner.includes('\\')) {
287
+ return raw;
188
288
  }
189
289
 
190
- if (
191
- node.quote === L_SINGLE_QUOTE &&
192
- types[C_ESCAPED_SINGLE_QUOTE] > 0 &&
193
- !types[C_ESCAPED_DOUBLE_QUOTE]
194
- ) {
195
- node.quote = L_DOUBLE_QUOTE;
196
- }
290
+ const { singleCount, doubleCount, hasEscapedNewline, hasRedundantEscape } =
291
+ scanQuotes(inner, currentQuote);
292
+
293
+ const targetQuote = selectTargetQuote(
294
+ singleCount,
295
+ doubleCount,
296
+ preferredQuote,
297
+ currentQuote
298
+ );
197
299
 
198
300
  if (
199
- node.quote === L_DOUBLE_QUOTE &&
200
- types[C_ESCAPED_DOUBLE_QUOTE] > 0 &&
201
- !types[C_ESCAPED_SINGLE_QUOTE]
301
+ targetQuote === currentQuote &&
302
+ !hasEscapedNewline &&
303
+ !hasRedundantEscape
202
304
  ) {
203
- node.quote = L_SINGLE_QUOTE;
305
+ return raw;
204
306
  }
205
307
 
206
- ast.nodes = changeChildQuotes(ast.nodes, node.quote);
207
- }
208
- /**
209
- * @param {StringAstNode[]} childNodes
210
- * @param {string} parentQuote
211
- * @return {StringAstNode[]}
212
- */
213
- function changeChildQuotes(childNodes, parentQuote) {
214
- const updatedChildren = [];
215
- for (const child of childNodes) {
216
- if (
217
- child.type === C_ESCAPED_DOUBLE_QUOTE &&
218
- parentQuote === L_SINGLE_QUOTE
219
- ) {
220
- updatedChildren.push(T_DOUBLE_QUOTE);
221
- } else if (
222
- child.type === C_ESCAPED_SINGLE_QUOTE &&
223
- parentQuote === L_DOUBLE_QUOTE
224
- ) {
225
- updatedChildren.push(T_SINGLE_QUOTE);
226
- } else {
227
- updatedChildren.push(child);
228
- }
229
- }
230
- return updatedChildren;
308
+ return reconstructString(inner, targetQuote);
231
309
  }
232
310
 
233
311
  /**
@@ -236,29 +314,18 @@ function changeChildQuotes(childNodes, parentQuote) {
236
314
  * @return {string}
237
315
  */
238
316
  function normalize(value, preferredQuote) {
239
- if (!value || !value.length) {
240
- return value;
317
+ const chunks = [];
318
+ let cursor = 0;
319
+ for (const [type, raw, start, end] of tokenize({ css: value })) {
320
+ if (type !== TokenType.String || !isClosedString(raw)) continue;
321
+ const normalized = normalizeString(raw, preferredQuote);
322
+ if (normalized === raw) continue;
323
+ chunks.push(value.slice(cursor, start), normalized);
324
+ cursor = end + 1;
241
325
  }
242
-
243
- return valueParser(value)
244
- .walk((child) => {
245
- if (child.type !== C_STRING) {
246
- return;
247
- }
248
-
249
- const ast = parse(child.value);
250
-
251
- if (ast.quotes) {
252
- changeWrappingQuotes(child, ast);
253
- } else if (preferredQuote === C_SINGLE) {
254
- child.quote = L_SINGLE_QUOTE;
255
- } else {
256
- child.quote = L_DOUBLE_QUOTE;
257
- }
258
-
259
- child.value = stringify(ast);
260
- })
261
- .toString();
326
+ if (cursor === 0) return value;
327
+ chunks.push(value.slice(cursor));
328
+ return chunks.join('');
262
329
  }
263
330
 
264
331
  /**
@@ -268,28 +335,30 @@ function normalize(value, preferredQuote) {
268
335
  * @return {string}
269
336
  */
270
337
  function minify(original, cache, preferredQuote) {
271
- const key = original + '|' + preferredQuote;
272
- if (cache.has(key)) {
273
- return /** @type {string} */ (cache.get(key));
338
+ if (!original || (!original.includes("'") && !original.includes('"'))) {
339
+ return original;
340
+ }
341
+ if (cache.has(original)) {
342
+ return /** @type {string} */ (cache.get(original));
274
343
  }
275
344
  const newValue = normalize(original, preferredQuote);
276
- cache.set(key, newValue);
345
+ cache.set(original, newValue);
277
346
  return newValue;
278
347
  }
279
348
 
349
+ /** @param {import('postcss').Declaration} decl @param {string} value */
350
+ function assignValue(decl, value) {
351
+ decl.value = value;
352
+ if (decl.raws.value?.raw) decl.raws.value = { raw: value, value };
353
+ }
354
+
280
355
  /** @typedef {{preferredQuote?: 'double' | 'single'}} Options */
281
356
  /**
282
357
  * @param {Options} opts
283
358
  * @return {import('postcss').Plugin}
284
359
  */
285
360
  function pluginCreator(opts) {
286
- const { preferredQuote } = Object.assign(
287
- {},
288
- {
289
- preferredQuote: 'double',
290
- },
291
- opts
292
- );
361
+ const { preferredQuote = 'double' } = opts ?? {};
293
362
 
294
363
  return {
295
364
  postcssPlugin: 'postcss-normalize-string',
@@ -305,11 +374,19 @@ function pluginCreator(opts) {
305
374
  case 'rule':
306
375
  node.selector = minify(node.selector, cache, preferredQuote);
307
376
  break;
308
- case 'decl':
309
- node.value = minify(node.value, cache, preferredQuote);
377
+ case 'decl': {
378
+ const rawValue = node.raws.value;
379
+ const value =
380
+ rawValue?.value === node.value
381
+ ? (rawValue.raw ?? node.value)
382
+ : node.value;
383
+ assignValue(node, minify(value, cache, preferredQuote));
310
384
  break;
385
+ }
311
386
  case 'atrule':
312
- node.params = minify(node.params, cache, preferredQuote);
387
+ if (node.name.toLowerCase() !== 'charset') {
388
+ node.params = minify(node.params, cache, preferredQuote);
389
+ }
313
390
  break;
314
391
  }
315
392
  });
package/types/index.d.ts CHANGED
@@ -1,30 +1,3 @@
1
- declare const T_ESCAPED_SINGLE_QUOTE: {
2
- type: string;
3
- value: string;
4
- };
5
- declare const T_ESCAPED_DOUBLE_QUOTE: {
6
- type: string;
7
- value: string;
8
- };
9
- declare const T_SINGLE_QUOTE: {
10
- type: string;
11
- value: string;
12
- };
13
- declare const T_NEWLINE: {
14
- type: string;
15
- value: string;
16
- };
17
- export type StringAstNode = typeof T_ESCAPED_SINGLE_QUOTE | typeof T_ESCAPED_DOUBLE_QUOTE | typeof T_SINGLE_QUOTE | typeof T_NEWLINE;
18
- export type StringAst = {
19
- nodes: StringAstNode[];
20
- types: {
21
- escapedSingleQuote: number;
22
- escapedDoubleQuote: number;
23
- singleQuote: number;
24
- doubleQuote: number;
25
- };
26
- quotes: boolean;
27
- };
28
1
  export type Options = {
29
2
  preferredQuote?: 'double' | 'single';
30
3
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAyCA,QAAA,MAAM,sBAAsB;;;CAAiD,CAAC;AAC9E,QAAA,MAAM,sBAAsB;;;CAAiD,CAAC;AAC9E,QAAA,MAAM,cAAc;;;CAAkD,CAAC;AAEvE,QAAA,MAAM,SAAS;;;CAAwC,CAAC;AAEpD,YAAoH,aAAa,GAAvH,OAAO,sBAAsB,GAAG,OAAO,sBAAsB,GAAG,OAAO,cAAc,GAAG,OAAO,SAAS,CAAe;AAElI,YAE6B,SAAS,GAF5B;IAAC,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC;IAC1G,MAAM,EAAE,OAAO,CAAA;CAAC,CAAW;AAoOrC,YAAkD,OAAO,GAA/C;IAAC,cAAc,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAC,CAAS;AAA7D,gEAAgE;AAChE;;;GAGG;AACH,iBAAS,aAAa,CAAC,IAAI,EAHhB,OAGgB,GAFf,OAAO,SAAS,EAAE,MAAM,CAmCnC;kBAjCQ,aAAa;iBAkCX,IAAI;;AAEf,QAAA,MAAM,aAAa,sBAAgB,CAAC;AAEpC,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAkWI,YAAkD,OAAO,GAA/C;IAAC,cAAc,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAC,CAAS;AAA7D,gEAAgE;AAChE;;;GAGG;AACH,iBAAS,aAAa,CAAC,IAAI,EAHhB,OAGgB,GAFf,OAAO,SAAS,EAAE,MAAM,CAqCnC;kBAnCQ,aAAa;iBAoCX,IAAI;;AAEf,QAAA,MAAM,aAAa,sBAAgB,CAAC;AAEpC,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,CAAC"}