wuchale 0.23.3 → 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 +292 -240
  8. package/dist/adapters.d.ts +18 -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,44 +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) => node.declaration ? this.visit(node.declaration) : [];
445
- visitExportDefaultDeclaration = this.visitExportNamedDeclaration;
446
- visitStatementsNSaveRealBodyStart = (nodes) => {
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) {
495
+ this.heuristciDetails.exported = true;
496
+ const msgs = node.declaration ? this.visit(node.declaration) : [];
497
+ delete this.heuristciDetails.exported;
498
+ return msgs;
499
+ }
500
+ visitExportDefaultDeclaration(node) {
501
+ return this.visitExportNamedDeclaration(node);
502
+ }
503
+ visitStatementsNSaveRealBodyStart(nodes) {
447
504
  const msgs = [];
448
505
  let bodyStart = null;
449
506
  for (const bod of nodes) {
@@ -467,8 +524,8 @@ export class Transformer {
467
524
  this.realBodyStarts.add(bodyStart);
468
525
  }
469
526
  return msgs;
470
- };
471
- getRealBodyStart = (nodes) => {
527
+ }
528
+ getRealBodyStart(nodes) {
472
529
  let nonLiteralStart = null;
473
530
  for (const node of nodes) {
474
531
  if (this.realBodyStarts.has(node.start)) {
@@ -481,8 +538,8 @@ export class Transformer {
481
538
  }
482
539
  }
483
540
  return nonLiteralStart ?? nodes[0]?.start;
484
- };
485
- visitFunctionBody = (node, name, end) => {
541
+ }
542
+ visitFunctionBody(node, name, end) {
486
543
  const prevFuncDef = this.heuristciDetails.funcName;
487
544
  const prevFuncNested = this.heuristciDetails.funcIsNested;
488
545
  this.heuristciDetails.funcName = name;
@@ -515,46 +572,60 @@ export class Transformer {
515
572
  this.heuristciDetails.funcIsNested = prevFuncNested;
516
573
  this.heuristciDetails.funcName = prevFuncDef;
517
574
  return msgs;
518
- };
519
- visitFunctionDeclaration = (node) => {
575
+ }
576
+ visitFunctionDeclaration(node) {
520
577
  const declaring = this.heuristciDetails.declaring;
521
578
  this.heuristciDetails.declaring = 'function';
522
579
  const msgs = this.visitFunctionBody(node.body, node.id?.name ?? '');
523
580
  this.heuristciDetails.declaring = declaring;
524
581
  return msgs;
525
- };
526
- visitArrowFunctionExpression = (node) => this.visitFunctionBody(node.body, '', node.end);
527
- visitFunctionExpression = (node) => this.visitFunctionBody(node.body, '');
528
- visitBlockStatement = (node) => this.visitStatementsNSaveRealBodyStart(node.body);
529
- visitReturnStatement = (node) => (node.argument ? this.visit(node.argument) : []);
530
- 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) {
531
596
  const msgs = this.visit(node.test);
532
597
  msgs.push(...this.visit(node.consequent));
533
598
  if (node.alternate) {
534
599
  msgs.push(...this.visit(node.alternate));
535
600
  }
536
601
  return msgs;
537
- };
538
- visitWhileStatement = (node) => [
539
- ...this.visit(node.test),
540
- ...this.visit(node.body),
541
- ];
542
- visitDoWhileStatement = (node) => [
543
- ...this.visit(node.body),
544
- ...this.visit(node.test),
545
- ];
546
- visitLabeledStatement = (node) => this.visit(node.body);
547
- visitParenthesizedExpression = (node) => this.visit(node.expression);
548
- visitSwitchStatement = (node) => node.cases.flatMap(this.visit);
549
- visitSwitchCase = (node) => {
550
- 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));
551
620
  if (node.test) {
552
621
  return [...this.visit(node.test), ...msgs];
553
622
  }
554
623
  return msgs;
555
- };
556
- visitYieldExpression = (node) => (node.argument ? this.visit(node.argument) : []);
557
- visitClassDeclaration = (node) => {
624
+ }
625
+ visitYieldExpression(node) {
626
+ return node.argument ? this.visit(node.argument) : [];
627
+ }
628
+ visitClassDeclaration(node) {
558
629
  const msgs = [];
559
630
  const prevDecl = this.heuristciDetails.declaring;
560
631
  this.heuristciDetails.declaring = 'class';
@@ -570,34 +641,26 @@ export class Transformer {
570
641
  else if (body.type === 'StaticBlock') {
571
642
  const currentFuncDef = this.heuristciDetails.funcName;
572
643
  this.heuristciDetails.funcName = `${node.id.name}.[static]`;
573
- msgs.push(...body.body.flatMap(this.visit));
644
+ msgs.push(...body.body.flatMap(n => this.visit(n)));
574
645
  this.heuristciDetails.funcName = currentFuncDef; // restore
575
646
  }
576
647
  }
577
648
  this.heuristciDetails.declaring = prevDecl; // restore
578
649
  return msgs;
579
- };
580
- checkHeuristicTemplateLiteral = (node, heurDetails) => {
581
- let heurTxt = '';
582
- for (const quasi of node.quasis) {
583
- heurTxt += quasi.value.cooked ?? '';
584
- if (!quasi.tail) {
585
- heurTxt += '#';
586
- }
587
- }
588
- heurTxt = heurTxt.trim();
589
- const [pass] = this.checkHeuristic(heurTxt, heurDetails ?? { scope: 'script' });
590
- return pass;
591
- };
592
- visitTemplateLiteralQuasis = (node, msgTyp) => {
650
+ }
651
+ visitTemplateLiteralQuasis(node, forHeuristic = false) {
593
652
  const msgs = [];
594
653
  let msgStr = node.quasis[0].value?.cooked ?? '';
595
654
  const placeholders = [];
596
655
  for (const [i, expr] of node.expressions.entries()) {
597
- msgs.push(...this.visit(expr));
598
656
  const quasi = node.quasis[i + 1];
599
657
  msgStr += `{${i}}${quasi.value.cooked}`;
600
- 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));
601
664
  const { start, end } = quasi;
602
665
  this.mstr.remove(start - 1, end);
603
666
  if (i + 1 === node.expressions.length) {
@@ -609,23 +672,28 @@ export class Transformer {
609
672
  msgStr: [msgStr],
610
673
  details: this.fullHeuristicDetails({ scope: 'script' }),
611
674
  context: this.commentDirectives.context,
675
+ placeholders,
612
676
  });
613
- msgInfo.type = msgTyp;
614
- msgInfo.placeholders = placeholders;
615
- const index = this.index.get(getKey(msgInfo.msgStr, msgInfo.context));
616
677
  msgs.push(msgInfo);
617
- return [index, msgs];
618
- };
619
- visitTemplateLiteral = (node, heurDetails = false) => {
678
+ return [msgInfo, forHeuristic ? 0 : this.index.get(getKey(msgInfo.msgStr, msgInfo.context)), msgs];
679
+ }
680
+ visitTemplateLiteral(node, heurDetails = false) {
620
681
  let msgTyp = 'message';
621
- if (heurDetails !== true) {
622
- 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' });
623
689
  if (!heuRes) {
624
- return node.expressions.flatMap(this.visit);
690
+ return node.expressions.flatMap(n => this.visit(n));
625
691
  }
626
692
  msgTyp = heuRes;
693
+ visitRes = this.visitTemplateLiteralQuasis(node);
627
694
  }
628
- const [index, msgs] = this.visitTemplateLiteralQuasis(node, msgTyp);
695
+ const [msgInfo, index, msgs] = visitRes;
696
+ msgInfo.type = msgTyp;
629
697
  const { start: start0, end: end0 } = node.quasis[0];
630
698
  let begin = `${this.vars().rtTrans}(${index}`;
631
699
  let end = ')';
@@ -643,14 +711,16 @@ export class Transformer {
643
711
  this.mstr.update(start0 - 1, end0 + 1, begin + end);
644
712
  }
645
713
  return msgs;
646
- };
647
- visitTaggedTemplateExpression = (node) => {
714
+ }
715
+ visitTaggedTemplateExpression(node) {
648
716
  const prevCall = this.heuristciDetails.call;
649
717
  this.heuristciDetails.call = this.getCalleeName(node.tag);
650
718
  let msgs = [];
651
- const heuRes = this.checkHeuristicTemplateLiteral(node.quasi);
719
+ const [msgInfoHeu] = this.visitTemplateLiteralQuasis(node.quasi, true);
720
+ const [heuRes] = this.checkHeuristic(msgInfoHeu.msgStr[0], { scope: 'script' });
652
721
  if (heuRes) {
653
- const [index, msgsNew] = this.visitTemplateLiteralQuasis(node.quasi, heuRes);
722
+ const [msgInfo, index, msgsNew] = this.visitTemplateLiteralQuasis(node.quasi);
723
+ msgInfo.type = heuRes;
654
724
  msgs = msgsNew;
655
725
  this.mstr.appendRight(node.tag.start, `${this.vars().rtTransTag}(`);
656
726
  const { start, end, expressions } = node.quasi;
@@ -665,8 +735,8 @@ export class Transformer {
665
735
  }
666
736
  this.heuristciDetails.call = prevCall;
667
737
  return msgs;
668
- };
669
- visitTryStatement = (node) => {
738
+ }
739
+ visitTryStatement(node) {
670
740
  const msgs = this.visit(node.block);
671
741
  if (node.handler) {
672
742
  msgs.push(...this.visit(node.handler.body));
@@ -675,17 +745,23 @@ export class Transformer {
675
745
  msgs.push(...this.visit(node.finalizer));
676
746
  }
677
747
  return msgs;
678
- };
679
- visitTSAsExpression = (node) => this.visit(node.expression);
680
- visitTSTypeAssertion = (node) => this.visit(node.expression);
681
- visitTSSatisfiesExpression = (node) => this.visit(node.expression);
682
- 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) {
683
759
  this.heuristciDetails.insideProgram = true;
684
760
  const msgs = this.visitStatementsNSaveRealBodyStart(node.body);
685
761
  this.heuristciDetails.insideProgram = false;
686
762
  return msgs;
687
- };
688
- visitWithCommentDirectives = (node, func) => {
763
+ }
764
+ visitWithCommentDirectives(node, func) {
689
765
  const commentDirectives = { ...this.commentDirectives };
690
766
  // for estree
691
767
  const comments = this.comments[node.start];
@@ -699,61 +775,37 @@ export class Transformer {
699
775
  const res = func();
700
776
  restoreCommentDirectives(this.commentDirectives, commentDirectives);
701
777
  return res;
702
- };
703
- visitEmptyStatement = () => [];
704
- visitArrayPattern = () => [];
705
- visitBreakStatement = () => [];
706
- visitCatchClause = () => [];
707
- visitClassBody = () => [];
708
- visitClassExpression = () => [];
709
- visitContinueStatement = () => [];
710
- visitDebuggerStatement = () => [];
711
- visitExportAllDeclaration = () => [];
712
- visitExportSpecifier = () => [];
713
- visitIdentifier = () => [];
714
- visitImportAttribute = () => [];
715
- visitImportDeclaration = () => [];
716
- visitImportDefaultSpecifier = () => [];
717
- visitImportExpression = () => [];
718
- visitImportNamespaceSpecifier = () => [];
719
- visitImportSpecifier = () => [];
720
- visitMetaProperty = () => [];
721
- visitMethodDefinition = () => []; // handled inside visitClassDeclaration
722
- visitPrivateIdentifier = () => [];
723
- visitPropertyDefinition = () => [];
724
- visitStaticBlock = () => []; // handled inside visitClassDeclaration
725
- visitSuper = () => [];
726
- visitTemplateElement = () => [];
727
- visitThisExpression = () => [];
728
- visitThrowStatement = () => [];
729
- visitUpdateExpression = () => [];
730
- visitWithStatement = () => [];
731
- visit = (node) => this.visitWithCommentDirectives(node, () => {
732
- if (this.commentDirectives.forceType === false) {
733
- return [];
734
- }
735
- let msgs = [];
736
- const visitor = this[`visit${node.type}`];
737
- if (visitor != null) {
738
- msgs = visitor(node);
739
- // } else {
740
- // console.log(node)
741
- }
742
- return msgs;
743
- });
744
- finalize = (msgs, hmrHeaderIndex, additionalHeader = '') => ({
745
- msgs,
746
- output: header => {
747
- this.mstr.prependRight(hmrHeaderIndex, `\n${header}\n${additionalHeader}\n`);
748
- return {
749
- code: this.mstr.toString(),
750
- map: this.mstr.generateMap(),
751
- };
752
- },
753
- });
754
- 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() {
755
807
  const [ast, comments] = parseScript(this.content);
756
808
  this.comments = comments;
757
809
  return this.finalize(this.visit(ast), this.getRealBodyStart(ast.body) ?? 0);
758
- };
810
+ }
759
811
  }