i18next-cli 1.56.3 → 1.56.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/dist/cjs/cli.js CHANGED
@@ -32,7 +32,7 @@ const program = new commander.Command();
32
32
  program
33
33
  .name('i18next-cli')
34
34
  .description('A unified, high-performance i18next CLI.')
35
- .version('1.56.3'); // This string is replaced with the actual version at build time by rollup
35
+ .version('1.56.5'); // This string is replaced with the actual version at build time by rollup
36
36
  // new: global config override option
37
37
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
38
38
  program
@@ -608,7 +608,48 @@ class CallExpressionHandler {
608
608
  return [];
609
609
  }
610
610
  }
611
- let current = body;
611
+ return this.extractKeysFromSelectorExpression(body);
612
+ }
613
+ /**
614
+ * Recursively extracts key paths from a selector-body expression.
615
+ *
616
+ * On top of the straight MemberExpression walk this also descends into
617
+ * branching forms so keys referenced in either branch are preserved
618
+ * (see #247): ternaries (`cond ? $.a : $.b`), nullish/logical
619
+ * short-circuits (`x ?? $.a`, `x && $.a`, `x || $.a`), and common
620
+ * wrapper nodes (parentheses, TS type assertions).
621
+ */
622
+ extractKeysFromSelectorExpression(expr) {
623
+ if (!expr)
624
+ return [];
625
+ // Unwrap wrappers that don't change the expressed key path.
626
+ if (expr.type === 'ParenthesisExpression' ||
627
+ expr.type === 'TsAsExpression' ||
628
+ expr.type === 'TsSatisfiesExpression' ||
629
+ expr.type === 'TsNonNullExpression' ||
630
+ expr.type === 'TsConstAssertion') {
631
+ return this.extractKeysFromSelectorExpression(expr.expression);
632
+ }
633
+ // Ternary: union of both branches.
634
+ if (expr.type === 'ConditionalExpression') {
635
+ return [
636
+ ...this.extractKeysFromSelectorExpression(expr.consequent),
637
+ ...this.extractKeysFromSelectorExpression(expr.alternate),
638
+ ];
639
+ }
640
+ // Short-circuit logicals (`||`, `&&`, `??`): union of both sides. SWC
641
+ // may emit these as LogicalExpression or BinaryExpression depending on
642
+ // version, so accept both.
643
+ if ((expr.type === 'LogicalExpression' || expr.type === 'BinaryExpression') &&
644
+ (expr.operator === '||' || expr.operator === '&&' || expr.operator === '??')) {
645
+ return [
646
+ ...this.extractKeysFromSelectorExpression(expr.left),
647
+ ...this.extractKeysFromSelectorExpression(expr.right),
648
+ ];
649
+ }
650
+ if (expr.type !== 'MemberExpression')
651
+ return [];
652
+ let current = expr;
612
653
  // Each element is an array of possible values for that position in the key path
613
654
  const parts = [];
614
655
  // Recursively walk down MemberExpressions
@@ -31,16 +31,19 @@ class JSXHandler {
31
31
  return astUtils.lineColumnFromOffset(this.getCurrentCode(), node.span.start);
32
32
  }
33
33
  /**
34
- * Warns about `<Trans>Hello <b>{name}</b></Trans>` style children where a
35
- * bare identifier is used as a React child. react-i18next inlines the value
36
- * at runtime, producing a key like `"Hello <1>meow</1>"`, but the extractor
37
- * serializes the identifier name as `"{{name}}"`. The two never match, and
38
- * even when an `i18nKey` is set, the placeholder `{{name}}` cannot be
39
- * interpolated without a `values={{ name }}` prop — it renders literally.
34
+ * Emits an error for `<Trans>Hello <b>{name}</b></Trans>` style children
35
+ * where a bare identifier is used as a React child. react-i18next inlines
36
+ * the value at runtime, producing a key like `"Hello <1>meow</1>"`, but the
37
+ * extractor serializes the identifier name as `"{{name}}"`. The two never
38
+ * match, and even when an `i18nKey` is set, the placeholder `{{name}}`
39
+ * cannot be interpolated without a `values={{ name }}` prop — it renders
40
+ * literally.
40
41
  *
41
- * We keep the existing extraction behaviour so projects that already rely on
42
- * the `{{name}}` output (with a matching `values` prop) aren't broken, and
43
- * instead surface a diagnostic pointing users at the runtime mismatch.
42
+ * We keep the existing extraction behaviour so projects that already rely
43
+ * on the `{{name}}` output (with a matching `values` prop) aren't broken,
44
+ * and instead surface a diagnostic pointing users at the runtime mismatch.
45
+ * Emitted via `logger.error` with an `Error:` prefix so build tooling that
46
+ * watches for errors (see #200) can treat this as fatal if desired.
44
47
  */
45
48
  warnOnBareIdentifierTransChildren(node, elementName) {
46
49
  const bareIdentifiers = [];
@@ -63,14 +66,14 @@ class JSXHandler {
63
66
  visit(node.children);
64
67
  if (bareIdentifiers.length === 0)
65
68
  return;
66
- const warn = this.pluginContext?.logger?.warn?.bind(this.pluginContext.logger) ??
67
- console.warn.bind(console);
69
+ const emit = this.pluginContext?.logger?.error?.bind(this.pluginContext.logger) ??
70
+ console.error.bind(console);
68
71
  for (const { name, span } of bareIdentifiers) {
69
72
  const loc = astUtils.lineColumnFromOffset(this.getCurrentCode(), span.start);
70
73
  const where = loc
71
74
  ? `${this.getCurrentFile()}:${loc.line}:${loc.column}`
72
75
  : this.getCurrentFile();
73
- warn(`<${elementName}> child {${name}} at ${where} won't match at runtime — react-i18next inlines the value (e.g. "<1>meow</1>"), but extraction produces "<1>{{${name}}}</1>". Use {{${name}}} (double braces) with values={{ ${name} }} for interpolation, or inline the value if it isn't meant to be translated.`);
76
+ emit(`Error: <${elementName}> child {${name}} at ${where} won't match at runtime — react-i18next inlines the value (e.g. "<1>meow</1>"), but extraction produces "<1>{{${name}}}</1>". Use {{${name}}} (double braces) with values={{ ${name} }} for interpolation.`);
74
77
  }
75
78
  }
76
79
  /**
package/dist/esm/cli.js CHANGED
@@ -30,7 +30,7 @@ const program = new Command();
30
30
  program
31
31
  .name('i18next-cli')
32
32
  .description('A unified, high-performance i18next CLI.')
33
- .version('1.56.3'); // This string is replaced with the actual version at build time by rollup
33
+ .version('1.56.5'); // This string is replaced with the actual version at build time by rollup
34
34
  // new: global config override option
35
35
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
36
36
  program
@@ -606,7 +606,48 @@ class CallExpressionHandler {
606
606
  return [];
607
607
  }
608
608
  }
609
- let current = body;
609
+ return this.extractKeysFromSelectorExpression(body);
610
+ }
611
+ /**
612
+ * Recursively extracts key paths from a selector-body expression.
613
+ *
614
+ * On top of the straight MemberExpression walk this also descends into
615
+ * branching forms so keys referenced in either branch are preserved
616
+ * (see #247): ternaries (`cond ? $.a : $.b`), nullish/logical
617
+ * short-circuits (`x ?? $.a`, `x && $.a`, `x || $.a`), and common
618
+ * wrapper nodes (parentheses, TS type assertions).
619
+ */
620
+ extractKeysFromSelectorExpression(expr) {
621
+ if (!expr)
622
+ return [];
623
+ // Unwrap wrappers that don't change the expressed key path.
624
+ if (expr.type === 'ParenthesisExpression' ||
625
+ expr.type === 'TsAsExpression' ||
626
+ expr.type === 'TsSatisfiesExpression' ||
627
+ expr.type === 'TsNonNullExpression' ||
628
+ expr.type === 'TsConstAssertion') {
629
+ return this.extractKeysFromSelectorExpression(expr.expression);
630
+ }
631
+ // Ternary: union of both branches.
632
+ if (expr.type === 'ConditionalExpression') {
633
+ return [
634
+ ...this.extractKeysFromSelectorExpression(expr.consequent),
635
+ ...this.extractKeysFromSelectorExpression(expr.alternate),
636
+ ];
637
+ }
638
+ // Short-circuit logicals (`||`, `&&`, `??`): union of both sides. SWC
639
+ // may emit these as LogicalExpression or BinaryExpression depending on
640
+ // version, so accept both.
641
+ if ((expr.type === 'LogicalExpression' || expr.type === 'BinaryExpression') &&
642
+ (expr.operator === '||' || expr.operator === '&&' || expr.operator === '??')) {
643
+ return [
644
+ ...this.extractKeysFromSelectorExpression(expr.left),
645
+ ...this.extractKeysFromSelectorExpression(expr.right),
646
+ ];
647
+ }
648
+ if (expr.type !== 'MemberExpression')
649
+ return [];
650
+ let current = expr;
610
651
  // Each element is an array of possible values for that position in the key path
611
652
  const parts = [];
612
653
  // Recursively walk down MemberExpressions
@@ -29,16 +29,19 @@ class JSXHandler {
29
29
  return lineColumnFromOffset(this.getCurrentCode(), node.span.start);
30
30
  }
31
31
  /**
32
- * Warns about `<Trans>Hello <b>{name}</b></Trans>` style children where a
33
- * bare identifier is used as a React child. react-i18next inlines the value
34
- * at runtime, producing a key like `"Hello <1>meow</1>"`, but the extractor
35
- * serializes the identifier name as `"{{name}}"`. The two never match, and
36
- * even when an `i18nKey` is set, the placeholder `{{name}}` cannot be
37
- * interpolated without a `values={{ name }}` prop — it renders literally.
32
+ * Emits an error for `<Trans>Hello <b>{name}</b></Trans>` style children
33
+ * where a bare identifier is used as a React child. react-i18next inlines
34
+ * the value at runtime, producing a key like `"Hello <1>meow</1>"`, but the
35
+ * extractor serializes the identifier name as `"{{name}}"`. The two never
36
+ * match, and even when an `i18nKey` is set, the placeholder `{{name}}`
37
+ * cannot be interpolated without a `values={{ name }}` prop — it renders
38
+ * literally.
38
39
  *
39
- * We keep the existing extraction behaviour so projects that already rely on
40
- * the `{{name}}` output (with a matching `values` prop) aren't broken, and
41
- * instead surface a diagnostic pointing users at the runtime mismatch.
40
+ * We keep the existing extraction behaviour so projects that already rely
41
+ * on the `{{name}}` output (with a matching `values` prop) aren't broken,
42
+ * and instead surface a diagnostic pointing users at the runtime mismatch.
43
+ * Emitted via `logger.error` with an `Error:` prefix so build tooling that
44
+ * watches for errors (see #200) can treat this as fatal if desired.
42
45
  */
43
46
  warnOnBareIdentifierTransChildren(node, elementName) {
44
47
  const bareIdentifiers = [];
@@ -61,14 +64,14 @@ class JSXHandler {
61
64
  visit(node.children);
62
65
  if (bareIdentifiers.length === 0)
63
66
  return;
64
- const warn = this.pluginContext?.logger?.warn?.bind(this.pluginContext.logger) ??
65
- console.warn.bind(console);
67
+ const emit = this.pluginContext?.logger?.error?.bind(this.pluginContext.logger) ??
68
+ console.error.bind(console);
66
69
  for (const { name, span } of bareIdentifiers) {
67
70
  const loc = lineColumnFromOffset(this.getCurrentCode(), span.start);
68
71
  const where = loc
69
72
  ? `${this.getCurrentFile()}:${loc.line}:${loc.column}`
70
73
  : this.getCurrentFile();
71
- warn(`<${elementName}> child {${name}} at ${where} won't match at runtime — react-i18next inlines the value (e.g. "<1>meow</1>"), but extraction produces "<1>{{${name}}}</1>". Use {{${name}}} (double braces) with values={{ ${name} }} for interpolation, or inline the value if it isn't meant to be translated.`);
74
+ emit(`Error: <${elementName}> child {${name}} at ${where} won't match at runtime — react-i18next inlines the value (e.g. "<1>meow</1>"), but extraction produces "<1>{{${name}}}</1>". Use {{${name}}} (double braces) with values={{ ${name} }} for interpolation.`);
72
75
  }
73
76
  }
74
77
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-cli",
3
- "version": "1.56.3",
3
+ "version": "1.56.5",
4
4
  "description": "A unified, high-performance i18next CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -67,6 +67,16 @@ export declare class CallExpressionHandler {
67
67
  * @returns Extracted key paths, or empty array if not statically analyzable
68
68
  */
69
69
  private extractKeysFromSelector;
70
+ /**
71
+ * Recursively extracts key paths from a selector-body expression.
72
+ *
73
+ * On top of the straight MemberExpression walk this also descends into
74
+ * branching forms so keys referenced in either branch are preserved
75
+ * (see #247): ternaries (`cond ? $.a : $.b`), nullish/logical
76
+ * short-circuits (`x ?? $.a`, `x && $.a`, `x || $.a`), and common
77
+ * wrapper nodes (parentheses, TS type assertions).
78
+ */
79
+ private extractKeysFromSelectorExpression;
70
80
  /**
71
81
  * Generates plural form keys based on the primary language's plural rules.
72
82
  *
@@ -1 +1 @@
1
- {"version":3,"file":"call-expression-handler.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/call-expression-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6C,MAAM,WAAW,CAAA;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAgB,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1G,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAa7D,qBAAa,qBAAqB;IAChC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,kBAAkB,CAAoB;IACvC,UAAU,cAAoB;IACrC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,iBAAiB,CAAsC;gBAG7D,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,MAAM,MAAM,EAC5B,cAAc,EAAE,MAAM,MAAM,EAC5B,iBAAiB,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAA2B;IAW3E;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;;;;;;;;;;;OAcG;IACH,oBAAoB,CAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,GAAG,IAAI;IA0ZxG;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,wBAAwB;IAyEhC;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;IA8BpC;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,uBAAuB;IAgE/B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,gBAAgB;IAyMxB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;CA2BxB"}
1
+ {"version":3,"file":"call-expression-handler.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/call-expression-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6C,MAAM,WAAW,CAAA;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAgB,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1G,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAa7D,qBAAa,qBAAqB;IAChC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,kBAAkB,CAAoB;IACvC,UAAU,cAAoB;IACrC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,iBAAiB,CAAsC;gBAG7D,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,MAAM,MAAM,EAC5B,cAAc,EAAE,MAAM,MAAM,EAC5B,iBAAiB,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAA2B;IAW3E;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;;;;;;;;;;;OAcG;IACH,oBAAoB,CAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,GAAG,IAAI;IA0ZxG;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,wBAAwB;IAyEhC;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;IA8BpC;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,uBAAuB;IAgB/B;;;;;;;;OAQG;IACH,OAAO,CAAC,iCAAiC;IAwFzC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,gBAAgB;IAyMxB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;CA2BxB"}
@@ -15,16 +15,19 @@ export declare class JSXHandler {
15
15
  */
16
16
  private getLocationFromNode;
17
17
  /**
18
- * Warns about `<Trans>Hello <b>{name}</b></Trans>` style children where a
19
- * bare identifier is used as a React child. react-i18next inlines the value
20
- * at runtime, producing a key like `"Hello <1>meow</1>"`, but the extractor
21
- * serializes the identifier name as `"{{name}}"`. The two never match, and
22
- * even when an `i18nKey` is set, the placeholder `{{name}}` cannot be
23
- * interpolated without a `values={{ name }}` prop — it renders literally.
18
+ * Emits an error for `<Trans>Hello <b>{name}</b></Trans>` style children
19
+ * where a bare identifier is used as a React child. react-i18next inlines
20
+ * the value at runtime, producing a key like `"Hello <1>meow</1>"`, but the
21
+ * extractor serializes the identifier name as `"{{name}}"`. The two never
22
+ * match, and even when an `i18nKey` is set, the placeholder `{{name}}`
23
+ * cannot be interpolated without a `values={{ name }}` prop — it renders
24
+ * literally.
24
25
  *
25
- * We keep the existing extraction behaviour so projects that already rely on
26
- * the `{{name}}` output (with a matching `values` prop) aren't broken, and
27
- * instead surface a diagnostic pointing users at the runtime mismatch.
26
+ * We keep the existing extraction behaviour so projects that already rely
27
+ * on the `{{name}}` output (with a matching `values` prop) aren't broken,
28
+ * and instead surface a diagnostic pointing users at the runtime mismatch.
29
+ * Emitted via `logger.error` with an `Error:` prefix so build tooling that
30
+ * watches for errors (see #200) can treat this as fatal if desired.
28
31
  */
29
32
  private warnOnBareIdentifierTransChildren;
30
33
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"jsx-handler.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/jsx-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,UAAU,EAAqC,MAAM,WAAW,CAAA;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAgB,MAAM,gBAAgB,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAS7D,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAc;gBAGlC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,MAAM,MAAM,EAC5B,cAAc,EAAE,MAAM,MAAM;IAS9B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iCAAiC;IAgCzC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;;;;;;;OAQG;IACH,gBAAgB,CAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,GAAG,IAAI;IA2UjI;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,0BAA0B;IAkIlC;;;;;;;;;OASG;IACH,OAAO,CAAC,cAAc;CAevB"}
1
+ {"version":3,"file":"jsx-handler.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/jsx-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,UAAU,EAAqC,MAAM,WAAW,CAAA;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAgB,MAAM,gBAAgB,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAS7D,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAc;gBAGlC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,MAAM,MAAM,EAC5B,cAAc,EAAE,MAAM,MAAM;IAS9B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,iCAAiC;IAgCzC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;;;;;;;OAQG;IACH,gBAAgB,CAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,GAAG,IAAI;IA2UjI;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,0BAA0B;IAkIlC;;;;;;;;;OASG;IACH,OAAO,CAAC,cAAc;CAevB"}