wuchale 0.18.11 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-utils/index.js +5 -5
- package/dist/adapter-utils/mixed-visitor.d.ts +5 -6
- package/dist/adapter-utils/mixed-visitor.js +2 -1
- package/dist/adapter-vanilla/index.js +2 -4
- package/dist/adapter-vanilla/transformer.d.ts +7 -13
- package/dist/adapter-vanilla/transformer.js +56 -61
- package/dist/adapters.d.ts +13 -16
- package/dist/adapters.js +7 -6
- package/dist/ai/gemini.d.ts +2 -1
- package/dist/ai/gemini.js +3 -3
- package/dist/cli/extract.js +9 -8
- package/dist/cli/index.js +14 -8
- package/dist/compile.js +11 -7
- package/dist/config.d.ts +3 -3
- package/dist/config.js +4 -6
- package/dist/handler.d.ts +9 -8
- package/dist/handler.js +139 -118
- package/dist/index.d.ts +1 -1
- package/dist/load-utils/index.d.ts +8 -3
- package/dist/load-utils/index.js +19 -14
- package/dist/log.d.ts +8 -2
- package/dist/log.js +8 -8
- package/dist/runtime.d.ts +5 -5
- package/dist/runtime.js +12 -15
- package/package.json +6 -2
|
@@ -7,13 +7,13 @@ export const varNames = {
|
|
|
7
7
|
};
|
|
8
8
|
export function runtimeVars(wrapFunc, base = varNames.rt) {
|
|
9
9
|
return {
|
|
10
|
-
rtTrans: `${wrapFunc(base)}
|
|
11
|
-
rtTPlural: `${wrapFunc(base)}.
|
|
10
|
+
rtTrans: `${wrapFunc(base)}`,
|
|
11
|
+
rtTPlural: `${wrapFunc(base)}.p`,
|
|
12
12
|
rtPlural: `${wrapFunc(base)}._.p`,
|
|
13
13
|
rtLocale: `${wrapFunc(base)}.l`,
|
|
14
|
-
rtCtx: `${wrapFunc(base)}.
|
|
15
|
-
rtTransCtx: `${wrapFunc(base)}.
|
|
16
|
-
rtTransTag: `${wrapFunc(base)}.
|
|
14
|
+
rtCtx: `${wrapFunc(base)}.c`,
|
|
15
|
+
rtTransCtx: `${wrapFunc(base)}.x`,
|
|
16
|
+
rtTransTag: `${wrapFunc(base)}.t`,
|
|
17
17
|
/** for when nesting, used in adapters with elements */
|
|
18
18
|
nestCtx: '_w_ctx_',
|
|
19
19
|
};
|
|
@@ -2,14 +2,13 @@ import type MagicString from "magic-string";
|
|
|
2
2
|
import { IndexTracker, Message, type HeuristicDetails, type HeuristicDetailsBase, type HeuristicFunc, type MessageType } from "../adapters.js";
|
|
3
3
|
import { type RuntimeVars, type CommentDirectives } from "./index.js";
|
|
4
4
|
type NestedRanges = [number, number, boolean][];
|
|
5
|
-
type BasicNode = {
|
|
6
|
-
start: number;
|
|
7
|
-
end: number;
|
|
8
|
-
};
|
|
9
5
|
type InitProps<NodeT> = {
|
|
10
6
|
vars: () => RuntimeVars;
|
|
11
7
|
mstr: MagicString;
|
|
12
|
-
getRange: (node: NodeT) =>
|
|
8
|
+
getRange: (node: NodeT) => {
|
|
9
|
+
start: number;
|
|
10
|
+
end: number;
|
|
11
|
+
};
|
|
13
12
|
isText: (node: NodeT) => boolean;
|
|
14
13
|
isExpression: (node: NodeT) => boolean;
|
|
15
14
|
isComment: (node: NodeT) => boolean;
|
|
@@ -34,7 +33,7 @@ type VisitProps<NodeT> = {
|
|
|
34
33
|
attribute?: string;
|
|
35
34
|
useComponent?: boolean;
|
|
36
35
|
};
|
|
37
|
-
export interface MixedVisitor<NodeT
|
|
36
|
+
export interface MixedVisitor<NodeT> extends InitProps<NodeT> {
|
|
38
37
|
}
|
|
39
38
|
export declare class MixedVisitor<NodeT> {
|
|
40
39
|
constructor(props: InitProps<NodeT>);
|
|
@@ -171,7 +171,8 @@ export class MixedVisitor {
|
|
|
171
171
|
}
|
|
172
172
|
if (props.scope === 'attribute' && `'"`.includes(this.mstr.original[lastChildEnd])) {
|
|
173
173
|
const firstChild = props.children[0];
|
|
174
|
-
|
|
174
|
+
const { start } = this.getRange(firstChild);
|
|
175
|
+
this.mstr.remove(start - 1, start);
|
|
175
176
|
this.mstr.remove(lastChildEnd, lastChildEnd + 1);
|
|
176
177
|
}
|
|
177
178
|
this.mstr.appendLeft(lastChildEnd, begin);
|
|
@@ -19,10 +19,8 @@ const defaultArgs = {
|
|
|
19
19
|
generateLoadID: defaultGenerateLoadID,
|
|
20
20
|
loader: 'vite',
|
|
21
21
|
runtime: {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
use: false,
|
|
25
|
-
}),
|
|
22
|
+
initReactive: ({ nested }) => nested ? null : false,
|
|
23
|
+
useReactive: false,
|
|
26
24
|
plain: {
|
|
27
25
|
wrapInit: expr => expr,
|
|
28
26
|
wrapUse: expr => expr,
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import MagicString from "magic-string";
|
|
2
2
|
import type * as Estree from "acorn";
|
|
3
3
|
import { Message } from '../adapters.js';
|
|
4
|
-
import type { HeuristicDetailsBase, HeuristicFunc, IndexTracker,
|
|
4
|
+
import type { HeuristicDetailsBase, HeuristicFunc, IndexTracker, TransformOutput, HeuristicDetails, RuntimeConf, CatalogExpr, CodePattern, UrlMatcher, HeuristicResultChecked, MessageType } from "../adapters.js";
|
|
5
5
|
import { type RuntimeVars, type CommentDirectives } from "../adapter-utils/index.js";
|
|
6
6
|
export declare const scriptParseOptions: Estree.Options;
|
|
7
7
|
export declare function scriptParseOptionsWithComments(): [Estree.Options, Estree.Comment[][]];
|
|
8
8
|
export declare function parseScript(content: string): [Estree.Program, Estree.Comment[][]];
|
|
9
|
-
type InitRuntimeFunc = (
|
|
10
|
-
export declare class Transformer {
|
|
9
|
+
type InitRuntimeFunc = (funcName?: string, parentFunc?: string) => string | undefined;
|
|
10
|
+
export declare class Transformer<RTCtxT = {}> {
|
|
11
11
|
index: IndexTracker;
|
|
12
12
|
heuristic: HeuristicFunc;
|
|
13
13
|
content: string;
|
|
14
14
|
comments: Estree.Comment[][];
|
|
15
|
-
filename: string;
|
|
16
15
|
mstr: MagicString;
|
|
17
16
|
patterns: CodePattern[];
|
|
18
17
|
matchUrl: UrlMatcher;
|
|
@@ -20,17 +19,12 @@ export declare class Transformer {
|
|
|
20
19
|
currentRtVar: string;
|
|
21
20
|
vars: () => RuntimeVars;
|
|
22
21
|
commentDirectives: CommentDirectives;
|
|
23
|
-
|
|
24
|
-
declaring?: ScriptDeclType;
|
|
25
|
-
currentFuncNested: boolean;
|
|
26
|
-
currentFuncDef?: string;
|
|
27
|
-
currentCall: string;
|
|
28
|
-
currentTopLevelCall?: string;
|
|
22
|
+
heuristciDetails: HeuristicDetails;
|
|
29
23
|
/** .start of the first statements in their respective parents, to put the runtime init before */
|
|
30
24
|
realBodyStarts: Set<number>;
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf
|
|
25
|
+
/** will be passed to decide which runtime variable to use */
|
|
26
|
+
runtimeCtx: RTCtxT;
|
|
27
|
+
constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf<RTCtxT>, matchUrl: UrlMatcher, rtBaseVars?: string[]);
|
|
34
28
|
fullHeuristicDetails: (detailsBase: HeuristicDetailsBase) => HeuristicDetails;
|
|
35
29
|
getHeuristicMessageType: (msg: Message) => HeuristicResultChecked;
|
|
36
30
|
checkHeuristic: (msgStr: string, detailsBase: HeuristicDetailsBase) => [MessageType, Message] | [false, null];
|
|
@@ -45,7 +45,6 @@ export class Transformer {
|
|
|
45
45
|
content;
|
|
46
46
|
/* for when the comments are not parsed as part of the AST */
|
|
47
47
|
comments = [];
|
|
48
|
-
filename;
|
|
49
48
|
mstr;
|
|
50
49
|
patterns;
|
|
51
50
|
matchUrl;
|
|
@@ -54,27 +53,22 @@ export class Transformer {
|
|
|
54
53
|
vars;
|
|
55
54
|
// state
|
|
56
55
|
commentDirectives = {};
|
|
57
|
-
|
|
58
|
-
declaring;
|
|
59
|
-
currentFuncNested = false;
|
|
60
|
-
currentFuncDef;
|
|
61
|
-
currentCall;
|
|
62
|
-
currentTopLevelCall;
|
|
56
|
+
heuristciDetails = { file: '', scope: 'script', insideProgram: true };
|
|
63
57
|
/** .start of the first statements in their respective parents, to put the runtime init before */
|
|
64
58
|
realBodyStarts = new Set();
|
|
65
|
-
/**
|
|
66
|
-
|
|
59
|
+
/** will be passed to decide which runtime variable to use */
|
|
60
|
+
runtimeCtx = {};
|
|
67
61
|
constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl, rtBaseVars = [varNames.rt]) {
|
|
68
62
|
this.index = index;
|
|
69
63
|
this.heuristic = heuristic;
|
|
70
64
|
this.patterns = patterns;
|
|
71
65
|
this.content = content;
|
|
72
|
-
this.
|
|
66
|
+
this.heuristciDetails.file = filename;
|
|
73
67
|
this.matchUrl = matchUrl;
|
|
74
|
-
const topLevelUseReactive = rtConf.useReactive({
|
|
68
|
+
const topLevelUseReactive = typeof rtConf.useReactive === 'boolean' ? () => rtConf.useReactive : ({
|
|
75
69
|
nested: false,
|
|
76
70
|
file: filename,
|
|
77
|
-
|
|
71
|
+
ctx: this.runtimeCtx,
|
|
78
72
|
});
|
|
79
73
|
const vars = {};
|
|
80
74
|
// to enable the use of different runtime vars for different places, right now for svelte <script module>s
|
|
@@ -86,35 +80,36 @@ export class Transformer {
|
|
|
86
80
|
}
|
|
87
81
|
this.currentRtVar = rtBaseVars[0];
|
|
88
82
|
this.vars = () => {
|
|
89
|
-
const useReactive = rtConf.useReactive({
|
|
90
|
-
funcName: this.
|
|
91
|
-
nested: this.
|
|
83
|
+
const useReactive = typeof rtConf.useReactive === 'boolean' ? rtConf.useReactive : rtConf.useReactive({
|
|
84
|
+
funcName: this.heuristciDetails.funcName ?? undefined,
|
|
85
|
+
nested: this.heuristciDetails.funcIsNested ?? false,
|
|
92
86
|
file: filename,
|
|
93
|
-
|
|
87
|
+
...this.runtimeCtx,
|
|
94
88
|
}) ?? topLevelUseReactive;
|
|
95
89
|
const currentVars = vars[this.currentRtVar];
|
|
96
|
-
return useReactive
|
|
90
|
+
return useReactive ? currentVars.reactive : currentVars.plain;
|
|
97
91
|
};
|
|
98
|
-
this.initRuntime = (
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
this.initRuntime = (funcName, parentFunc) => {
|
|
93
|
+
let initReactive = rtConf.initReactive({
|
|
94
|
+
funcName,
|
|
95
|
+
nested: parentFunc != null,
|
|
96
|
+
file: filename,
|
|
97
|
+
...this.runtimeCtx,
|
|
98
|
+
});
|
|
99
|
+
if (initReactive == null) {
|
|
101
100
|
return;
|
|
102
101
|
}
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
if (typeof rtConf.useReactive === 'boolean') {
|
|
103
|
+
initReactive = rtConf.useReactive; // should be consistent
|
|
104
|
+
}
|
|
105
|
+
const wrapInit = initReactive ? rtConf.reactive.wrapInit : rtConf.plain.wrapInit;
|
|
106
|
+
const expr = initReactive ? catalogExpr.reactive : catalogExpr.plain;
|
|
105
107
|
return `\nconst ${this.currentRtVar} = ${wrapInit(expr)}\n`;
|
|
106
108
|
};
|
|
107
109
|
}
|
|
108
110
|
fullHeuristicDetails = (detailsBase) => {
|
|
109
|
-
const details = {
|
|
110
|
-
|
|
111
|
-
call: this.currentCall,
|
|
112
|
-
declaring: this.declaring,
|
|
113
|
-
funcName: this.currentFuncDef,
|
|
114
|
-
topLevelCall: this.currentTopLevelCall,
|
|
115
|
-
...detailsBase
|
|
116
|
-
};
|
|
117
|
-
if (details.declaring == null && this.insideProgram) {
|
|
111
|
+
const details = { ...this.heuristciDetails, ...detailsBase };
|
|
112
|
+
if (details.declaring == null && details.insideProgram) {
|
|
118
113
|
details.declaring = 'expression';
|
|
119
114
|
}
|
|
120
115
|
return details;
|
|
@@ -182,12 +177,12 @@ export class Transformer {
|
|
|
182
177
|
visitNewExpression = (node) => node.arguments.map(this.visit).flat();
|
|
183
178
|
defaultVisitCallExpression = (node) => {
|
|
184
179
|
const msgs = this.visit(node.callee);
|
|
185
|
-
const currentCall = this.
|
|
186
|
-
this.
|
|
180
|
+
const currentCall = this.heuristciDetails.call;
|
|
181
|
+
this.heuristciDetails.call = this.getCalleeName(node.callee);
|
|
187
182
|
for (const arg of node.arguments) {
|
|
188
183
|
msgs.push(...this.visit(arg));
|
|
189
184
|
}
|
|
190
|
-
this.
|
|
185
|
+
this.heuristciDetails.call = currentCall; // restore
|
|
191
186
|
return msgs;
|
|
192
187
|
};
|
|
193
188
|
visitCallExpression = (node) => {
|
|
@@ -368,25 +363,25 @@ export class Transformer {
|
|
|
368
363
|
return `[${callee.type}]`;
|
|
369
364
|
};
|
|
370
365
|
defaultVisitVariableDeclarator = (node) => {
|
|
371
|
-
let atTopLevelDefn = this.insideProgram && !this.declaring;
|
|
366
|
+
let atTopLevelDefn = this.heuristciDetails.insideProgram && !this.heuristciDetails.declaring;
|
|
372
367
|
if (!node.init) {
|
|
373
368
|
return [];
|
|
374
369
|
}
|
|
375
370
|
if (atTopLevelDefn) {
|
|
376
371
|
if (node.init.type === 'ArrowFunctionExpression' || node.init.type === 'FunctionExpression') {
|
|
377
|
-
this.declaring = 'function';
|
|
372
|
+
this.heuristciDetails.declaring = 'function';
|
|
378
373
|
}
|
|
379
374
|
else {
|
|
380
|
-
this.declaring = 'variable';
|
|
375
|
+
this.heuristciDetails.declaring = 'variable';
|
|
381
376
|
if (node.init.type === 'CallExpression') {
|
|
382
|
-
this.
|
|
377
|
+
this.heuristciDetails.topLevelCall = this.getCalleeName(node.init.callee);
|
|
383
378
|
}
|
|
384
379
|
}
|
|
385
380
|
}
|
|
386
381
|
const msgs = [...this.visit(node.id), ...this.visit(node.init)];
|
|
387
382
|
if (atTopLevelDefn) {
|
|
388
|
-
this.
|
|
389
|
-
this.declaring = undefined;
|
|
383
|
+
this.heuristciDetails.topLevelCall = undefined; // reset
|
|
384
|
+
this.heuristciDetails.declaring = undefined;
|
|
390
385
|
}
|
|
391
386
|
return msgs;
|
|
392
387
|
};
|
|
@@ -432,13 +427,13 @@ export class Transformer {
|
|
|
432
427
|
return nonLiteralStart ?? nodes[0]?.start;
|
|
433
428
|
};
|
|
434
429
|
visitFunctionBody = (node, name, end) => {
|
|
435
|
-
const prevFuncDef = this.
|
|
436
|
-
const prevFuncNested = this.
|
|
437
|
-
this.
|
|
438
|
-
this.
|
|
430
|
+
const prevFuncDef = this.heuristciDetails.funcName;
|
|
431
|
+
const prevFuncNested = this.heuristciDetails.funcIsNested;
|
|
432
|
+
this.heuristciDetails.funcName = name;
|
|
433
|
+
this.heuristciDetails.funcIsNested = name != null && prevFuncDef != null;
|
|
439
434
|
const msgs = this.visit(node);
|
|
440
435
|
if (msgs.length > 0) {
|
|
441
|
-
const initRuntime = this.initRuntime(this.
|
|
436
|
+
const initRuntime = this.initRuntime(this.heuristciDetails.funcName, prevFuncDef ?? undefined);
|
|
442
437
|
if (initRuntime) {
|
|
443
438
|
if (node.type === 'BlockStatement') {
|
|
444
439
|
this.mstr.prependLeft(this.getRealBodyStart(node.body) ?? node.start, initRuntime);
|
|
@@ -461,15 +456,15 @@ export class Transformer {
|
|
|
461
456
|
}
|
|
462
457
|
}
|
|
463
458
|
}
|
|
464
|
-
this.
|
|
465
|
-
this.
|
|
459
|
+
this.heuristciDetails.funcIsNested = prevFuncNested;
|
|
460
|
+
this.heuristciDetails.funcName = prevFuncDef;
|
|
466
461
|
return msgs;
|
|
467
462
|
};
|
|
468
463
|
visitFunctionDeclaration = (node) => {
|
|
469
|
-
const declaring = this.declaring;
|
|
470
|
-
this.declaring = 'function';
|
|
464
|
+
const declaring = this.heuristciDetails.declaring;
|
|
465
|
+
this.heuristciDetails.declaring = 'function';
|
|
471
466
|
const msgs = this.visitFunctionBody(node.body, node.id?.name ?? '');
|
|
472
|
-
this.declaring = declaring;
|
|
467
|
+
this.heuristciDetails.declaring = declaring;
|
|
473
468
|
return msgs;
|
|
474
469
|
};
|
|
475
470
|
visitArrowFunctionExpression = (node) => this.visitFunctionBody(node.body, '', node.end);
|
|
@@ -486,8 +481,8 @@ export class Transformer {
|
|
|
486
481
|
};
|
|
487
482
|
visitClassDeclaration = (node) => {
|
|
488
483
|
const msgs = [];
|
|
489
|
-
const prevDecl = this.declaring;
|
|
490
|
-
this.declaring = 'class';
|
|
484
|
+
const prevDecl = this.heuristciDetails.declaring;
|
|
485
|
+
this.heuristciDetails.declaring = 'class';
|
|
491
486
|
for (const body of node.body.body) {
|
|
492
487
|
if (body.type === 'MethodDefinition') {
|
|
493
488
|
msgs.push(...this.visit(body.key));
|
|
@@ -497,13 +492,13 @@ export class Transformer {
|
|
|
497
492
|
}
|
|
498
493
|
}
|
|
499
494
|
else if (body.type === 'StaticBlock') {
|
|
500
|
-
const currentFuncDef = this.
|
|
501
|
-
this.
|
|
495
|
+
const currentFuncDef = this.heuristciDetails.funcName;
|
|
496
|
+
this.heuristciDetails.funcName = `${node.id.name}.[static]`;
|
|
502
497
|
msgs.push(...body.body.map(this.visit).flat());
|
|
503
|
-
this.
|
|
498
|
+
this.heuristciDetails.funcName = currentFuncDef; // restore
|
|
504
499
|
}
|
|
505
500
|
}
|
|
506
|
-
this.declaring = prevDecl; // restore
|
|
501
|
+
this.heuristciDetails.declaring = prevDecl; // restore
|
|
507
502
|
return msgs;
|
|
508
503
|
};
|
|
509
504
|
checkHeuristicTemplateLiteral = (node, heurDetails) => {
|
|
@@ -568,8 +563,8 @@ export class Transformer {
|
|
|
568
563
|
return msgs;
|
|
569
564
|
};
|
|
570
565
|
visitTaggedTemplateExpression = (node) => {
|
|
571
|
-
const prevCall = this.
|
|
572
|
-
this.
|
|
566
|
+
const prevCall = this.heuristciDetails.call;
|
|
567
|
+
this.heuristciDetails.call = this.getCalleeName(node.tag);
|
|
573
568
|
let msgs = [];
|
|
574
569
|
const heuRes = this.checkHeuristicTemplateLiteral(node.quasi);
|
|
575
570
|
if (heuRes) {
|
|
@@ -586,7 +581,7 @@ export class Transformer {
|
|
|
586
581
|
this.mstr.update(start, end, `, ${index})`);
|
|
587
582
|
}
|
|
588
583
|
}
|
|
589
|
-
this.
|
|
584
|
+
this.heuristciDetails.call = prevCall;
|
|
590
585
|
return msgs;
|
|
591
586
|
};
|
|
592
587
|
visitSwitchStatement = (node) => node.cases.map(c => c.consequent.map(this.visit)).flat().flat();
|
|
@@ -603,9 +598,9 @@ export class Transformer {
|
|
|
603
598
|
visitTSAsExpression = (node) => this.visit(node.expression);
|
|
604
599
|
visitTSTypeAssertion = (node) => this.visit(node.expression);
|
|
605
600
|
visitProgram = (node) => {
|
|
606
|
-
this.insideProgram = true;
|
|
601
|
+
this.heuristciDetails.insideProgram = true;
|
|
607
602
|
const msgs = this.visitStatementsNSaveRealBodyStart(node.body);
|
|
608
|
-
this.insideProgram = false;
|
|
603
|
+
this.heuristciDetails.insideProgram = false;
|
|
609
604
|
return msgs;
|
|
610
605
|
};
|
|
611
606
|
visitWithCommentDirectives = (node, func) => {
|
package/dist/adapters.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export type HeuristicDetails = HeuristicDetailsBase & {
|
|
|
11
11
|
file: string;
|
|
12
12
|
declaring?: ScriptDeclType;
|
|
13
13
|
funcName?: string | null;
|
|
14
|
+
funcIsNested?: boolean;
|
|
15
|
+
insideProgram: boolean;
|
|
14
16
|
topLevelCall?: string;
|
|
15
17
|
call?: string;
|
|
16
18
|
};
|
|
@@ -43,7 +45,7 @@ export declare const defaultHeuristic: HeuristicFunc;
|
|
|
43
45
|
export declare const defaultHeuristicFuncOnly: HeuristicFunc;
|
|
44
46
|
export declare const defaultGenerateLoadID: (filename: string) => string;
|
|
45
47
|
export declare class IndexTracker {
|
|
46
|
-
indices:
|
|
48
|
+
indices: Map<string, number>;
|
|
47
49
|
nextIndex: number;
|
|
48
50
|
get: (msgStr: string) => number;
|
|
49
51
|
}
|
|
@@ -55,9 +57,6 @@ export type CatalogExpr = {
|
|
|
55
57
|
plain: string;
|
|
56
58
|
reactive: string;
|
|
57
59
|
};
|
|
58
|
-
export type TransformHeader = {
|
|
59
|
-
head: string;
|
|
60
|
-
};
|
|
61
60
|
export type UrlMatcher = (url: string) => string | null | undefined;
|
|
62
61
|
type TransformCtx = {
|
|
63
62
|
content: string;
|
|
@@ -81,22 +80,19 @@ export type TransformOutput = {
|
|
|
81
80
|
export type TransformFunc = (expr: TransformCtx) => TransformOutput;
|
|
82
81
|
export type TransformFuncAsync = (expr: TransformCtx) => Promise<TransformOutput>;
|
|
83
82
|
export type WrapFunc = (expr: string) => string;
|
|
84
|
-
export type
|
|
83
|
+
export type DecideReactiveDetails<RTCtxT> = RTCtxT & {
|
|
85
84
|
funcName?: string;
|
|
86
85
|
nested: boolean;
|
|
87
86
|
file: string;
|
|
88
|
-
additional: object;
|
|
89
|
-
}) => {
|
|
90
|
-
/** null to disable initializing */
|
|
91
|
-
init: boolean | null;
|
|
92
|
-
use: boolean;
|
|
93
87
|
};
|
|
94
88
|
type RuntimeConfDetails = {
|
|
95
89
|
wrapInit: WrapFunc;
|
|
96
90
|
wrapUse: WrapFunc;
|
|
97
91
|
};
|
|
98
|
-
export type RuntimeConf = {
|
|
99
|
-
|
|
92
|
+
export type RuntimeConf<RTCtxT = {}> = {
|
|
93
|
+
/** return null to disable */
|
|
94
|
+
initReactive: (details: DecideReactiveDetails<RTCtxT>) => boolean | null;
|
|
95
|
+
useReactive: boolean | ((details: DecideReactiveDetails<RTCtxT>) => boolean);
|
|
100
96
|
plain: RuntimeConfDetails;
|
|
101
97
|
reactive: RuntimeConfDetails;
|
|
102
98
|
};
|
|
@@ -104,7 +100,8 @@ export type LoaderPath = {
|
|
|
104
100
|
client: string;
|
|
105
101
|
server: string;
|
|
106
102
|
};
|
|
107
|
-
export type AdapterPassThruOpts = {
|
|
103
|
+
export type AdapterPassThruOpts<RTCtxT extends {} = {}> = {
|
|
104
|
+
sourceLocale?: string;
|
|
108
105
|
files: GlobConf;
|
|
109
106
|
localesDir: string;
|
|
110
107
|
/** if writing transformed code to a directory is desired, specify this */
|
|
@@ -116,9 +113,9 @@ export type AdapterPassThruOpts = {
|
|
|
116
113
|
localize?: boolean | URLLocalizer;
|
|
117
114
|
};
|
|
118
115
|
generateLoadID: (filename: string) => string;
|
|
119
|
-
runtime: Partial<RuntimeConf
|
|
116
|
+
runtime: Partial<RuntimeConf<RTCtxT>>;
|
|
120
117
|
};
|
|
121
|
-
export type Adapter = AdapterPassThruOpts & {
|
|
118
|
+
export type Adapter<RTCtxT extends {} = {}> = AdapterPassThruOpts<RTCtxT> & {
|
|
122
119
|
transform: TransformFunc | TransformFuncAsync;
|
|
123
120
|
/** possible filename extensions for loader. E.g. `.js` */
|
|
124
121
|
loaderExts: string[];
|
|
@@ -132,7 +129,7 @@ export type CodePattern = {
|
|
|
132
129
|
args: ('message' | 'pluralFunc' | 'locale' | 'other')[];
|
|
133
130
|
};
|
|
134
131
|
export type LoaderChoice<LoadersAvailable> = LoadersAvailable | string & {} | 'custom';
|
|
135
|
-
export type AdapterArgs<LoadersAvailable> = AdapterPassThruOpts & {
|
|
132
|
+
export type AdapterArgs<LoadersAvailable, RTCtxT extends {} = {}> = AdapterPassThruOpts<RTCtxT> & {
|
|
136
133
|
loader: LoaderChoice<LoadersAvailable>;
|
|
137
134
|
heuristic: HeuristicFunc;
|
|
138
135
|
patterns: CodePattern[];
|
package/dist/adapters.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const someHeuDet = { file: '', scope: 'markup' };
|
|
1
|
+
const someHeuDet = { file: '', scope: 'markup', insideProgram: true };
|
|
2
2
|
export class Message {
|
|
3
3
|
msgStr; // array for plurals
|
|
4
4
|
plural = false;
|
|
@@ -93,14 +93,15 @@ export const defaultHeuristicFuncOnly = msg => {
|
|
|
93
93
|
};
|
|
94
94
|
export const defaultGenerateLoadID = (filename) => filename.replace(/[^a-zA-Z0-9_]+/g, '_');
|
|
95
95
|
export class IndexTracker {
|
|
96
|
-
indices =
|
|
96
|
+
indices = new Map();
|
|
97
97
|
nextIndex = 0;
|
|
98
98
|
get = (msgStr) => {
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
let index = this.indices.get(msgStr);
|
|
100
|
+
if (index != null) {
|
|
101
|
+
return index;
|
|
101
102
|
}
|
|
102
|
-
|
|
103
|
-
this.indices
|
|
103
|
+
index = this.nextIndex;
|
|
104
|
+
this.indices.set(msgStr, index);
|
|
104
105
|
this.nextIndex++;
|
|
105
106
|
return index;
|
|
106
107
|
};
|
package/dist/ai/gemini.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { AI } from './index.js';
|
|
2
2
|
type GeminiOpts = {
|
|
3
3
|
apiKey?: string;
|
|
4
|
+
model?: string;
|
|
4
5
|
batchSize?: number;
|
|
5
6
|
think?: boolean;
|
|
6
7
|
parallel?: number;
|
|
7
8
|
};
|
|
8
|
-
export declare function gemini({ apiKey, batchSize, think, parallel }?: GeminiOpts): AI | null;
|
|
9
|
+
export declare function gemini({ apiKey, model, batchSize, think, parallel }?: GeminiOpts): AI | null;
|
|
9
10
|
export declare const defaultGemini: AI | null;
|
|
10
11
|
export {};
|
package/dist/ai/gemini.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const url = 'https://generativelanguage.googleapis.com/v1beta/models/
|
|
1
|
+
const url = 'https://generativelanguage.googleapis.com/v1beta/models/';
|
|
2
2
|
const headers = { 'Content-Type': 'application/json' };
|
|
3
3
|
function prepareData(content, instruction, think) {
|
|
4
4
|
return {
|
|
@@ -13,7 +13,7 @@ function prepareData(content, instruction, think) {
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
export function gemini({ apiKey = 'env', batchSize = 50, think = false, parallel = 4 } = {}) {
|
|
16
|
+
export function gemini({ apiKey = 'env', model = 'gemini-2.5-flash', batchSize = 50, think = false, parallel = 4 } = {}) {
|
|
17
17
|
if (apiKey === 'env') {
|
|
18
18
|
apiKey = process.env.GEMINI_API_KEY ?? '';
|
|
19
19
|
}
|
|
@@ -26,7 +26,7 @@ export function gemini({ apiKey = 'env', batchSize = 50, think = false, parallel
|
|
|
26
26
|
parallel,
|
|
27
27
|
translate: async (content, instruction) => {
|
|
28
28
|
const data = prepareData(content, instruction, think);
|
|
29
|
-
const res = await fetch(url
|
|
29
|
+
const res = await fetch(`${url}${model}:generateContent`, {
|
|
30
30
|
method: 'POST',
|
|
31
31
|
headers: { ...headers, 'x-goog-api-key': apiKey },
|
|
32
32
|
body: JSON.stringify(data)
|
package/dist/cli/extract.js
CHANGED
|
@@ -2,20 +2,21 @@ import { AdapterHandler } from "../handler.js";
|
|
|
2
2
|
import { color, Logger } from "../log.js";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { watch as watchFS } from 'chokidar';
|
|
5
|
-
function extractor(handler) {
|
|
5
|
+
function extractor(handler, logger) {
|
|
6
6
|
const adapterName = color.magenta(handler.key);
|
|
7
7
|
return async (filename) => {
|
|
8
|
-
|
|
8
|
+
logger.info(`${adapterName}: Extract from ${color.cyan(filename)}`);
|
|
9
9
|
const contents = await readFile(filename);
|
|
10
10
|
await handler.transform(contents.toString(), filename);
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
export async function extract(config, clean, watch, sync) {
|
|
14
|
-
|
|
14
|
+
const logger = new Logger(config.logLevel);
|
|
15
|
+
!watch && logger.info('Extracting...');
|
|
15
16
|
const handlers = [];
|
|
16
|
-
const sharedState =
|
|
17
|
+
const sharedState = new Map();
|
|
17
18
|
for (const [key, adapter] of Object.entries(config.adapters)) {
|
|
18
|
-
const handler = new AdapterHandler(adapter, key, config, 'cli', process.cwd(),
|
|
19
|
+
const handler = new AdapterHandler(adapter, key, config, 'cli', process.cwd(), logger);
|
|
19
20
|
await handler.init(sharedState);
|
|
20
21
|
handlers.push(handler);
|
|
21
22
|
}
|
|
@@ -24,12 +25,12 @@ export async function extract(config, clean, watch, sync) {
|
|
|
24
25
|
await handler.directScanFS(clean, sync);
|
|
25
26
|
}
|
|
26
27
|
if (!watch) {
|
|
27
|
-
|
|
28
|
+
logger.info('Extraction finished.');
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
31
|
// watch
|
|
31
|
-
|
|
32
|
-
const handlersWithExtr = handlers.map(h => [h.fileMatches, extractor(h)]);
|
|
32
|
+
logger.info('Watching for changes');
|
|
33
|
+
const handlersWithExtr = handlers.map(h => [h.fileMatches, extractor(h, logger)]);
|
|
33
34
|
watchFS('.', { ignoreInitial: true }).on('all', async (event, filename) => {
|
|
34
35
|
if (!['add', 'change'].includes(event)) {
|
|
35
36
|
return;
|
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { defaultConfigNames, getConfig } from "../config.js";
|
|
3
3
|
import { parseArgs } from 'node:util';
|
|
4
|
-
import { color } from "../log.js";
|
|
4
|
+
import { color, logLevels } from "../log.js";
|
|
5
5
|
import { extract } from "./extract.js";
|
|
6
6
|
import { status } from "./status.js";
|
|
7
7
|
const { positionals, values } = parseArgs({
|
|
@@ -23,6 +23,11 @@ const { positionals, values } = parseArgs({
|
|
|
23
23
|
type: 'boolean',
|
|
24
24
|
default: false,
|
|
25
25
|
},
|
|
26
|
+
'log-level': {
|
|
27
|
+
type: 'string',
|
|
28
|
+
short: 'l',
|
|
29
|
+
default: 'info',
|
|
30
|
+
},
|
|
26
31
|
help: {
|
|
27
32
|
type: 'boolean',
|
|
28
33
|
short: 'h',
|
|
@@ -41,16 +46,17 @@ Commands:
|
|
|
41
46
|
${color.cyan('status')} Show current status
|
|
42
47
|
|
|
43
48
|
Options:
|
|
44
|
-
${color.cyan('--config')}
|
|
45
|
-
${color.cyan('--clean')}, ${color.cyan('-c')}
|
|
46
|
-
${color.cyan('--watch')}, ${color.cyan('-w')}
|
|
47
|
-
${color.cyan('--sync')}
|
|
48
|
-
${color.cyan('--
|
|
49
|
+
${color.cyan('--config')} use another config file instead of ${defaultConfigNames.map(color.cyan).join('|')}
|
|
50
|
+
${color.cyan('--clean')}, ${color.cyan('-c')} (only when no commands) remove unused messages from catalogs
|
|
51
|
+
${color.cyan('--watch')}, ${color.cyan('-w')} (only when no commands) continuously watch for file changes
|
|
52
|
+
${color.cyan('--sync')} (only when no commands) extract sequentially instead of in parallel
|
|
53
|
+
${color.cyan('--log-level')}, ${color.cyan('-l')} {${Object.keys(logLevels).map(color.cyan)}} (only when no commands) set log level
|
|
54
|
+
${color.cyan('--help')}, ${color.cyan('-h')} Show this help
|
|
49
55
|
`;
|
|
50
56
|
async function getConfigNLocales() {
|
|
51
57
|
const config = await getConfig(values.config);
|
|
52
|
-
|
|
53
|
-
return [config, locales];
|
|
58
|
+
config.logLevel = values["log-level"];
|
|
59
|
+
return [config, config.locales];
|
|
54
60
|
}
|
|
55
61
|
if (values.help) {
|
|
56
62
|
console.log('wuchale cli');
|
package/dist/compile.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
const OPEN = Symbol();
|
|
2
|
+
const CLOSE = Symbol();
|
|
3
|
+
const SELF_CLOSE = Symbol();
|
|
4
|
+
const PLACEHOLDER = Symbol();
|
|
1
5
|
const digitRange = ['0', '9'].map(d => d.charCodeAt(0));
|
|
2
6
|
function extractSpecial(msgStr, start) {
|
|
3
7
|
const inPlaceHolder = msgStr[start] === '{';
|
|
@@ -32,18 +36,18 @@ function extractSpecial(msgStr, start) {
|
|
|
32
36
|
if (endChar !== '}') {
|
|
33
37
|
return [null, null, start];
|
|
34
38
|
}
|
|
35
|
-
return [
|
|
39
|
+
return [PLACEHOLDER, n, i + 1];
|
|
36
40
|
}
|
|
37
41
|
if (endChar === '/' && msgStr[i + 1] === '>') {
|
|
38
|
-
return [
|
|
42
|
+
return [SELF_CLOSE, n, i + 2];
|
|
39
43
|
}
|
|
40
44
|
if (endChar != '>') {
|
|
41
45
|
return [null, null, start];
|
|
42
46
|
}
|
|
43
47
|
if (inClose) {
|
|
44
|
-
return [
|
|
48
|
+
return [CLOSE, n, i + 1];
|
|
45
49
|
}
|
|
46
|
-
return [
|
|
50
|
+
return [OPEN, n, i + 1];
|
|
47
51
|
}
|
|
48
52
|
function compile(msgStr, start = 0, parentTag = null) {
|
|
49
53
|
let curTxt = '';
|
|
@@ -63,14 +67,14 @@ function compile(msgStr, start = 0, parentTag = null) {
|
|
|
63
67
|
compiled.push(curTxt);
|
|
64
68
|
curTxt = '';
|
|
65
69
|
}
|
|
66
|
-
if (type ===
|
|
70
|
+
if (type === OPEN) {
|
|
67
71
|
currentOpenTag = n;
|
|
68
72
|
const [subExt, newIc] = compile(msgStr, newI, n);
|
|
69
73
|
compiled.push([n, ...subExt]);
|
|
70
74
|
i = newIc;
|
|
71
75
|
continue;
|
|
72
76
|
}
|
|
73
|
-
if (type ===
|
|
77
|
+
if (type === CLOSE) {
|
|
74
78
|
if (currentOpenTag != null) {
|
|
75
79
|
if (currentOpenTag != n) {
|
|
76
80
|
throw Error('Closing a different tag');
|
|
@@ -84,7 +88,7 @@ function compile(msgStr, start = 0, parentTag = null) {
|
|
|
84
88
|
throw Error('Closing a different tag');
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
|
-
else if (type ===
|
|
91
|
+
else if (type === SELF_CLOSE) {
|
|
88
92
|
compiled.push([n]);
|
|
89
93
|
}
|
|
90
94
|
else { // placeholder
|