@cloudpss/template 0.6.14 → 0.6.16

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,121 @@
1
+ import { unwrapFromVmValue } from '@mirascript/mirascript';
2
+ import { buildError } from './builder.js';
3
+ import type { TemplateFunction, TemplateOptions } from './index.js';
4
+ import { parseTemplate } from './parser.js';
5
+ import {
6
+ hasOwn,
7
+ isError,
8
+ isArrayBuffer,
9
+ copyArrayBuffer,
10
+ stringify,
11
+ toString,
12
+ isArrayBufferView,
13
+ isArray,
14
+ } from './utils.js';
15
+
16
+ /** 模板序列号 */
17
+ let seq = 0;
18
+
19
+ const $init = [unwrapFromVmValue] as const;
20
+ const $unwrapFromVmValue = 0;
21
+
22
+ /** 创建模板 */
23
+ export class TemplateCompiler {
24
+ constructor(
25
+ readonly template: unknown,
26
+ readonly options: Required<TemplateOptions>,
27
+ ) {}
28
+ private readonly $: unknown[] = [...$init];
29
+ /** 放入 $,返回索引 */
30
+ private use(value: unknown): number {
31
+ this.$.push(value);
32
+ return this.$.length - 1;
33
+ }
34
+ /** 构建数组 */
35
+ private buildArray(arr: unknown[]): string {
36
+ let result = '[';
37
+ for (let i = 0, len = arr.length; i < len; i++) {
38
+ result += this.buildValue(arr[i]);
39
+ result += ',\n';
40
+ }
41
+ result += ']';
42
+ return result;
43
+ }
44
+ /** 构建 ArrayBuffer */
45
+ private buildArrayBuffer(buffer: ArrayBuffer | SharedArrayBuffer): string {
46
+ const copy = copyArrayBuffer(buffer, 0);
47
+ return `$[${this.use(copy)}].slice(0)`;
48
+ }
49
+ /** 构建 ArrayBufferView */
50
+ private buildArrayBufferView(view: ArrayBufferView): string {
51
+ const copy = copyArrayBuffer(view.buffer, view.byteOffset, view.byteLength);
52
+ return `new ${view.constructor.name}($[${this.use(copy)}].slice(0))`;
53
+ }
54
+ /** 构建可能为模板的字符串 */
55
+ private buildTemplate(value: string): string {
56
+ const template = parseTemplate(value);
57
+ if (typeof template == 'string') {
58
+ return stringify(template);
59
+ } else {
60
+ return `$[${$unwrapFromVmValue}]($[${this.use(template.value)}](context))`;
61
+ }
62
+ }
63
+ /** 构建对象 */
64
+ private buildObject(obj: Record<string, unknown>): string {
65
+ let result = '{';
66
+ for (const key in obj) {
67
+ if (!hasOwn(obj, key)) continue;
68
+ result += '[';
69
+ if (this.options.objectKeyMode === 'ignore') {
70
+ result += stringify(key);
71
+ } else {
72
+ result += this.buildTemplate(key);
73
+ }
74
+ result += ']:';
75
+ const value = obj[key];
76
+ result += this.buildValue(value);
77
+ result += ',\n';
78
+ }
79
+ result += '}';
80
+ return result;
81
+ }
82
+ /** 构建值 */
83
+ private buildValue(value: unknown): string {
84
+ if (value === null) return 'null';
85
+ if (value === undefined) return 'undefined';
86
+ if (value === true) return 'true';
87
+ if (value === false) return 'false';
88
+ if (typeof value == 'function') return 'undefined';
89
+ if (typeof value == 'symbol') return 'undefined';
90
+ if (typeof value == 'bigint') return `${value}n`;
91
+ if (typeof value == 'number') return String(value);
92
+ if (typeof value == 'string') return this.buildTemplate(value);
93
+ /* c8 ignore next */
94
+ if (typeof value != 'object') throw new Error(`Unsupported value: ${toString(value)}`);
95
+ if (value instanceof Date) return `new Date(${value.getTime()})`;
96
+ if (value instanceof RegExp) return value.toString();
97
+ if (isError(value)) return buildError(value);
98
+ if (isArray(value)) return this.buildArray(value);
99
+ if (isArrayBuffer(value)) return this.buildArrayBuffer(value);
100
+ if (isArrayBufferView(value)) return this.buildArrayBufferView(value);
101
+ return this.buildObject(value as Record<string, unknown>);
102
+ }
103
+ /** 构建模板 */
104
+ build(): TemplateFunction {
105
+ const source = this.buildValue(this.template);
106
+ try {
107
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval, @typescript-eslint/no-unsafe-call
108
+ const result = new Function(
109
+ '$',
110
+ [
111
+ `//# sourceURL=cloudpss-template[${seq++}]`, // sourceURL 用于调试
112
+ `return (context) => (${source});`,
113
+ ].join('\n'),
114
+ )(this.$) as TemplateFunction;
115
+ return result;
116
+ /* c8 ignore next 3 */
117
+ } catch (e) {
118
+ throw new Error(`Failed to compile template: ${source}\n${(e as Error).message}`, { cause: e });
119
+ }
120
+ }
121
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,60 @@
1
- export { parseTemplate, parseInterpolation } from './parser.js';
2
- export type { Template, FormulaTemplate, InterpolationTemplate } from './parser.js';
3
- export { template } from './template/index.js';
4
- export type { TemplateFunction, TemplateOptions } from './template/index.js';
1
+ import type { VmContext } from '@mirascript/mirascript';
2
+ import { TemplateCompiler } from './compiler.js';
3
+
4
+ export {
5
+ type VmContext,
6
+ VmError,
7
+ VmExtern,
8
+ VmModule,
9
+ VmFunction,
10
+ type VmAny,
11
+ type VmArray,
12
+ type VmConst,
13
+ type VmImmutable,
14
+ type VmPrimitive,
15
+ type VmScript,
16
+ type VmRecord,
17
+ type VmUninitialized,
18
+ type VmValue,
19
+ createVmContext,
20
+ isVmContext,
21
+ isVmExtern,
22
+ isVmModule,
23
+ isVmFunction,
24
+ isVmValue,
25
+ isVmAny,
26
+ isVmArray,
27
+ isVmCallable,
28
+ isVmConst,
29
+ isVmImmutable,
30
+ isVmPrimitive,
31
+ isVmRecord,
32
+ isVmScript,
33
+ isVmWrapper,
34
+ wrapToVmValue,
35
+ unwrapFromVmValue,
36
+ configCheckpoint,
37
+ } from '@mirascript/mirascript';
38
+
39
+ /** 模板选项 */
40
+ export interface TemplateOptions {
41
+ /**
42
+ * 对 object key 的处理方式
43
+ * - `template` 使用模板进行插值
44
+ * - `ignore` 原样输出
45
+ * @default 'template'
46
+ */
47
+ objectKeyMode?: 'template' | 'ignore';
48
+ }
49
+
50
+ /** 已编译的模板函数 */
51
+ export type TemplateFunction<T = unknown> = (context?: VmContext) => T;
52
+
53
+ /** 创建模板 */
54
+ export function template<T = unknown>(template: T, options: TemplateOptions = {}): TemplateFunction<T> {
55
+ const opt: Required<TemplateOptions> = {
56
+ objectKeyMode: 'template',
57
+ ...options,
58
+ };
59
+ return new TemplateCompiler(template, opt).build() as TemplateFunction<T>;
60
+ }
package/src/parser.ts CHANGED
@@ -1,173 +1,41 @@
1
- /** 公式模板 */
2
- export type FormulaTemplate = {
3
- type: 'formula';
4
- value: string;
5
- };
6
-
7
- /** 字符串插值模板 */
8
- export type InterpolationTemplate = {
9
- type: 'interpolation';
10
- templates: string[];
11
- values: string[];
12
- };
1
+ import { compileSync, type VmScript } from '@mirascript/mirascript';
2
+ import { LRUCache } from 'lru-cache';
13
3
 
14
4
  /** 字符串模板 */
15
- export type Template = string | FormulaTemplate | InterpolationTemplate;
5
+ export type Template =
6
+ | string
7
+ | {
8
+ type: TemplateType;
9
+ value: VmScript;
10
+ };
16
11
 
17
12
  /** 字符串模板类型 */
18
- export type TemplateType = (Template & object)['type'];
19
-
20
- const PARSER_STATUS_TEXT = 0;
21
- const PARSER_STATUS_EXPRESSION_SIMPLE = 1;
22
- const PARSER_STATUS_EXPRESSION_COMPLEX = 2;
23
- /** 解析状态机 */
24
- type ParserStatus =
25
- | typeof PARSER_STATUS_TEXT
26
- | typeof PARSER_STATUS_EXPRESSION_SIMPLE
27
- | typeof PARSER_STATUS_EXPRESSION_COMPLEX;
28
-
29
- /** 检查字符满足 [a-zA-Z0-9_] */
30
- function isIdentifierChar(char: string): boolean {
31
- // eslint-disable-next-line unicorn/prefer-code-point
32
- const charCode = char.charCodeAt(0);
33
- return (
34
- (charCode >= 97 && charCode <= 122) ||
35
- (charCode >= 65 && charCode <= 90) ||
36
- (charCode >= 48 && charCode <= 57) ||
37
- charCode === 95
38
- );
39
- }
40
-
41
- /** 检查字符满足 [a-zA-Z_] */
42
- function isIdentifierFirstChar(char: string): boolean {
43
- // eslint-disable-next-line unicorn/prefer-code-point
44
- const charCode = char.charCodeAt(0);
45
- return (charCode >= 97 && charCode <= 122) || (charCode >= 65 && charCode <= 90) || charCode === 95;
46
- }
47
-
48
- /** 字符串插值模板标识符 */
49
- const INTERPOLATION_CHAR = '$';
50
- /** 字符串插值模板表达式开始标识符 */
51
- const INTERPOLATION_EXPRESSION_START = ['{', '[', '<', '('];
52
- /** 字符串插值模板表达式结束标识符 */
53
- const INTERPOLATION_EXPRESSION_END = ['}', ']', '>', ')'];
54
-
55
- /**
56
- * 解析字符串插值模板
57
- * @example parseInterpolationImpl("hello $name! I am $age years old. I'll be ${age+1} next year. Give me $$100.")
58
- * // {
59
- * // type: 'interpolation',
60
- * // templates: ['hello ', '! I am ', ' years old. I\'ll be ', ' next year. Give me $$100.'],
61
- * // values: ['name', 'age', 'age+1']
62
- * // }
63
- */
64
- function parseInterpolationImpl(template: string, start: number, length: number): InterpolationTemplate {
65
- const templates: string[] = [];
66
- const values: string[] = [];
67
- let currentTemplate = '';
68
- let currentValue = '';
69
- let expressionComplexDepth = 0;
70
- let status: ParserStatus = PARSER_STATUS_TEXT;
71
- let complexExpressionStartType = -1;
72
-
73
- const end = start + length - 1;
74
- for (let i = start; i <= end; i++) {
75
- if (status === PARSER_STATUS_TEXT) {
76
- const nextInterpolationChar = template.indexOf(INTERPOLATION_CHAR, i);
77
- if (nextInterpolationChar < 0 || nextInterpolationChar >= end) {
78
- // No more interpolation
79
- currentTemplate += template.slice(i, end + 1);
80
- break;
81
- }
82
- currentTemplate += template.slice(i, nextInterpolationChar);
83
- i = nextInterpolationChar;
84
- const nextChar = template.charAt(nextInterpolationChar + 1);
85
-
86
- complexExpressionStartType = INTERPOLATION_EXPRESSION_START.indexOf(nextChar);
87
- if (complexExpressionStartType >= 0) {
88
- // Start of complex expression
89
- templates.push(currentTemplate);
90
- currentTemplate = '';
91
- status = PARSER_STATUS_EXPRESSION_COMPLEX;
92
- expressionComplexDepth = 1;
93
- i++;
94
- continue;
95
- }
96
- if (isIdentifierFirstChar(nextChar)) {
97
- // Start of simple expression
98
- templates.push(currentTemplate);
99
- currentTemplate = '';
100
- currentValue = nextChar;
101
- status = PARSER_STATUS_EXPRESSION_SIMPLE;
102
- i++;
103
- continue;
104
- }
105
- // Not an expression
106
- currentTemplate += INTERPOLATION_CHAR;
107
- continue;
108
- }
109
- const char = template.charAt(i);
110
- if (status === PARSER_STATUS_EXPRESSION_SIMPLE) {
111
- if (isIdentifierChar(char)) {
112
- currentValue += char;
113
- continue;
114
- }
115
- // End of expression
116
- values.push(currentValue);
117
- currentValue = '';
118
- status = PARSER_STATUS_TEXT;
119
- i--;
120
- continue;
121
- }
122
- if (status === PARSER_STATUS_EXPRESSION_COMPLEX) {
123
- if (char === INTERPOLATION_EXPRESSION_START[complexExpressionStartType]) {
124
- expressionComplexDepth++;
125
- } else if (char === INTERPOLATION_EXPRESSION_END[complexExpressionStartType]) {
126
- expressionComplexDepth--;
127
- if (expressionComplexDepth === 0) {
128
- // End of expression
129
- values.push(currentValue.trim());
130
- currentValue = '';
131
- status = PARSER_STATUS_TEXT;
132
- continue;
133
- }
134
- }
135
- currentValue += char;
136
- continue;
137
- }
138
- }
139
- if (status === PARSER_STATUS_TEXT) {
140
- templates.push(currentTemplate);
141
- } else if (status === PARSER_STATUS_EXPRESSION_SIMPLE) {
142
- values.push(currentValue);
143
- templates.push('');
144
- } else {
145
- throw new Error('Unexpected end of input');
146
- }
13
+ export type TemplateType = 'interpolation' | 'formula';
147
14
 
148
- return {
149
- type: 'interpolation',
150
- templates,
151
- values,
152
- };
153
- }
15
+ const CACHE_SIZE = 100;
154
16
 
155
- /**
156
- * 解析字符串插值模板
157
- * @example parseInterpolation("hello $name! I am $age years old. I'll be ${age+1} next year. And $(2*age) after $<age> years.")
158
- * // {
159
- * // type: 'interpolation',
160
- * // templates: ['hello ', '! I am ', ' years old. I\'ll be ', ' next year. And ', ' after ', ' years.'],
161
- * // values: ['name', 'age', 'age+1', '2*age', 'age']
162
- * // }
163
- */
164
- export function parseInterpolation(template: string, start?: number, length?: number): InterpolationTemplate {
165
- start ??= 0;
166
- length ??= template.length - start;
167
- if (start < 0 || start > template.length) throw new Error('start out of range');
168
- if (length < 0 || start + length > template.length) throw new Error('length out of range');
169
- return parseInterpolationImpl(template, start, length);
170
- }
17
+ const formula = new LRUCache<string, Template & { type: 'formula' }>({
18
+ max: CACHE_SIZE,
19
+ memoMethod: (template: string) => {
20
+ const formula = template.slice(1);
21
+ const value = compileSync(formula, { input_mode: 'Script' });
22
+ return {
23
+ type: 'formula',
24
+ value: value,
25
+ };
26
+ },
27
+ });
28
+ const interpolation = new LRUCache<string, Template & { type: 'interpolation' }>({
29
+ max: CACHE_SIZE,
30
+ memoMethod: (template: string) => {
31
+ const expr = template.slice(1);
32
+ const value = compileSync(expr, { input_mode: 'Template' });
33
+ return {
34
+ type: 'interpolation',
35
+ value: value,
36
+ };
37
+ },
38
+ });
171
39
 
172
40
  /**
173
41
  * 解析字符串模板
@@ -177,18 +45,12 @@ export function parseInterpolation(template: string, start?: number, length?: nu
177
45
  * - 否则表示是一个普通字符串
178
46
  */
179
47
  export function parseTemplate(template: string): Template {
180
- if (!template) return '';
181
48
  if (template.length <= 1) return template;
182
49
  if (template.startsWith('=')) {
183
- return {
184
- type: 'formula',
185
- value: template.slice(1),
186
- };
50
+ return formula.memo(template);
187
51
  }
188
52
  if (template.startsWith('$')) {
189
- const result = parseInterpolationImpl(template, 1, template.length - 1);
190
- if (result.values.length === 0) return result.templates[0]!;
191
- return result;
53
+ return interpolation.memo(template);
192
54
  }
193
55
  return template;
194
56
  }
package/src/utils.ts ADDED
@@ -0,0 +1,50 @@
1
+ /** 是否为 ArrayBuffer */
2
+ export let isArrayBuffer: (value: object) => value is ArrayBuffer | SharedArrayBuffer;
3
+
4
+ /** 是否为 Error */
5
+ export let isError: (value: unknown) => value is Error;
6
+
7
+ declare global {
8
+ /** @inheritdoc */
9
+ interface ErrorConstructor {
10
+ /** @inheritdoc */
11
+ isError?(this: void, value: unknown): value is Error;
12
+ }
13
+ }
14
+
15
+ if (typeof Error.isError == 'function') {
16
+ isError = Error.isError;
17
+ }
18
+
19
+ if (typeof process == 'object' && typeof process.getBuiltinModule == 'function') {
20
+ const typeUtils = process.getBuiltinModule('node:util/types');
21
+ isArrayBuffer = typeUtils.isAnyArrayBuffer;
22
+ isError = typeUtils.isNativeError;
23
+ }
24
+
25
+ isError ??= (value: unknown): value is Error => {
26
+ return value instanceof Error;
27
+ };
28
+
29
+ isArrayBuffer ??= (value: object): value is ArrayBuffer | SharedArrayBuffer => {
30
+ const tag = toString(value);
31
+ return tag === '[object ArrayBuffer]' || tag === '[object SharedArrayBuffer]';
32
+ };
33
+
34
+ /**
35
+ * Object.prototype.toString.call 的快捷方式
36
+ */
37
+ // eslint-disable-next-line @typescript-eslint/unbound-method
38
+ export const toString = Function.call.bind(Object.prototype.toString) as (value: unknown) => string;
39
+ export const { hasOwn } = Object;
40
+ export const { isArray } = Array;
41
+ export const isArrayBufferView = ArrayBuffer.isView.bind(ArrayBuffer);
42
+ export const { stringify } = JSON;
43
+ /**
44
+ * 获取 ArrayBuffer 的拷贝
45
+ */
46
+ export function copyArrayBuffer(buffer: ArrayBuffer | SharedArrayBuffer, start: number, length?: number): ArrayBuffer {
47
+ const copy = new ArrayBuffer(length ?? buffer.byteLength - start);
48
+ new Uint8Array(copy).set(new Uint8Array(buffer, start, length));
49
+ return copy;
50
+ }
package/tests/template.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { randomBytes, randomFillSync } from 'node:crypto';
2
- import { setTimeout as timeout } from 'node:timers/promises';
3
- import { template } from '@cloudpss/template';
2
+ import { template, createVmContext } from '@cloudpss/template';
4
3
 
5
4
  describe('template', () => {
6
5
  it('should handle primitives', () => {
@@ -147,7 +146,7 @@ describe('template', () => {
147
146
  randomFillSync(new Uint8Array(buffer));
148
147
  const result = template(buffer)();
149
148
  expect(new Uint8Array(result)).toEqual(new Uint8Array(buffer));
150
- expect(result).toBeInstanceOf(SharedArrayBuffer);
149
+ expect(result).toBeInstanceOf(ArrayBuffer);
151
150
  expect(result).not.toBe(buffer);
152
151
  });
153
152
  });
@@ -199,9 +198,11 @@ describe('template', () => {
199
198
  });
200
199
  it('should build interpolated strings', () => {
201
200
  const t = template({ hello: '$Hello, ${name}!', not: 'Hello $name', array: ['$$name', '$not'] });
202
- const result = t({
203
- name: 'world',
204
- });
201
+ const result = t(
202
+ createVmContext({
203
+ name: 'world',
204
+ }),
205
+ );
205
206
  expect(result).toEqual({
206
207
  hello: 'Hello, world!',
207
208
  not: 'Hello $name',
@@ -227,7 +228,7 @@ describe('template', () => {
227
228
  describe('should work while objectKeyMode is', () => {
228
229
  it('template', () => {
229
230
  const obj = { $: 1, _: 2, '=x': 3, $$y: 4 };
230
- const result = template(obj, { objectKeyMode: 'template' })({ x: 11n, y: 12 });
231
+ const result = template(obj, { objectKeyMode: 'template' })(createVmContext({}, { x: 11n, y: 12 }));
231
232
  expect(result).toEqual({
232
233
  $: 1,
233
234
  _: 2,
@@ -237,7 +238,7 @@ describe('template', () => {
237
238
  });
238
239
  it('ignore', () => {
239
240
  const obj = { $: 1, _: 2, '=x': 3, $$y: 4 };
240
- const result = template(obj, { objectKeyMode: 'ignore' })({ x: 11n, y: 12 });
241
+ const result = template(obj, { objectKeyMode: 'ignore' })(createVmContext({}, { x: 11n, y: 12 }));
241
242
  expect(result).toEqual({
242
243
  $: 1,
243
244
  _: 2,
@@ -247,62 +248,22 @@ describe('template', () => {
247
248
  });
248
249
  });
249
250
 
250
- describe('should work with default evaluator', () => {
251
- it('with formula', () => {
252
- const obj = { a: '=a', b: '=b' };
253
- const result = template(obj)({ a: 1 });
254
- expect(result).toEqual({ a: 1, b: undefined });
255
- });
256
- it('with interpolation', () => {
257
- const obj = { a: '$$a', b: '$$b' };
258
- const result = template(obj)({ a: 1 });
259
- expect(result).toEqual({ a: '1', b: '' });
260
- });
261
- });
262
- describe('should work with custom evaluator', () => {
251
+ describe('should work with evaluator', () => {
263
252
  it('with formula', () => {
264
- const obj = { a: '=a', b: '=b' };
265
- const result = template(obj, {
266
- evaluator: {
267
- inject: { a: 'abcd', b: 11n },
268
- compile: (expression) => `evaluator.${expression}`,
269
- },
270
- })({ a: 1 });
271
- expect(result).toEqual({ a: 'abcd', b: 11n });
253
+ const obj = { a: '=a', b: '=b', complex: '=a + (b ?? 1)' };
254
+ const result = template(obj)(createVmContext({ a: 1, b: undefined }));
255
+ expect(result).toEqual({ a: 1, b: null, complex: 2 });
272
256
  });
273
257
  it('with interpolation', () => {
274
- const obj = { a: '$$a', b: '$$b' };
275
- const result = template(obj, {
276
- evaluator: {
277
- inject: { a: 'abcd', b: 11n },
278
- compile: (expression) => `evaluator.${expression}`,
279
- },
280
- })({ a: 1 });
281
- expect(result).toEqual({ a: 'abcd', b: '11' });
282
- });
283
- });
284
- describe('should work with async evaluator', () => {
285
- it('with formula', async () => {
286
- const obj = { a: '=a', b: '=b' };
287
- const result = template(obj, {
288
- evaluator: {
289
- inject: { a: 'abcd', b: 11n, timeout },
290
- async: true,
291
- compile: (expression) => `await evaluator.timeout(100, evaluator.${expression})`,
292
- },
293
- })({ a: 1 });
294
- await expect(result).resolves.toEqual({ a: 'abcd', b: 11n });
258
+ const obj = { a: '$$a', b: '$$b', complex: '$Value is ${a}-${b}' };
259
+ const result = template(obj)(createVmContext({ a: 1, b: undefined }));
260
+ expect(result).toEqual({ a: '1', b: '', complex: 'Value is 1-' });
295
261
  });
296
- it('with interpolation', async () => {
297
- const obj = { a: '$$a', b: '$$b' };
298
- const result = template(obj, {
299
- evaluator: {
300
- inject: { a: 'abcd', b: 11n, timeout },
301
- async: true,
302
- compile: (expression) => `await evaluator.timeout(100, evaluator.${expression})`,
303
- },
304
- })({ a: 1 });
305
- await expect(result).resolves.toEqual({ a: 'abcd', b: '11' });
262
+ it('has extern values', () => {
263
+ const obj = { a: '=ab', b: '$$(ta.length)', t: '=ta' };
264
+ const externValues = { ab: new ArrayBuffer(8), ta: new Uint8Array(4) };
265
+ const result = template(obj)(createVmContext({}, externValues));
266
+ expect(result).toEqual({ a: externValues.ab, b: '4', t: externValues.ta });
306
267
  });
307
268
  });
308
269
  });
@@ -1 +0,0 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/template/compiler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuBpE,WAAW;AACX,qBAAa,gBAAgB;IAErB,QAAQ,CAAC,QAAQ,EAAE,OAAO;IAC1B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC;gBADlC,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC;IAE/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,WAAW;IACX,OAAO,CAAC,SAAS;IAOjB,YAAY;IACZ,OAAO,CAAC,WAAW;IAgBnB,eAAe;IACf,OAAO,CAAC,UAAU;IAUlB,WAAW;IACX,OAAO,CAAC,UAAU;IAGlB,qBAAqB;IACrB,OAAO,CAAC,gBAAgB;IAIxB,yBAAyB;IACzB,OAAO,CAAC,oBAAoB;IAI5B,WAAW;IACX,OAAO,CAAC,WAAW;IAqBnB,UAAU;IACV,OAAO,CAAC,UAAU;IAoBlB,WAAW;IACX,KAAK,IAAI,gBAAgB;CAwB5B"}