i18next-cli 1.56.8 → 1.56.9
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 +1 -1
- package/dist/cjs/extractor/core/ast-visitors.js +34 -0
- package/dist/cjs/extractor/parsers/scope-manager.js +218 -0
- package/dist/esm/cli.js +1 -1
- package/dist/esm/extractor/core/ast-visitors.js +34 -0
- package/dist/esm/extractor/parsers/scope-manager.js +218 -0
- package/package.json +1 -1
- package/types/extractor/core/ast-visitors.d.ts.map +1 -1
- package/types/extractor/parsers/scope-manager.d.ts +62 -1
- package/types/extractor/parsers/scope-manager.d.ts.map +1 -1
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.
|
|
35
|
+
.version('1.56.9'); // 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
|
|
@@ -165,7 +165,37 @@ class ASTVisitors {
|
|
|
165
165
|
if (!node)
|
|
166
166
|
return;
|
|
167
167
|
let isNewScope = false;
|
|
168
|
+
let isNewClassScope = false;
|
|
168
169
|
let paramTemporaries;
|
|
170
|
+
// ENTER CLASS SCOPE for class declarations / expressions and pre-register
|
|
171
|
+
// class field initializers so that later `this.<field>` references inside
|
|
172
|
+
// method bodies can inherit the namespace/keyPrefix from the field.
|
|
173
|
+
if (node.type === 'ClassDeclaration' ||
|
|
174
|
+
node.type === 'ClassExpression' ||
|
|
175
|
+
node.type === 'ClassDecl' ||
|
|
176
|
+
node.type === 'ClassExpr') {
|
|
177
|
+
this.scopeManager.enterClassScope();
|
|
178
|
+
isNewClassScope = true;
|
|
179
|
+
const classBody = Array.isArray(node.body) ? node.body : (node.body?.body ?? []);
|
|
180
|
+
for (const member of classBody) {
|
|
181
|
+
if (!member || typeof member !== 'object')
|
|
182
|
+
continue;
|
|
183
|
+
if (member.type === 'ClassProperty' ||
|
|
184
|
+
member.type === 'PrivateProperty' ||
|
|
185
|
+
member.type === 'PropertyDefinition' ||
|
|
186
|
+
member.type === 'ClassPrivateProperty') {
|
|
187
|
+
let fieldName;
|
|
188
|
+
const key = member.key;
|
|
189
|
+
if (key?.type === 'Identifier')
|
|
190
|
+
fieldName = key.value ?? key.name;
|
|
191
|
+
else if (key?.type === 'PrivateName')
|
|
192
|
+
fieldName = '#' + (key.value ?? key.name ?? key.id?.value ?? key.id?.name);
|
|
193
|
+
if (!fieldName)
|
|
194
|
+
continue;
|
|
195
|
+
this.scopeManager.registerClassField(fieldName, member.value);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
169
199
|
// ENTER SCOPE for functions
|
|
170
200
|
// Accept many SWC/TS AST variants for function-like nodes (declarations, expressions, arrow functions)
|
|
171
201
|
if (node.type === 'Function' ||
|
|
@@ -540,6 +570,10 @@ class ASTVisitors {
|
|
|
540
570
|
}
|
|
541
571
|
this.scopeManager.exitScope();
|
|
542
572
|
}
|
|
573
|
+
// LEAVE CLASS SCOPE for classes
|
|
574
|
+
if (isNewClassScope) {
|
|
575
|
+
this.scopeManager.exitClassScope();
|
|
576
|
+
}
|
|
543
577
|
}
|
|
544
578
|
/**
|
|
545
579
|
* If `node` is a call like `ARRAY.map(param => ...)` where ARRAY is a known
|
|
@@ -6,6 +6,11 @@ class ScopeManager {
|
|
|
6
6
|
scopeStack = [];
|
|
7
7
|
config;
|
|
8
8
|
scope = new Map();
|
|
9
|
+
// Stack of class scopes; each entry maps a class field name (e.g. `myField`
|
|
10
|
+
// or `#privateField`) to the ScopeInfo derived from its initializer. Used to
|
|
11
|
+
// resolve `const { t } = this.field` and `const { t } = this.field()` patterns
|
|
12
|
+
// inside class methods.
|
|
13
|
+
thisFieldStack = [];
|
|
9
14
|
// Track simple local constants with string literal values to resolve identifier args
|
|
10
15
|
simpleConstants = new Map();
|
|
11
16
|
// Track simple local constant objects with string literal property values
|
|
@@ -63,6 +68,49 @@ class ScopeManager {
|
|
|
63
68
|
this.scope = new Map();
|
|
64
69
|
this.simpleConstants.clear();
|
|
65
70
|
this.simpleConstantObjects.clear();
|
|
71
|
+
this.thisFieldStack = [];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Pushes a new class scope used for tracking class field → ScopeInfo
|
|
75
|
+
* mappings. Should be called when entering a ClassDeclaration or
|
|
76
|
+
* ClassExpression.
|
|
77
|
+
*/
|
|
78
|
+
enterClassScope() {
|
|
79
|
+
this.thisFieldStack.push(new Map());
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Pops the current class scope. Should be called when leaving a
|
|
83
|
+
* ClassDeclaration or ClassExpression.
|
|
84
|
+
*/
|
|
85
|
+
exitClassScope() {
|
|
86
|
+
this.thisFieldStack.pop();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Records a class field's ScopeInfo so that later `this.<field>` or
|
|
90
|
+
* `this.<field>()` accesses inside the class can inherit the namespace
|
|
91
|
+
* and keyPrefix from its initializer.
|
|
92
|
+
*
|
|
93
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
94
|
+
* @param info - Scope information derived from the field's initializer
|
|
95
|
+
*/
|
|
96
|
+
setThisField(fieldName, info) {
|
|
97
|
+
if (this.thisFieldStack.length > 0) {
|
|
98
|
+
this.thisFieldStack[this.thisFieldStack.length - 1].set(fieldName, info);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Looks up a class field's ScopeInfo from the innermost class scope outward.
|
|
103
|
+
*
|
|
104
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
105
|
+
* @returns Scope information if found, undefined otherwise
|
|
106
|
+
*/
|
|
107
|
+
getThisField(fieldName) {
|
|
108
|
+
for (let i = this.thisFieldStack.length - 1; i >= 0; i--) {
|
|
109
|
+
if (this.thisFieldStack[i].has(fieldName)) {
|
|
110
|
+
return this.thisFieldStack[i].get(fieldName);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
66
114
|
}
|
|
67
115
|
/**
|
|
68
116
|
* Enters a new variable scope by pushing a new scope map onto the stack.
|
|
@@ -219,6 +267,17 @@ class ScopeManager {
|
|
|
219
267
|
}
|
|
220
268
|
// continue processing; still may be a useTranslation/getFixedT call below
|
|
221
269
|
}
|
|
270
|
+
// Handle: const { t } = this.#field OR const { t } = this.#field()
|
|
271
|
+
// Resolve the source `this.<field>` to its previously-registered ScopeInfo
|
|
272
|
+
// and propagate it onto the destructured variables.
|
|
273
|
+
const thisFieldName = ScopeManager.extractThisFieldName(init);
|
|
274
|
+
if (thisFieldName !== undefined) {
|
|
275
|
+
const sourceScope = this.getThisField(thisFieldName);
|
|
276
|
+
if (sourceScope) {
|
|
277
|
+
this.attachScopeToDestructuredVars(node, sourceScope);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
222
281
|
// Determine the actual call expression, looking inside AwaitExpressions.
|
|
223
282
|
const callExpr = init.type === 'AwaitExpression' && init.argument.type === 'CallExpression'
|
|
224
283
|
? init.argument
|
|
@@ -545,6 +604,165 @@ class ScopeManager {
|
|
|
545
604
|
this.setVarInScope(targetVarName, { defaultNs: finalNs, keyPrefix: finalKeyPrefix });
|
|
546
605
|
}
|
|
547
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* Returns the field name being referenced when an expression takes the form
|
|
609
|
+
* `this.<field>` or `this.<field>()`. Strips the call wrapper if present and
|
|
610
|
+
* prefixes private fields with `#`.
|
|
611
|
+
*
|
|
612
|
+
* Returns undefined if the expression is not such an access.
|
|
613
|
+
*/
|
|
614
|
+
static extractThisFieldName(init) {
|
|
615
|
+
let memberExpr;
|
|
616
|
+
if (init.type === 'MemberExpression') {
|
|
617
|
+
memberExpr = init;
|
|
618
|
+
}
|
|
619
|
+
else if (init.type === 'CallExpression' && init.callee.type === 'MemberExpression') {
|
|
620
|
+
memberExpr = init.callee;
|
|
621
|
+
}
|
|
622
|
+
if (!memberExpr)
|
|
623
|
+
return undefined;
|
|
624
|
+
if (memberExpr.object.type !== 'ThisExpression')
|
|
625
|
+
return undefined;
|
|
626
|
+
const prop = memberExpr.property;
|
|
627
|
+
if (prop?.type === 'Identifier')
|
|
628
|
+
return prop.value;
|
|
629
|
+
if (prop?.type === 'PrivateName')
|
|
630
|
+
return '#' + prop.value;
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Attaches the given ScopeInfo to all destructured variables of a variable
|
|
635
|
+
* declarator (`const { t } = ...`, `const [t] = ...`, or `const t = ...`).
|
|
636
|
+
*/
|
|
637
|
+
attachScopeToDestructuredVars(node, info) {
|
|
638
|
+
if (node.id.type === 'ObjectPattern') {
|
|
639
|
+
for (const prop of node.id.properties) {
|
|
640
|
+
if (prop.type === 'AssignmentPatternProperty' && prop.key.type === 'Identifier') {
|
|
641
|
+
this.setVarInScope(prop.key.value, info);
|
|
642
|
+
}
|
|
643
|
+
if (prop.type === 'KeyValuePatternProperty' && prop.value.type === 'Identifier') {
|
|
644
|
+
this.setVarInScope(prop.value.value, info);
|
|
645
|
+
// Also store under the pattern key name so legacy comment-scope
|
|
646
|
+
// lookups by the original property name continue to work.
|
|
647
|
+
if (prop.key.type === 'Identifier' && (prop.key.value === 't' || prop.key.value === 'getFixedT')) {
|
|
648
|
+
this.scope.set(prop.value.value, { defaultNs: info.defaultNs, keyPrefix: info.keyPrefix });
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
else if (node.id.type === 'Identifier') {
|
|
654
|
+
this.setVarInScope(node.id.value, info);
|
|
655
|
+
}
|
|
656
|
+
else if (node.id.type === 'ArrayPattern') {
|
|
657
|
+
const firstElement = node.id.elements[0];
|
|
658
|
+
if (firstElement?.type === 'Identifier') {
|
|
659
|
+
this.setVarInScope(firstElement.value, info);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Registers a class field's initializer with the current class scope so that
|
|
665
|
+
* later `const { t } = this.<field>` or `const { t } = this.<field>()` calls
|
|
666
|
+
* inside the class body inherit the namespace and keyPrefix from the field
|
|
667
|
+
* initializer.
|
|
668
|
+
*
|
|
669
|
+
* Recognizes the same useTranslation-like patterns supported on regular
|
|
670
|
+
* variable declarations (configured via `useTranslationNames`).
|
|
671
|
+
*
|
|
672
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
673
|
+
* @param value - The field initializer expression
|
|
674
|
+
*/
|
|
675
|
+
registerClassField(fieldName, value) {
|
|
676
|
+
if (!value)
|
|
677
|
+
return;
|
|
678
|
+
if (this.thisFieldStack.length === 0)
|
|
679
|
+
return;
|
|
680
|
+
const callExpr = value.type === 'AwaitExpression' && value.argument.type === 'CallExpression'
|
|
681
|
+
? value.argument
|
|
682
|
+
: value.type === 'CallExpression'
|
|
683
|
+
? value
|
|
684
|
+
: null;
|
|
685
|
+
if (!callExpr)
|
|
686
|
+
return;
|
|
687
|
+
const callee = callExpr.callee;
|
|
688
|
+
if (callee.type !== 'Identifier')
|
|
689
|
+
return;
|
|
690
|
+
const hookConfig = this.getUseTranslationConfig(callee.value);
|
|
691
|
+
if (!hookConfig)
|
|
692
|
+
return;
|
|
693
|
+
const info = this.computeScopeInfoFromHookCall(callExpr, hookConfig);
|
|
694
|
+
if (info.defaultNs || info.keyPrefix) {
|
|
695
|
+
this.setThisField(fieldName, info);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Computes ScopeInfo (defaultNs, keyPrefix) for a useTranslation-style call
|
|
700
|
+
* given a hook configuration that describes argument positions. Mirrors the
|
|
701
|
+
* extraction performed by handleUseTranslationDeclarator without attaching
|
|
702
|
+
* the result to any variable.
|
|
703
|
+
*/
|
|
704
|
+
computeScopeInfoFromHookCall(callExpr, hookConfig) {
|
|
705
|
+
const nsArgIndex = hookConfig.nsArg ?? 0;
|
|
706
|
+
const kpArgIndex = hookConfig.keyPrefixArg ?? 1;
|
|
707
|
+
let defaultNs;
|
|
708
|
+
let keyPrefix;
|
|
709
|
+
const first = callExpr.arguments?.[0]?.expression;
|
|
710
|
+
const second = callExpr.arguments?.[1]?.expression;
|
|
711
|
+
const third = callExpr.arguments?.[2]?.expression;
|
|
712
|
+
const looksLikeLanguage = (s) => /^[a-z]{2,3}([-_][A-Za-z0-9-]+)?$/i.test(s);
|
|
713
|
+
const isBuiltInLngNsForm = hookConfig.name === 'useTranslation' &&
|
|
714
|
+
first?.type === 'StringLiteral' &&
|
|
715
|
+
second?.type === 'StringLiteral' &&
|
|
716
|
+
looksLikeLanguage(first.value);
|
|
717
|
+
let kpArg;
|
|
718
|
+
if (isBuiltInLngNsForm) {
|
|
719
|
+
defaultNs = second.value;
|
|
720
|
+
kpArg = third;
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
if (nsArgIndex !== -1) {
|
|
724
|
+
const nsNode = callExpr.arguments?.[nsArgIndex]?.expression;
|
|
725
|
+
if (nsNode?.type === 'StringLiteral') {
|
|
726
|
+
defaultNs = nsNode.value;
|
|
727
|
+
}
|
|
728
|
+
else if (nsNode?.type === 'Identifier') {
|
|
729
|
+
defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
|
|
730
|
+
}
|
|
731
|
+
else if (nsNode?.type === 'MemberExpression') {
|
|
732
|
+
defaultNs = this.resolveSimpleMemberExpression(nsNode);
|
|
733
|
+
}
|
|
734
|
+
else if (nsNode?.type === 'ArrayExpression') {
|
|
735
|
+
const firstEl = nsNode.elements[0]?.expression;
|
|
736
|
+
if (firstEl?.type === 'StringLiteral') {
|
|
737
|
+
defaultNs = firstEl.value;
|
|
738
|
+
}
|
|
739
|
+
else if (firstEl?.type === 'Identifier') {
|
|
740
|
+
defaultNs = this.resolveSimpleStringIdentifier(firstEl.value);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
|
|
745
|
+
}
|
|
746
|
+
if (kpArg?.type === 'ObjectExpression') {
|
|
747
|
+
const kp = astUtils.getObjectPropValue(kpArg, 'keyPrefix', this.resolveSimpleStringIdentifier.bind(this));
|
|
748
|
+
if (typeof kp === 'string') {
|
|
749
|
+
keyPrefix = kp;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
else if (kpArg?.type === 'StringLiteral') {
|
|
753
|
+
keyPrefix = kpArg.value;
|
|
754
|
+
}
|
|
755
|
+
else if (kpArg?.type === 'Identifier') {
|
|
756
|
+
keyPrefix = this.resolveSimpleStringIdentifier(kpArg.value);
|
|
757
|
+
}
|
|
758
|
+
else if (kpArg?.type === 'TemplateLiteral') {
|
|
759
|
+
const tpl = kpArg;
|
|
760
|
+
if ((tpl.expressions || []).length === 0) {
|
|
761
|
+
keyPrefix = tpl.quasis?.[0]?.cooked ?? undefined;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return { defaultNs, keyPrefix };
|
|
765
|
+
}
|
|
548
766
|
}
|
|
549
767
|
|
|
550
768
|
exports.ScopeManager = ScopeManager;
|
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.
|
|
33
|
+
.version('1.56.9'); // 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
|
|
@@ -163,7 +163,37 @@ class ASTVisitors {
|
|
|
163
163
|
if (!node)
|
|
164
164
|
return;
|
|
165
165
|
let isNewScope = false;
|
|
166
|
+
let isNewClassScope = false;
|
|
166
167
|
let paramTemporaries;
|
|
168
|
+
// ENTER CLASS SCOPE for class declarations / expressions and pre-register
|
|
169
|
+
// class field initializers so that later `this.<field>` references inside
|
|
170
|
+
// method bodies can inherit the namespace/keyPrefix from the field.
|
|
171
|
+
if (node.type === 'ClassDeclaration' ||
|
|
172
|
+
node.type === 'ClassExpression' ||
|
|
173
|
+
node.type === 'ClassDecl' ||
|
|
174
|
+
node.type === 'ClassExpr') {
|
|
175
|
+
this.scopeManager.enterClassScope();
|
|
176
|
+
isNewClassScope = true;
|
|
177
|
+
const classBody = Array.isArray(node.body) ? node.body : (node.body?.body ?? []);
|
|
178
|
+
for (const member of classBody) {
|
|
179
|
+
if (!member || typeof member !== 'object')
|
|
180
|
+
continue;
|
|
181
|
+
if (member.type === 'ClassProperty' ||
|
|
182
|
+
member.type === 'PrivateProperty' ||
|
|
183
|
+
member.type === 'PropertyDefinition' ||
|
|
184
|
+
member.type === 'ClassPrivateProperty') {
|
|
185
|
+
let fieldName;
|
|
186
|
+
const key = member.key;
|
|
187
|
+
if (key?.type === 'Identifier')
|
|
188
|
+
fieldName = key.value ?? key.name;
|
|
189
|
+
else if (key?.type === 'PrivateName')
|
|
190
|
+
fieldName = '#' + (key.value ?? key.name ?? key.id?.value ?? key.id?.name);
|
|
191
|
+
if (!fieldName)
|
|
192
|
+
continue;
|
|
193
|
+
this.scopeManager.registerClassField(fieldName, member.value);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
167
197
|
// ENTER SCOPE for functions
|
|
168
198
|
// Accept many SWC/TS AST variants for function-like nodes (declarations, expressions, arrow functions)
|
|
169
199
|
if (node.type === 'Function' ||
|
|
@@ -538,6 +568,10 @@ class ASTVisitors {
|
|
|
538
568
|
}
|
|
539
569
|
this.scopeManager.exitScope();
|
|
540
570
|
}
|
|
571
|
+
// LEAVE CLASS SCOPE for classes
|
|
572
|
+
if (isNewClassScope) {
|
|
573
|
+
this.scopeManager.exitClassScope();
|
|
574
|
+
}
|
|
541
575
|
}
|
|
542
576
|
/**
|
|
543
577
|
* If `node` is a call like `ARRAY.map(param => ...)` where ARRAY is a known
|
|
@@ -4,6 +4,11 @@ class ScopeManager {
|
|
|
4
4
|
scopeStack = [];
|
|
5
5
|
config;
|
|
6
6
|
scope = new Map();
|
|
7
|
+
// Stack of class scopes; each entry maps a class field name (e.g. `myField`
|
|
8
|
+
// or `#privateField`) to the ScopeInfo derived from its initializer. Used to
|
|
9
|
+
// resolve `const { t } = this.field` and `const { t } = this.field()` patterns
|
|
10
|
+
// inside class methods.
|
|
11
|
+
thisFieldStack = [];
|
|
7
12
|
// Track simple local constants with string literal values to resolve identifier args
|
|
8
13
|
simpleConstants = new Map();
|
|
9
14
|
// Track simple local constant objects with string literal property values
|
|
@@ -61,6 +66,49 @@ class ScopeManager {
|
|
|
61
66
|
this.scope = new Map();
|
|
62
67
|
this.simpleConstants.clear();
|
|
63
68
|
this.simpleConstantObjects.clear();
|
|
69
|
+
this.thisFieldStack = [];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Pushes a new class scope used for tracking class field → ScopeInfo
|
|
73
|
+
* mappings. Should be called when entering a ClassDeclaration or
|
|
74
|
+
* ClassExpression.
|
|
75
|
+
*/
|
|
76
|
+
enterClassScope() {
|
|
77
|
+
this.thisFieldStack.push(new Map());
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Pops the current class scope. Should be called when leaving a
|
|
81
|
+
* ClassDeclaration or ClassExpression.
|
|
82
|
+
*/
|
|
83
|
+
exitClassScope() {
|
|
84
|
+
this.thisFieldStack.pop();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Records a class field's ScopeInfo so that later `this.<field>` or
|
|
88
|
+
* `this.<field>()` accesses inside the class can inherit the namespace
|
|
89
|
+
* and keyPrefix from its initializer.
|
|
90
|
+
*
|
|
91
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
92
|
+
* @param info - Scope information derived from the field's initializer
|
|
93
|
+
*/
|
|
94
|
+
setThisField(fieldName, info) {
|
|
95
|
+
if (this.thisFieldStack.length > 0) {
|
|
96
|
+
this.thisFieldStack[this.thisFieldStack.length - 1].set(fieldName, info);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Looks up a class field's ScopeInfo from the innermost class scope outward.
|
|
101
|
+
*
|
|
102
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
103
|
+
* @returns Scope information if found, undefined otherwise
|
|
104
|
+
*/
|
|
105
|
+
getThisField(fieldName) {
|
|
106
|
+
for (let i = this.thisFieldStack.length - 1; i >= 0; i--) {
|
|
107
|
+
if (this.thisFieldStack[i].has(fieldName)) {
|
|
108
|
+
return this.thisFieldStack[i].get(fieldName);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
64
112
|
}
|
|
65
113
|
/**
|
|
66
114
|
* Enters a new variable scope by pushing a new scope map onto the stack.
|
|
@@ -217,6 +265,17 @@ class ScopeManager {
|
|
|
217
265
|
}
|
|
218
266
|
// continue processing; still may be a useTranslation/getFixedT call below
|
|
219
267
|
}
|
|
268
|
+
// Handle: const { t } = this.#field OR const { t } = this.#field()
|
|
269
|
+
// Resolve the source `this.<field>` to its previously-registered ScopeInfo
|
|
270
|
+
// and propagate it onto the destructured variables.
|
|
271
|
+
const thisFieldName = ScopeManager.extractThisFieldName(init);
|
|
272
|
+
if (thisFieldName !== undefined) {
|
|
273
|
+
const sourceScope = this.getThisField(thisFieldName);
|
|
274
|
+
if (sourceScope) {
|
|
275
|
+
this.attachScopeToDestructuredVars(node, sourceScope);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
220
279
|
// Determine the actual call expression, looking inside AwaitExpressions.
|
|
221
280
|
const callExpr = init.type === 'AwaitExpression' && init.argument.type === 'CallExpression'
|
|
222
281
|
? init.argument
|
|
@@ -543,6 +602,165 @@ class ScopeManager {
|
|
|
543
602
|
this.setVarInScope(targetVarName, { defaultNs: finalNs, keyPrefix: finalKeyPrefix });
|
|
544
603
|
}
|
|
545
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Returns the field name being referenced when an expression takes the form
|
|
607
|
+
* `this.<field>` or `this.<field>()`. Strips the call wrapper if present and
|
|
608
|
+
* prefixes private fields with `#`.
|
|
609
|
+
*
|
|
610
|
+
* Returns undefined if the expression is not such an access.
|
|
611
|
+
*/
|
|
612
|
+
static extractThisFieldName(init) {
|
|
613
|
+
let memberExpr;
|
|
614
|
+
if (init.type === 'MemberExpression') {
|
|
615
|
+
memberExpr = init;
|
|
616
|
+
}
|
|
617
|
+
else if (init.type === 'CallExpression' && init.callee.type === 'MemberExpression') {
|
|
618
|
+
memberExpr = init.callee;
|
|
619
|
+
}
|
|
620
|
+
if (!memberExpr)
|
|
621
|
+
return undefined;
|
|
622
|
+
if (memberExpr.object.type !== 'ThisExpression')
|
|
623
|
+
return undefined;
|
|
624
|
+
const prop = memberExpr.property;
|
|
625
|
+
if (prop?.type === 'Identifier')
|
|
626
|
+
return prop.value;
|
|
627
|
+
if (prop?.type === 'PrivateName')
|
|
628
|
+
return '#' + prop.value;
|
|
629
|
+
return undefined;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Attaches the given ScopeInfo to all destructured variables of a variable
|
|
633
|
+
* declarator (`const { t } = ...`, `const [t] = ...`, or `const t = ...`).
|
|
634
|
+
*/
|
|
635
|
+
attachScopeToDestructuredVars(node, info) {
|
|
636
|
+
if (node.id.type === 'ObjectPattern') {
|
|
637
|
+
for (const prop of node.id.properties) {
|
|
638
|
+
if (prop.type === 'AssignmentPatternProperty' && prop.key.type === 'Identifier') {
|
|
639
|
+
this.setVarInScope(prop.key.value, info);
|
|
640
|
+
}
|
|
641
|
+
if (prop.type === 'KeyValuePatternProperty' && prop.value.type === 'Identifier') {
|
|
642
|
+
this.setVarInScope(prop.value.value, info);
|
|
643
|
+
// Also store under the pattern key name so legacy comment-scope
|
|
644
|
+
// lookups by the original property name continue to work.
|
|
645
|
+
if (prop.key.type === 'Identifier' && (prop.key.value === 't' || prop.key.value === 'getFixedT')) {
|
|
646
|
+
this.scope.set(prop.value.value, { defaultNs: info.defaultNs, keyPrefix: info.keyPrefix });
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
else if (node.id.type === 'Identifier') {
|
|
652
|
+
this.setVarInScope(node.id.value, info);
|
|
653
|
+
}
|
|
654
|
+
else if (node.id.type === 'ArrayPattern') {
|
|
655
|
+
const firstElement = node.id.elements[0];
|
|
656
|
+
if (firstElement?.type === 'Identifier') {
|
|
657
|
+
this.setVarInScope(firstElement.value, info);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Registers a class field's initializer with the current class scope so that
|
|
663
|
+
* later `const { t } = this.<field>` or `const { t } = this.<field>()` calls
|
|
664
|
+
* inside the class body inherit the namespace and keyPrefix from the field
|
|
665
|
+
* initializer.
|
|
666
|
+
*
|
|
667
|
+
* Recognizes the same useTranslation-like patterns supported on regular
|
|
668
|
+
* variable declarations (configured via `useTranslationNames`).
|
|
669
|
+
*
|
|
670
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
671
|
+
* @param value - The field initializer expression
|
|
672
|
+
*/
|
|
673
|
+
registerClassField(fieldName, value) {
|
|
674
|
+
if (!value)
|
|
675
|
+
return;
|
|
676
|
+
if (this.thisFieldStack.length === 0)
|
|
677
|
+
return;
|
|
678
|
+
const callExpr = value.type === 'AwaitExpression' && value.argument.type === 'CallExpression'
|
|
679
|
+
? value.argument
|
|
680
|
+
: value.type === 'CallExpression'
|
|
681
|
+
? value
|
|
682
|
+
: null;
|
|
683
|
+
if (!callExpr)
|
|
684
|
+
return;
|
|
685
|
+
const callee = callExpr.callee;
|
|
686
|
+
if (callee.type !== 'Identifier')
|
|
687
|
+
return;
|
|
688
|
+
const hookConfig = this.getUseTranslationConfig(callee.value);
|
|
689
|
+
if (!hookConfig)
|
|
690
|
+
return;
|
|
691
|
+
const info = this.computeScopeInfoFromHookCall(callExpr, hookConfig);
|
|
692
|
+
if (info.defaultNs || info.keyPrefix) {
|
|
693
|
+
this.setThisField(fieldName, info);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Computes ScopeInfo (defaultNs, keyPrefix) for a useTranslation-style call
|
|
698
|
+
* given a hook configuration that describes argument positions. Mirrors the
|
|
699
|
+
* extraction performed by handleUseTranslationDeclarator without attaching
|
|
700
|
+
* the result to any variable.
|
|
701
|
+
*/
|
|
702
|
+
computeScopeInfoFromHookCall(callExpr, hookConfig) {
|
|
703
|
+
const nsArgIndex = hookConfig.nsArg ?? 0;
|
|
704
|
+
const kpArgIndex = hookConfig.keyPrefixArg ?? 1;
|
|
705
|
+
let defaultNs;
|
|
706
|
+
let keyPrefix;
|
|
707
|
+
const first = callExpr.arguments?.[0]?.expression;
|
|
708
|
+
const second = callExpr.arguments?.[1]?.expression;
|
|
709
|
+
const third = callExpr.arguments?.[2]?.expression;
|
|
710
|
+
const looksLikeLanguage = (s) => /^[a-z]{2,3}([-_][A-Za-z0-9-]+)?$/i.test(s);
|
|
711
|
+
const isBuiltInLngNsForm = hookConfig.name === 'useTranslation' &&
|
|
712
|
+
first?.type === 'StringLiteral' &&
|
|
713
|
+
second?.type === 'StringLiteral' &&
|
|
714
|
+
looksLikeLanguage(first.value);
|
|
715
|
+
let kpArg;
|
|
716
|
+
if (isBuiltInLngNsForm) {
|
|
717
|
+
defaultNs = second.value;
|
|
718
|
+
kpArg = third;
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
if (nsArgIndex !== -1) {
|
|
722
|
+
const nsNode = callExpr.arguments?.[nsArgIndex]?.expression;
|
|
723
|
+
if (nsNode?.type === 'StringLiteral') {
|
|
724
|
+
defaultNs = nsNode.value;
|
|
725
|
+
}
|
|
726
|
+
else if (nsNode?.type === 'Identifier') {
|
|
727
|
+
defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
|
|
728
|
+
}
|
|
729
|
+
else if (nsNode?.type === 'MemberExpression') {
|
|
730
|
+
defaultNs = this.resolveSimpleMemberExpression(nsNode);
|
|
731
|
+
}
|
|
732
|
+
else if (nsNode?.type === 'ArrayExpression') {
|
|
733
|
+
const firstEl = nsNode.elements[0]?.expression;
|
|
734
|
+
if (firstEl?.type === 'StringLiteral') {
|
|
735
|
+
defaultNs = firstEl.value;
|
|
736
|
+
}
|
|
737
|
+
else if (firstEl?.type === 'Identifier') {
|
|
738
|
+
defaultNs = this.resolveSimpleStringIdentifier(firstEl.value);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
|
|
743
|
+
}
|
|
744
|
+
if (kpArg?.type === 'ObjectExpression') {
|
|
745
|
+
const kp = getObjectPropValue(kpArg, 'keyPrefix', this.resolveSimpleStringIdentifier.bind(this));
|
|
746
|
+
if (typeof kp === 'string') {
|
|
747
|
+
keyPrefix = kp;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
else if (kpArg?.type === 'StringLiteral') {
|
|
751
|
+
keyPrefix = kpArg.value;
|
|
752
|
+
}
|
|
753
|
+
else if (kpArg?.type === 'Identifier') {
|
|
754
|
+
keyPrefix = this.resolveSimpleStringIdentifier(kpArg.value);
|
|
755
|
+
}
|
|
756
|
+
else if (kpArg?.type === 'TemplateLiteral') {
|
|
757
|
+
const tpl = kpArg;
|
|
758
|
+
if ((tpl.expressions || []).length === 0) {
|
|
759
|
+
keyPrefix = tpl.quasis?.[0]?.cooked ?? undefined;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return { defaultNs, keyPrefix };
|
|
763
|
+
}
|
|
546
764
|
}
|
|
547
765
|
|
|
548
766
|
export { ScopeManager };
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAItE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAE9B,IAAW,UAAU,gBAEpB;IAED,SAAgB,YAAY,EAAE,YAAY,CAAA;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;IAEhC;;;;;;OAMG;gBAED,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,eAAe,EACvB,kBAAkB,CAAC,EAAE,kBAAkB;IAiCzC;;;;;;;;;;;;;OAaG;IACI,mBAAmB,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/C;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8CzB;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAUjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;
|
|
1
|
+
{"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAItE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAE9B,IAAW,UAAU,gBAEpB;IAED,SAAgB,YAAY,EAAE,YAAY,CAAA;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;IAEhC;;;;;;OAMG;gBAED,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,eAAe,EACvB,kBAAkB,CAAC,EAAE,kBAAkB;IAiCzC;;;;;;;;;;;;;OAaG;IACI,mBAAmB,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/C;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8CzB;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAUjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;IAyZZ;;;;;;;;OAQG;IACH,OAAO,CAAC,gCAAgC;IAqDxC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;;;;;;;OAQG;IACI,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI5D;;OAEG;IACI,cAAc,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxD;;;;;;OAMG;IACI,cAAc,IAAK,MAAM;IAIhC;;OAEG;IACI,cAAc,IAAK,MAAM;CAGjC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { VariableDeclarator } from '@swc/core';
|
|
1
|
+
import type { Expression, VariableDeclarator } from '@swc/core';
|
|
2
2
|
import type { ScopeInfo, I18nextToolkitConfig } from '../../types.js';
|
|
3
3
|
export declare class ScopeManager {
|
|
4
4
|
private scopeStack;
|
|
5
5
|
private config;
|
|
6
6
|
private scope;
|
|
7
|
+
private thisFieldStack;
|
|
7
8
|
private simpleConstants;
|
|
8
9
|
private simpleConstantObjects;
|
|
9
10
|
private sharedConstants;
|
|
@@ -27,6 +28,33 @@ export declare class ScopeManager {
|
|
|
27
28
|
* leak between files.
|
|
28
29
|
*/
|
|
29
30
|
reset(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Pushes a new class scope used for tracking class field → ScopeInfo
|
|
33
|
+
* mappings. Should be called when entering a ClassDeclaration or
|
|
34
|
+
* ClassExpression.
|
|
35
|
+
*/
|
|
36
|
+
enterClassScope(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Pops the current class scope. Should be called when leaving a
|
|
39
|
+
* ClassDeclaration or ClassExpression.
|
|
40
|
+
*/
|
|
41
|
+
exitClassScope(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Records a class field's ScopeInfo so that later `this.<field>` or
|
|
44
|
+
* `this.<field>()` accesses inside the class can inherit the namespace
|
|
45
|
+
* and keyPrefix from its initializer.
|
|
46
|
+
*
|
|
47
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
48
|
+
* @param info - Scope information derived from the field's initializer
|
|
49
|
+
*/
|
|
50
|
+
setThisField(fieldName: string, info: ScopeInfo): void;
|
|
51
|
+
/**
|
|
52
|
+
* Looks up a class field's ScopeInfo from the innermost class scope outward.
|
|
53
|
+
*
|
|
54
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
55
|
+
* @returns Scope information if found, undefined otherwise
|
|
56
|
+
*/
|
|
57
|
+
getThisField(fieldName: string): ScopeInfo | undefined;
|
|
30
58
|
/**
|
|
31
59
|
* Enters a new variable scope by pushing a new scope map onto the stack.
|
|
32
60
|
* Used when entering functions to isolate variable declarations.
|
|
@@ -131,5 +159,38 @@ export declare class ScopeManager {
|
|
|
131
159
|
* resulting scope to the newly declared variable.
|
|
132
160
|
*/
|
|
133
161
|
private handleGetFixedTFromVariableDeclarator;
|
|
162
|
+
/**
|
|
163
|
+
* Returns the field name being referenced when an expression takes the form
|
|
164
|
+
* `this.<field>` or `this.<field>()`. Strips the call wrapper if present and
|
|
165
|
+
* prefixes private fields with `#`.
|
|
166
|
+
*
|
|
167
|
+
* Returns undefined if the expression is not such an access.
|
|
168
|
+
*/
|
|
169
|
+
private static extractThisFieldName;
|
|
170
|
+
/**
|
|
171
|
+
* Attaches the given ScopeInfo to all destructured variables of a variable
|
|
172
|
+
* declarator (`const { t } = ...`, `const [t] = ...`, or `const t = ...`).
|
|
173
|
+
*/
|
|
174
|
+
private attachScopeToDestructuredVars;
|
|
175
|
+
/**
|
|
176
|
+
* Registers a class field's initializer with the current class scope so that
|
|
177
|
+
* later `const { t } = this.<field>` or `const { t } = this.<field>()` calls
|
|
178
|
+
* inside the class body inherit the namespace and keyPrefix from the field
|
|
179
|
+
* initializer.
|
|
180
|
+
*
|
|
181
|
+
* Recognizes the same useTranslation-like patterns supported on regular
|
|
182
|
+
* variable declarations (configured via `useTranslationNames`).
|
|
183
|
+
*
|
|
184
|
+
* @param fieldName - Field name (private fields are prefixed with `#`)
|
|
185
|
+
* @param value - The field initializer expression
|
|
186
|
+
*/
|
|
187
|
+
registerClassField(fieldName: string, value: Expression | null | undefined): void;
|
|
188
|
+
/**
|
|
189
|
+
* Computes ScopeInfo (defaultNs, keyPrefix) for a useTranslation-style call
|
|
190
|
+
* given a hook configuration that describes argument positions. Mirrors the
|
|
191
|
+
* extraction performed by handleUseTranslationDeclarator without attaching
|
|
192
|
+
* the result to any variable.
|
|
193
|
+
*/
|
|
194
|
+
private computeScopeInfoFromHookCall;
|
|
134
195
|
}
|
|
135
196
|
//# sourceMappingURL=scope-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,kBAAkB,EAMnB,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAG/F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;IAMlF,OAAO,CAAC,cAAc,CAAoC;IAG1D,OAAO,CAAC,eAAe,CAAiC;IAGxD,OAAO,CAAC,qBAAqB,CAAiD;IAI9E,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,qBAAqB,CAAiD;gBAEjE,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,+BAA+B;IAgB9C;;;;;;OAMG;IACI,KAAK,IAAK,IAAI;IAQrB;;;;OAIG;IACH,eAAe,IAAK,IAAI;IAIxB;;;OAGG;IACH,cAAc,IAAK,IAAI;IAIvB;;;;;;;OAOG;IACH,YAAY,CAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAMvD;;;;;OAKG;IACH,YAAY,CAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IASvD;;;OAGG;IACH,UAAU,IAAK,IAAI;IAInB;;;OAGG;IACH,SAAS,IAAK,IAAI;IAIlB;;;;;;OAMG;IACH,aAAa,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAUnD;;;;;;OAMG;IACH,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAkBrD,OAAO,CAAC,uBAAuB;IAoB/B;;OAEG;IACI,6BAA6B,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIvE;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAqBrC;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAsGzD;;;;;;;;OAQG;IACH,OAAO,CAAC,+BAA+B;IA0GvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAmFtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;IAiBjC;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAexB;;;;;;;;;OASG;IACH,OAAO,CAAC,qCAAqC;IAqB7C;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAgBnC;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAyBrC;;;;;;;;;;;OAWG;IACH,kBAAkB,CAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAwBlF;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;CA+DrC"}
|