wuchale 0.23.4 → 0.24.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.
Files changed (46) hide show
  1. package/dist/adapter-utils/mixed-visitor.d.ts +21 -14
  2. package/dist/adapter-utils/mixed-visitor.js +110 -101
  3. package/dist/adapter-vanilla/index.js +8 -6
  4. package/dist/adapter-vanilla/inertvisitors.d.ts +31 -0
  5. package/dist/adapter-vanilla/inertvisitors.js +86 -0
  6. package/dist/adapter-vanilla/transformer.d.ts +67 -95
  7. package/dist/adapter-vanilla/transformer.js +288 -241
  8. package/dist/adapters.d.ts +16 -12
  9. package/dist/adapters.js +33 -13
  10. package/dist/ai/gemini.js +1 -1
  11. package/dist/ai/index.js +3 -1
  12. package/dist/bundlers/vite.d.ts +1 -1
  13. package/dist/bundlers/vite.js +3 -3
  14. package/dist/cli/check.js +1 -1
  15. package/dist/cli/index.js +12 -5
  16. package/dist/cli/status.js +1 -1
  17. package/dist/config.d.ts +2 -1
  18. package/dist/config.js +2 -2
  19. package/dist/handler/files.d.ts +11 -13
  20. package/dist/handler/files.js +37 -44
  21. package/dist/handler/index.d.ts +7 -4
  22. package/dist/handler/index.js +85 -62
  23. package/dist/handler/state.d.ts +10 -11
  24. package/dist/handler/state.js +40 -28
  25. package/dist/handler/url.d.ts +10 -13
  26. package/dist/handler/url.js +51 -80
  27. package/dist/hub.d.ts +1 -1
  28. package/dist/hub.js +16 -14
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +2 -2
  31. package/dist/load-utils/index.d.ts +6 -8
  32. package/dist/load-utils/index.js +11 -11
  33. package/dist/load-utils/pure.d.ts +2 -2
  34. package/dist/load-utils/server.d.ts +3 -3
  35. package/dist/load-utils/server.js +4 -7
  36. package/dist/pofile.d.ts +5 -5
  37. package/dist/pofile.js +23 -35
  38. package/dist/storage.d.ts +6 -3
  39. package/dist/storage.js +98 -0
  40. package/dist/url.d.ts +12 -10
  41. package/dist/url.js +206 -31
  42. package/package.json +4 -5
  43. package/src/adapter-vanilla/loaders/bundle.js +1 -1
  44. package/src/adapter-vanilla/loaders/server.js +3 -3
  45. package/src/adapter-vanilla/loaders/vite.js +2 -2
  46. package/src/adapter-vanilla/loaders/vite.ssr.js +3 -3
@@ -4,6 +4,7 @@ import { Parser } from 'acorn';
4
4
  import MagicString from 'magic-string';
5
5
  import { restoreCommentDirectives, runtimeVars, updateCommentDirectives, varNames, } from '../adapter-utils/index.js';
6
6
  import { defaultHeuristicFuncOnly, getKey, newMessage } from '../adapters.js';
7
+ import InertVisitors from './inertvisitors.js';
7
8
  export const scriptParseOptions = {
8
9
  sourceType: 'module',
9
10
  ecmaVersion: 'latest',
@@ -44,7 +45,13 @@ export function parseScript(content) {
44
45
  const [opts, comments] = scriptParseOptionsWithComments();
45
46
  return [ScriptParser.parse(content, opts), comments];
46
47
  }
47
- export class Transformer {
48
+ const extendPropDownTypes = [
49
+ 'Literal',
50
+ 'TemplateLiteral',
51
+ 'TaggedTemplateExpression',
52
+ 'ObjectExpression',
53
+ ];
54
+ export class Transformer extends InertVisitors {
48
55
  index;
49
56
  heuristic;
50
57
  content;
@@ -53,6 +60,7 @@ export class Transformer {
53
60
  mstr;
54
61
  patterns;
55
62
  matchUrl;
63
+ initReactive;
56
64
  initRuntime;
57
65
  currentRtVar;
58
66
  vars;
@@ -63,20 +71,21 @@ export class Transformer {
63
71
  realBodyStarts = new Set();
64
72
  /** will be passed to decide which runtime variable to use */
65
73
  runtimeCtx = {};
66
- constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl, rtBaseVars = [varNames.rt]) {
67
- this.index = index;
74
+ constructor(ctx, heuristic, patterns, rtConf, rtBaseVars = [varNames.rt]) {
75
+ super();
76
+ this.index = ctx.index;
77
+ this.content = ctx.content;
78
+ this.matchUrl = ctx.matchUrl;
79
+ this.heuristciDetails.file = ctx.filename;
68
80
  this.heuristic = heuristic;
69
81
  this.patterns = patterns;
70
- this.content = content;
71
82
  this.mstr = new MagicString(this.content);
72
- this.heuristciDetails.file = filename;
73
- this.matchUrl = matchUrl;
74
83
  const topLevelUseReactive = typeof rtConf.useReactive === 'boolean'
75
84
  ? rtConf.useReactive
76
85
  : (rtConf.useReactive({
77
86
  funcName: undefined,
78
87
  nested: false,
79
- file: filename,
88
+ file: ctx.filename,
80
89
  ctx: this.runtimeCtx,
81
90
  }) ?? false);
82
91
  const vars = {};
@@ -94,19 +103,20 @@ export class Transformer {
94
103
  : (rtConf.useReactive({
95
104
  funcName: this.heuristciDetails.funcName ?? undefined,
96
105
  nested: this.heuristciDetails.funcIsNested ?? false,
97
- file: filename,
106
+ file: ctx.filename,
98
107
  ctx: this.runtimeCtx,
99
108
  }) ?? topLevelUseReactive);
100
109
  const currentVars = vars[this.currentRtVar];
101
110
  return useReactive ? currentVars.reactive : currentVars.plain;
102
111
  };
112
+ this.initReactive = (funcName, parentFunc) => rtConf.initReactive({
113
+ funcName,
114
+ nested: parentFunc != null,
115
+ file: ctx.filename,
116
+ ctx: this.runtimeCtx,
117
+ });
103
118
  this.initRuntime = (funcName, parentFunc) => {
104
- let initReactive = rtConf.initReactive({
105
- funcName,
106
- nested: parentFunc != null,
107
- file: filename,
108
- ctx: this.runtimeCtx,
109
- });
119
+ let initReactive = this.initReactive(funcName, parentFunc);
110
120
  if (initReactive == null) {
111
121
  return;
112
122
  }
@@ -114,15 +124,17 @@ export class Transformer {
114
124
  initReactive = rtConf.useReactive; // should be consistent
115
125
  }
116
126
  const wrapInit = initReactive ? rtConf.reactive.wrapInit : rtConf.plain.wrapInit;
117
- const expr = initReactive ? catalogExpr.reactive : catalogExpr.plain;
127
+ const expr = initReactive ? ctx.expr.reactive : ctx.expr.plain;
118
128
  return `\nconst ${this.currentRtVar} = ${wrapInit(expr)};\n`;
119
129
  };
120
130
  }
121
- fullHeuristicDetails = (detailsBase) => ({
122
- ...this.heuristciDetails,
123
- ...detailsBase,
124
- });
125
- getHeuristicMessageType = (msg) => {
131
+ fullHeuristicDetails(detailsBase) {
132
+ return {
133
+ ...this.heuristciDetails,
134
+ ...detailsBase,
135
+ };
136
+ }
137
+ getHeuristicMessageType(msg) {
126
138
  const msgStr = msg.msgStr.join('\n');
127
139
  if (!msgStr) {
128
140
  // nothing to ask
@@ -136,8 +148,8 @@ export class Transformer {
136
148
  return false;
137
149
  }
138
150
  return this.commentDirectives.forceType || heuRes;
139
- };
140
- checkHeuristic = (msgStr, detailsBase) => {
151
+ }
152
+ checkHeuristic(msgStr, detailsBase) {
141
153
  if (!msgStr) {
142
154
  // nothing to ask
143
155
  return [false, null];
@@ -148,12 +160,13 @@ export class Transformer {
148
160
  context: this.commentDirectives.context,
149
161
  });
150
162
  const heuRes = this.getHeuristicMessageType(msg);
151
- if (!heuRes) {
163
+ // not allowed here, or msg is new but new msgs are not allowed
164
+ if (!heuRes || !this.index.has(getKey(msg.msgStr, msg.context))) {
152
165
  return [false, null];
153
166
  }
154
167
  msg.type = heuRes;
155
168
  return [heuRes, msg];
156
- };
169
+ }
157
170
  literalRepl(msgInfo) {
158
171
  const repl = `${this.vars().rtTrans}(${this.index.get(getKey(msgInfo.msgStr, msgInfo.context))})`;
159
172
  if (msgInfo.type !== 'url') {
@@ -161,7 +174,7 @@ export class Transformer {
161
174
  }
162
175
  return `${varNames.urlLocalize}(${repl}, ${this.vars().rtLocale})`;
163
176
  }
164
- visitLiteral = (node, heuristicDetailsBase) => {
177
+ visitLiteral(node, heuristicDetailsBase) {
165
178
  if (typeof node.value !== 'string') {
166
179
  return [];
167
180
  }
@@ -172,29 +185,61 @@ export class Transformer {
172
185
  }
173
186
  this.mstr.update(start, end, this.literalRepl(msgInfo));
174
187
  return [msgInfo];
175
- };
176
- visitArrayExpression = (node) => node.elements.flatMap(elm => (elm ? this.visit(elm) : []));
177
- visitSequenceExpression = (node) => node.expressions.flatMap(this.visit);
178
- visitObjectExpression = (node) => node.properties.flatMap(this.visit);
179
- visitObjectPattern = (node) => node.properties.flatMap(this.visit);
180
- visitRestElement = (node) => this.visit(node.argument);
181
- visitProperty = (node) => {
188
+ }
189
+ visitArrayExpression(node) {
190
+ return node.elements.flatMap(elm => (elm ? this.visit(elm) : []));
191
+ }
192
+ visitSequenceExpression(node) {
193
+ return node.expressions.flatMap(n => this.visit(n));
194
+ }
195
+ visitObjectExpression(node) {
196
+ return node.properties.flatMap(n => this.visit(n));
197
+ }
198
+ visitObjectPattern(node) {
199
+ return node.properties.flatMap(n => this.visit(n));
200
+ }
201
+ visitRestElement(node) {
202
+ return this.visit(node.argument);
203
+ }
204
+ visitProperty(node) {
182
205
  const msgs = this.visit(node.key);
183
- if (msgs.length && node.key.type === 'Literal' && typeof node.key.value === 'string' && !node.computed) {
206
+ let keyName = '[]';
207
+ let keyIsLiteral = false;
208
+ if (node.key.type === 'Identifier') {
209
+ keyName = node.key.name;
210
+ }
211
+ else if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
212
+ keyIsLiteral = true;
213
+ keyName = node.key.value;
214
+ }
215
+ if (msgs.length && keyIsLiteral && !node.computed) {
184
216
  this.mstr.appendRight(node.key.start, '[');
185
217
  this.mstr.appendLeft(node.key.end, ']');
186
218
  }
219
+ const extendPropDown = extendPropDownTypes.includes(node.value.type);
220
+ const prevProp = this.heuristciDetails.property;
221
+ if (extendPropDown) {
222
+ this.heuristciDetails.property = prevProp ? `${prevProp}.${keyName}` : keyName;
223
+ }
187
224
  msgs.push(...this.visit(node.value));
225
+ if (extendPropDown) {
226
+ this.heuristciDetails.property = prevProp; // restore
227
+ }
188
228
  return msgs;
189
- };
190
- visitSpreadElement = (node) => this.visit(node.argument);
191
- visitMemberExpression = (node) => [
192
- ...this.visit(node.object),
193
- ...this.visit(node.property),
194
- ];
195
- visitChainExpression = (node) => this.visit(node.expression);
196
- visitNewExpression = (node) => node.arguments.flatMap(this.visit);
197
- defaultVisitCallExpression = (node) => {
229
+ }
230
+ visitSpreadElement(node) {
231
+ return this.visit(node.argument);
232
+ }
233
+ visitMemberExpression(node) {
234
+ return [...this.visit(node.object), ...this.visit(node.property)];
235
+ }
236
+ visitChainExpression(node) {
237
+ return this.visit(node.expression);
238
+ }
239
+ visitNewExpression(node) {
240
+ return node.arguments.flatMap(n => this.visit(n));
241
+ }
242
+ defaultVisitCallExpression(node) {
198
243
  const msgs = this.visit(node.callee);
199
244
  const currentCall = this.heuristciDetails.call;
200
245
  this.heuristciDetails.call = this.getCalleeName(node.callee);
@@ -203,8 +248,8 @@ export class Transformer {
203
248
  }
204
249
  this.heuristciDetails.call = currentCall; // restore
205
250
  return msgs;
206
- };
207
- visitCallExpression = (node) => {
251
+ }
252
+ visitCallExpression(node) {
208
253
  if (node.callee.type !== 'Identifier') {
209
254
  return this.defaultVisitCallExpression(node);
210
255
  }
@@ -300,7 +345,6 @@ export class Transformer {
300
345
  details: this.fullHeuristicDetails({ scope: 'script' }),
301
346
  context: this.commentDirectives.context,
302
347
  });
303
- msgInfo.plural = true;
304
348
  const index = this.index.get(getKey(msgInfo.msgStr, msgInfo.context));
305
349
  msgs.push(msgInfo);
306
350
  updates.push([argVal.start, argVal.end, `${this.vars().rtTPlural}(${index})`]);
@@ -312,38 +356,35 @@ export class Transformer {
312
356
  this.mstr.appendRight(index, insert);
313
357
  }
314
358
  return msgs;
315
- };
316
- visitBinaryExpression = (node) => [
317
- ...this.visit(node.left),
318
- ...this.visit(node.right),
319
- ];
320
- visitConditionalExpression = (node) => [
321
- ...this.visit(node.test),
322
- ...this.visit(node.consequent),
323
- ...this.visit(node.alternate),
324
- ];
325
- visitUnaryExpression = (node) => this.visit(node.argument);
326
- visitLogicalExpression = (node) => [
327
- ...this.visit(node.left),
328
- ...this.visit(node.right),
329
- ];
330
- visitAwaitExpression = (node) => this.visit(node.argument);
331
- visitAssignmentExpression = this.visitBinaryExpression;
332
- visitAssignmentPattern = (node) => [
333
- ...this.visit(node.left),
334
- ...this.visit(node.right),
335
- ];
336
- visitForOfStatement = (node) => [
337
- ...this.visit(node.left),
338
- ...this.visit(node.right),
339
- ...this.visit(node.body),
340
- ];
341
- visitForInStatement = (node) => [
342
- ...this.visit(node.left),
343
- ...this.visit(node.right),
344
- ...this.visit(node.body),
345
- ];
346
- visitForStatement = (node) => {
359
+ }
360
+ visitBinaryExpression(node) {
361
+ return [...this.visit(node.left), ...this.visit(node.right)];
362
+ }
363
+ visitConditionalExpression(node) {
364
+ return [...this.visit(node.test), ...this.visit(node.consequent), ...this.visit(node.alternate)];
365
+ }
366
+ visitUnaryExpression(node) {
367
+ return this.visit(node.argument);
368
+ }
369
+ visitLogicalExpression(node) {
370
+ return [...this.visit(node.left), ...this.visit(node.right)];
371
+ }
372
+ visitAwaitExpression(node) {
373
+ return this.visit(node.argument);
374
+ }
375
+ visitAssignmentExpression(node) {
376
+ return [...this.visit(node.left), ...this.visit(node.right)];
377
+ }
378
+ visitAssignmentPattern(node) {
379
+ return [...this.visit(node.left), ...this.visit(node.right)];
380
+ }
381
+ visitForOfStatement(node) {
382
+ return [...this.visit(node.left), ...this.visit(node.right), ...this.visit(node.body)];
383
+ }
384
+ visitForInStatement(node) {
385
+ return [...this.visit(node.left), ...this.visit(node.right), ...this.visit(node.body)];
386
+ }
387
+ visitForStatement(node) {
347
388
  const msgs = this.visit(node.body);
348
389
  if (node.init) {
349
390
  msgs.push(...this.visit(node.init));
@@ -355,8 +396,8 @@ export class Transformer {
355
396
  msgs.push(...this.visit(node.update));
356
397
  }
357
398
  return msgs;
358
- };
359
- getMemberChainName = (node) => {
399
+ }
400
+ getMemberChainName(node) {
360
401
  let name = '';
361
402
  if (node.object.type === 'Identifier') {
362
403
  name = node.object.name;
@@ -378,8 +419,8 @@ export class Transformer {
378
419
  name = `[${node.type}]`;
379
420
  }
380
421
  return name;
381
- };
382
- getCalleeName = (callee) => {
422
+ }
423
+ getCalleeName(callee) {
383
424
  if (callee.type === 'Identifier') {
384
425
  return callee.name;
385
426
  }
@@ -387,7 +428,7 @@ export class Transformer {
387
428
  return this.getMemberChainName(callee);
388
429
  }
389
430
  return `[${callee.type}]`;
390
- };
431
+ }
391
432
  getActualExpression(expr) {
392
433
  if (!expr) {
393
434
  return null;
@@ -406,49 +447,60 @@ export class Transformer {
406
447
  }
407
448
  return msgs;
408
449
  }
409
- defaultVisitVariableDeclarator = (node) => this.withUpdateTLDetails(topLevel => {
410
- if (!node.init) {
411
- return [];
412
- }
413
- const init = this.getActualExpression(node.init);
414
- if (topLevel) {
415
- if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {
416
- this.heuristciDetails.declaring = 'function';
450
+ visitExpressionStatement(node) {
451
+ return this.withUpdateTLDetails(topLevel => {
452
+ const expr = this.getActualExpression(node.expression);
453
+ if (topLevel) {
454
+ this.heuristciDetails.declaring = 'expression';
455
+ if (expr.type === 'CallExpression') {
456
+ this.heuristciDetails.topLevelCall = this.getCalleeName(expr.callee);
457
+ }
417
458
  }
418
- else {
419
- this.heuristciDetails.declaring = 'variable';
459
+ return this.visit(expr);
460
+ });
461
+ }
462
+ // for e.g. svelte to surrounded with $derived
463
+ visitVariableDeclarator(node) {
464
+ return this.withUpdateTLDetails(topLevel => {
465
+ if (!node.init) {
466
+ return [];
420
467
  }
421
- }
422
- this.heuristciDetails.leftSide = true;
423
- const msgs = this.visit(node.id);
424
- this.heuristciDetails.leftSide = false;
425
- if (topLevel && this.heuristciDetails.declaring === 'variable' && init.type === 'CallExpression') {
426
- this.heuristciDetails.topLevelCall = this.getCalleeName(init.callee);
427
- }
428
- delete this.heuristciDetails.leftSide;
429
- return [...msgs, ...this.visit(node.init)];
430
- });
431
- visitExpressionStatement = (node) => this.withUpdateTLDetails(topLevel => {
432
- const expr = this.getActualExpression(node.expression);
433
- if (topLevel) {
434
- this.heuristciDetails.declaring = 'expression';
435
- if (expr.type === 'CallExpression') {
436
- this.heuristciDetails.topLevelCall = this.getCalleeName(expr.callee);
468
+ const init = this.getActualExpression(node.init);
469
+ if (topLevel) {
470
+ if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {
471
+ this.heuristciDetails.declaring = 'function';
472
+ }
473
+ else {
474
+ this.heuristciDetails.declaring = 'variable';
475
+ }
437
476
  }
438
- }
439
- return this.visit(expr);
440
- });
441
- // for e.g. svelte to surrounded with $derived
442
- visitVariableDeclarator = this.defaultVisitVariableDeclarator;
443
- visitVariableDeclaration = (node) => node.declarations.flatMap(this.visitVariableDeclarator);
444
- visitExportNamedDeclaration = (node) => {
477
+ this.heuristciDetails.leftSide = true;
478
+ const msgs = this.visit(node.id);
479
+ this.heuristciDetails.leftSide = false;
480
+ if (topLevel && this.heuristciDetails.declaring === 'variable' && init.type === 'CallExpression') {
481
+ this.heuristciDetails.topLevelCall = this.getCalleeName(init.callee);
482
+ }
483
+ delete this.heuristciDetails.leftSide;
484
+ if (node.id.type === 'Identifier' &&
485
+ (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression')) {
486
+ return [...msgs, ...this.visitFunctionBody(init.body, node.id.name, init.end)];
487
+ }
488
+ return [...msgs, ...this.visit(node.init)];
489
+ });
490
+ }
491
+ visitVariableDeclaration(node) {
492
+ return node.declarations.flatMap(n => this.visitVariableDeclarator(n));
493
+ }
494
+ visitExportNamedDeclaration(node) {
445
495
  this.heuristciDetails.exported = true;
446
496
  const msgs = node.declaration ? this.visit(node.declaration) : [];
447
497
  delete this.heuristciDetails.exported;
448
498
  return msgs;
449
- };
450
- visitExportDefaultDeclaration = this.visitExportNamedDeclaration;
451
- visitStatementsNSaveRealBodyStart = (nodes) => {
499
+ }
500
+ visitExportDefaultDeclaration(node) {
501
+ return this.visitExportNamedDeclaration(node);
502
+ }
503
+ visitStatementsNSaveRealBodyStart(nodes) {
452
504
  const msgs = [];
453
505
  let bodyStart = null;
454
506
  for (const bod of nodes) {
@@ -472,8 +524,8 @@ export class Transformer {
472
524
  this.realBodyStarts.add(bodyStart);
473
525
  }
474
526
  return msgs;
475
- };
476
- getRealBodyStart = (nodes) => {
527
+ }
528
+ getRealBodyStart(nodes) {
477
529
  let nonLiteralStart = null;
478
530
  for (const node of nodes) {
479
531
  if (this.realBodyStarts.has(node.start)) {
@@ -486,8 +538,8 @@ export class Transformer {
486
538
  }
487
539
  }
488
540
  return nonLiteralStart ?? nodes[0]?.start;
489
- };
490
- visitFunctionBody = (node, name, end) => {
541
+ }
542
+ visitFunctionBody(node, name, end) {
491
543
  const prevFuncDef = this.heuristciDetails.funcName;
492
544
  const prevFuncNested = this.heuristciDetails.funcIsNested;
493
545
  this.heuristciDetails.funcName = name;
@@ -520,46 +572,60 @@ export class Transformer {
520
572
  this.heuristciDetails.funcIsNested = prevFuncNested;
521
573
  this.heuristciDetails.funcName = prevFuncDef;
522
574
  return msgs;
523
- };
524
- visitFunctionDeclaration = (node) => {
575
+ }
576
+ visitFunctionDeclaration(node) {
525
577
  const declaring = this.heuristciDetails.declaring;
526
578
  this.heuristciDetails.declaring = 'function';
527
579
  const msgs = this.visitFunctionBody(node.body, node.id?.name ?? '');
528
580
  this.heuristciDetails.declaring = declaring;
529
581
  return msgs;
530
- };
531
- visitArrowFunctionExpression = (node) => this.visitFunctionBody(node.body, '', node.end);
532
- visitFunctionExpression = (node) => this.visitFunctionBody(node.body, '');
533
- visitBlockStatement = (node) => this.visitStatementsNSaveRealBodyStart(node.body);
534
- visitReturnStatement = (node) => (node.argument ? this.visit(node.argument) : []);
535
- visitIfStatement = (node) => {
582
+ }
583
+ visitArrowFunctionExpression(node) {
584
+ return this.visitFunctionBody(node.body, '', node.end);
585
+ }
586
+ visitFunctionExpression(node) {
587
+ return this.visitFunctionBody(node.body, '');
588
+ }
589
+ visitBlockStatement(node) {
590
+ return this.visitStatementsNSaveRealBodyStart(node.body);
591
+ }
592
+ visitReturnStatement(node) {
593
+ return node.argument ? this.visit(node.argument) : [];
594
+ }
595
+ visitIfStatement(node) {
536
596
  const msgs = this.visit(node.test);
537
597
  msgs.push(...this.visit(node.consequent));
538
598
  if (node.alternate) {
539
599
  msgs.push(...this.visit(node.alternate));
540
600
  }
541
601
  return msgs;
542
- };
543
- visitWhileStatement = (node) => [
544
- ...this.visit(node.test),
545
- ...this.visit(node.body),
546
- ];
547
- visitDoWhileStatement = (node) => [
548
- ...this.visit(node.body),
549
- ...this.visit(node.test),
550
- ];
551
- visitLabeledStatement = (node) => this.visit(node.body);
552
- visitParenthesizedExpression = (node) => this.visit(node.expression);
553
- visitSwitchStatement = (node) => node.cases.flatMap(this.visit);
554
- visitSwitchCase = (node) => {
555
- const msgs = node.consequent.flatMap(this.visit);
602
+ }
603
+ visitWhileStatement(node) {
604
+ return [...this.visit(node.test), ...this.visit(node.body)];
605
+ }
606
+ visitDoWhileStatement(node) {
607
+ return [...this.visit(node.body), ...this.visit(node.test)];
608
+ }
609
+ visitLabeledStatement(node) {
610
+ return this.visit(node.body);
611
+ }
612
+ visitParenthesizedExpression(node) {
613
+ return this.visit(node.expression);
614
+ }
615
+ visitSwitchStatement(node) {
616
+ return node.cases.flatMap(n => this.visit(n));
617
+ }
618
+ visitSwitchCase(node) {
619
+ const msgs = node.consequent.flatMap(n => this.visit(n));
556
620
  if (node.test) {
557
621
  return [...this.visit(node.test), ...msgs];
558
622
  }
559
623
  return msgs;
560
- };
561
- visitYieldExpression = (node) => (node.argument ? this.visit(node.argument) : []);
562
- visitClassDeclaration = (node) => {
624
+ }
625
+ visitYieldExpression(node) {
626
+ return node.argument ? this.visit(node.argument) : [];
627
+ }
628
+ visitClassDeclaration(node) {
563
629
  const msgs = [];
564
630
  const prevDecl = this.heuristciDetails.declaring;
565
631
  this.heuristciDetails.declaring = 'class';
@@ -575,34 +641,26 @@ export class Transformer {
575
641
  else if (body.type === 'StaticBlock') {
576
642
  const currentFuncDef = this.heuristciDetails.funcName;
577
643
  this.heuristciDetails.funcName = `${node.id.name}.[static]`;
578
- msgs.push(...body.body.flatMap(this.visit));
644
+ msgs.push(...body.body.flatMap(n => this.visit(n)));
579
645
  this.heuristciDetails.funcName = currentFuncDef; // restore
580
646
  }
581
647
  }
582
648
  this.heuristciDetails.declaring = prevDecl; // restore
583
649
  return msgs;
584
- };
585
- checkHeuristicTemplateLiteral = (node, heurDetails) => {
586
- let heurTxt = '';
587
- for (const quasi of node.quasis) {
588
- heurTxt += quasi.value.cooked ?? '';
589
- if (!quasi.tail) {
590
- heurTxt += '#';
591
- }
592
- }
593
- heurTxt = heurTxt.trim();
594
- const [pass] = this.checkHeuristic(heurTxt, heurDetails ?? { scope: 'script' });
595
- return pass;
596
- };
597
- visitTemplateLiteralQuasis = (node, msgTyp) => {
650
+ }
651
+ visitTemplateLiteralQuasis(node, forHeuristic = false) {
598
652
  const msgs = [];
599
653
  let msgStr = node.quasis[0].value?.cooked ?? '';
600
654
  const placeholders = [];
601
655
  for (const [i, expr] of node.expressions.entries()) {
602
- msgs.push(...this.visit(expr));
603
656
  const quasi = node.quasis[i + 1];
604
657
  msgStr += `{${i}}${quasi.value.cooked}`;
605
- placeholders.push([i, this.content.slice(expr.start, expr.end)]);
658
+ placeholders.push([i.toString(), this.content.slice(expr.start, expr.end)]);
659
+ if (forHeuristic) {
660
+ // skip modifications and sub visits
661
+ continue;
662
+ }
663
+ msgs.push(...this.visit(expr));
606
664
  const { start, end } = quasi;
607
665
  this.mstr.remove(start - 1, end);
608
666
  if (i + 1 === node.expressions.length) {
@@ -614,23 +672,28 @@ export class Transformer {
614
672
  msgStr: [msgStr],
615
673
  details: this.fullHeuristicDetails({ scope: 'script' }),
616
674
  context: this.commentDirectives.context,
675
+ placeholders,
617
676
  });
618
- msgInfo.type = msgTyp;
619
- msgInfo.placeholders = placeholders;
620
- const index = this.index.get(getKey(msgInfo.msgStr, msgInfo.context));
621
677
  msgs.push(msgInfo);
622
- return [index, msgs];
623
- };
624
- visitTemplateLiteral = (node, heurDetails = false) => {
678
+ return [msgInfo, forHeuristic ? 0 : this.index.get(getKey(msgInfo.msgStr, msgInfo.context)), msgs];
679
+ }
680
+ visitTemplateLiteral(node, heurDetails = false) {
625
681
  let msgTyp = 'message';
626
- if (heurDetails !== true) {
627
- const heuRes = this.checkHeuristicTemplateLiteral(node, typeof heurDetails === 'boolean' ? undefined : heurDetails);
682
+ let visitRes;
683
+ if (heurDetails === true) {
684
+ visitRes = this.visitTemplateLiteralQuasis(node);
685
+ }
686
+ else {
687
+ const [msgInfoHeu] = this.visitTemplateLiteralQuasis(node, true);
688
+ const [heuRes] = this.checkHeuristic(msgInfoHeu.msgStr[0], heurDetails || { scope: 'script' });
628
689
  if (!heuRes) {
629
- return node.expressions.flatMap(this.visit);
690
+ return node.expressions.flatMap(n => this.visit(n));
630
691
  }
631
692
  msgTyp = heuRes;
693
+ visitRes = this.visitTemplateLiteralQuasis(node);
632
694
  }
633
- const [index, msgs] = this.visitTemplateLiteralQuasis(node, msgTyp);
695
+ const [msgInfo, index, msgs] = visitRes;
696
+ msgInfo.type = msgTyp;
634
697
  const { start: start0, end: end0 } = node.quasis[0];
635
698
  let begin = `${this.vars().rtTrans}(${index}`;
636
699
  let end = ')';
@@ -648,14 +711,16 @@ export class Transformer {
648
711
  this.mstr.update(start0 - 1, end0 + 1, begin + end);
649
712
  }
650
713
  return msgs;
651
- };
652
- visitTaggedTemplateExpression = (node) => {
714
+ }
715
+ visitTaggedTemplateExpression(node) {
653
716
  const prevCall = this.heuristciDetails.call;
654
717
  this.heuristciDetails.call = this.getCalleeName(node.tag);
655
718
  let msgs = [];
656
- const heuRes = this.checkHeuristicTemplateLiteral(node.quasi);
719
+ const [msgInfoHeu] = this.visitTemplateLiteralQuasis(node.quasi, true);
720
+ const [heuRes] = this.checkHeuristic(msgInfoHeu.msgStr[0], { scope: 'script' });
657
721
  if (heuRes) {
658
- const [index, msgsNew] = this.visitTemplateLiteralQuasis(node.quasi, heuRes);
722
+ const [msgInfo, index, msgsNew] = this.visitTemplateLiteralQuasis(node.quasi);
723
+ msgInfo.type = heuRes;
659
724
  msgs = msgsNew;
660
725
  this.mstr.appendRight(node.tag.start, `${this.vars().rtTransTag}(`);
661
726
  const { start, end, expressions } = node.quasi;
@@ -670,8 +735,8 @@ export class Transformer {
670
735
  }
671
736
  this.heuristciDetails.call = prevCall;
672
737
  return msgs;
673
- };
674
- visitTryStatement = (node) => {
738
+ }
739
+ visitTryStatement(node) {
675
740
  const msgs = this.visit(node.block);
676
741
  if (node.handler) {
677
742
  msgs.push(...this.visit(node.handler.body));
@@ -680,17 +745,23 @@ export class Transformer {
680
745
  msgs.push(...this.visit(node.finalizer));
681
746
  }
682
747
  return msgs;
683
- };
684
- visitTSAsExpression = (node) => this.visit(node.expression);
685
- visitTSTypeAssertion = (node) => this.visit(node.expression);
686
- visitTSSatisfiesExpression = (node) => this.visit(node.expression);
687
- visitProgram = (node) => {
748
+ }
749
+ visitTSAsExpression(node) {
750
+ return this.visit(node.expression);
751
+ }
752
+ visitTSTypeAssertion(node) {
753
+ return this.visit(node.expression);
754
+ }
755
+ visitTSSatisfiesExpression(node) {
756
+ return this.visit(node.expression);
757
+ }
758
+ visitProgram(node) {
688
759
  this.heuristciDetails.insideProgram = true;
689
760
  const msgs = this.visitStatementsNSaveRealBodyStart(node.body);
690
761
  this.heuristciDetails.insideProgram = false;
691
762
  return msgs;
692
- };
693
- visitWithCommentDirectives = (node, func) => {
763
+ }
764
+ visitWithCommentDirectives(node, func) {
694
765
  const commentDirectives = { ...this.commentDirectives };
695
766
  // for estree
696
767
  const comments = this.comments[node.start];
@@ -704,61 +775,37 @@ export class Transformer {
704
775
  const res = func();
705
776
  restoreCommentDirectives(this.commentDirectives, commentDirectives);
706
777
  return res;
707
- };
708
- visitEmptyStatement = () => [];
709
- visitArrayPattern = () => [];
710
- visitBreakStatement = () => [];
711
- visitCatchClause = () => [];
712
- visitClassBody = () => [];
713
- visitClassExpression = () => [];
714
- visitContinueStatement = () => [];
715
- visitDebuggerStatement = () => [];
716
- visitExportAllDeclaration = () => [];
717
- visitExportSpecifier = () => [];
718
- visitIdentifier = () => [];
719
- visitImportAttribute = () => [];
720
- visitImportDeclaration = () => [];
721
- visitImportDefaultSpecifier = () => [];
722
- visitImportExpression = () => [];
723
- visitImportNamespaceSpecifier = () => [];
724
- visitImportSpecifier = () => [];
725
- visitMetaProperty = () => [];
726
- visitMethodDefinition = () => []; // handled inside visitClassDeclaration
727
- visitPrivateIdentifier = () => [];
728
- visitPropertyDefinition = () => [];
729
- visitStaticBlock = () => []; // handled inside visitClassDeclaration
730
- visitSuper = () => [];
731
- visitTemplateElement = () => [];
732
- visitThisExpression = () => [];
733
- visitThrowStatement = () => [];
734
- visitUpdateExpression = () => [];
735
- visitWithStatement = () => [];
736
- visit = (node) => this.visitWithCommentDirectives(node, () => {
737
- if (this.commentDirectives.forceType === false) {
738
- return [];
739
- }
740
- let msgs = [];
741
- const visitor = this[`visit${node.type}`];
742
- if (visitor != null) {
743
- msgs = visitor(node);
744
- // } else {
745
- // console.log(node)
746
- }
747
- return msgs;
748
- });
749
- finalize = (msgs, hmrHeaderIndex, additionalHeader = '') => ({
750
- msgs,
751
- output: header => {
752
- this.mstr.prependRight(hmrHeaderIndex, `\n${header}\n${additionalHeader}\n`);
753
- return {
754
- code: this.mstr.toString(),
755
- map: this.mstr.generateMap(),
756
- };
757
- },
758
- });
759
- transform = () => {
778
+ }
779
+ visit(node) {
780
+ return this.visitWithCommentDirectives(node, () => {
781
+ if (this.commentDirectives.forceType === false) {
782
+ return [];
783
+ }
784
+ let msgs = [];
785
+ const visitor = this[`visit${node.type}`];
786
+ if (visitor != null) {
787
+ msgs = visitor.bind(this)(node);
788
+ // } else {
789
+ // console.log(node)
790
+ }
791
+ return msgs;
792
+ });
793
+ }
794
+ finalize(msgs, hmrHeaderIndex, additionalHeader = '') {
795
+ return {
796
+ msgs,
797
+ output: header => {
798
+ this.mstr.prependRight(hmrHeaderIndex, `\n${header}\n${additionalHeader}\n`);
799
+ return {
800
+ code: this.mstr.toString(),
801
+ map: this.mstr.generateMap(),
802
+ };
803
+ },
804
+ };
805
+ }
806
+ transform() {
760
807
  const [ast, comments] = parseScript(this.content);
761
808
  this.comments = comments;
762
809
  return this.finalize(this.visit(ast), this.getRealBodyStart(ast.body) ?? 0);
763
- };
810
+ }
764
811
  }