@tolgee/cli 1.1.2 → 1.2.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.
@@ -1,4 +1,5 @@
1
1
  import { createMachine, assign, send, forwardTo } from 'xstate';
2
+ import translateCallMachine from './shared/translateCall.js';
2
3
  import propertiesMachine from './shared/properties.js';
3
4
  import commentsService from './shared/comments.js';
4
5
  const VOID_KEY = { keyName: '', line: -1 };
@@ -237,111 +238,38 @@ export default createMachine({
237
238
  },
238
239
  },
239
240
  call: {
240
- on: {
241
- 'punctuation.definition.string.begin.ts': 'param_string',
242
- 'punctuation.definition.string.template.begin.ts': 'param_string',
243
- 'variable.other.readwrite.ts': [
244
- {
245
- target: 'idle',
246
- actions: 'dynamicOptions',
247
- cond: (ctx) => !!ctx.key.keyName,
248
- },
241
+ invoke: {
242
+ id: 'tCall',
243
+ src: translateCallMachine,
244
+ onDone: [
249
245
  {
250
246
  target: 'idle',
251
247
  actions: 'dynamicKeyName',
252
- },
253
- ],
254
- 'punctuation.definition.block.ts': {
255
- target: 'param_object',
256
- cond: (_ctx, evt) => evt.token === '{',
257
- },
258
- 'meta.brace.round.ts': {
259
- target: 'idle',
260
- cond: (_ctx, evt) => evt.token === ')',
261
- actions: 'pushKey',
262
- },
263
- },
264
- },
265
- param_string: {
266
- on: {
267
- '*': [
268
- {
269
- target: 'param_end',
270
- actions: ['storeKeyName', 'storeKeyCurrentNamespace'],
271
- cond: (ctx) => !ctx.key.keyName,
272
- },
273
- {
274
- target: 'param_end',
275
- actions: ['storeKeyDefault', 'storeKeyCurrentNamespace'],
276
- cond: (ctx) => !!ctx.key.keyName,
277
- },
278
- ],
279
- },
280
- },
281
- param_end: {
282
- on: {
283
- 'punctuation.separator.comma.ts': 'call',
284
- 'punctuation.definition.template-expression.begin.ts': [
285
- {
286
- target: 'param_end_warn',
287
- actions: 'dynamicKeyDefault',
288
- cond: (ctx) => !!ctx.key.defaultValue,
248
+ cond: (_, evt) => evt.data.keyName === false,
289
249
  },
290
250
  {
291
251
  target: 'idle',
292
- actions: 'dynamicKeyName',
293
- },
294
- ],
295
- 'keyword.operator.arithmetic.ts': [
296
- {
297
- target: 'param_end_warn',
298
- actions: 'dynamicKeyDefault',
299
- cond: (ctx) => !!ctx.key.defaultValue,
252
+ actions: 'dynamicNamespace',
253
+ cond: (_, evt) => evt.data.namespace === false,
300
254
  },
301
255
  {
302
256
  target: 'idle',
303
- actions: 'dynamicKeyName',
257
+ actions: 'dynamicOptions',
258
+ cond: (_, evt) => evt.data.dynamicOptions,
304
259
  },
305
- ],
306
- 'meta.brace.round.ts': {
307
- target: 'idle',
308
- cond: (_ctx, evt) => evt.token === ')',
309
- actions: 'pushKey',
310
- },
311
- },
312
- },
313
- param_end_warn: {
314
- on: {
315
- 'punctuation.separator.comma.ts': 'call',
316
- 'meta.brace.round.ts': {
317
- target: 'idle',
318
- cond: (_ctx, evt) => evt.token === ')',
319
- actions: 'pushKey',
320
- },
321
- },
322
- },
323
- param_object: {
324
- invoke: {
325
- id: 'propertiesMachine',
326
- src: propertiesMachine,
327
- data: {
328
- depth: 1,
329
- },
330
- onDone: [
331
260
  {
332
261
  target: 'idle',
333
- actions: 'emitWarningFromParameters',
334
- cond: 'isPropertiesDataDynamic',
262
+ cond: (_, evt) => !evt.data.keyName,
335
263
  },
336
264
  {
337
265
  target: 'idle',
338
- actions: ['consumeParameters', 'pushKey'],
266
+ actions: 'consumeTranslateCall',
339
267
  },
340
268
  ],
341
269
  },
342
270
  on: {
343
271
  '*': {
344
- actions: forwardTo('propertiesMachine'),
272
+ actions: forwardTo('tCall'),
345
273
  },
346
274
  },
347
275
  },
@@ -381,6 +309,37 @@ export default createMachine({
381
309
  { warning: 'W_DYNAMIC_NAMESPACE', line: ctx.line },
382
310
  ],
383
311
  }),
312
+ consumeTranslateCall: assign({
313
+ warnings: (ctx, evt) => {
314
+ if (!evt.data.namespace && ctx.getTranslate === false) {
315
+ return [
316
+ ...ctx.warnings,
317
+ { warning: 'W_UNRESOLVABLE_NAMESPACE', line: ctx.line },
318
+ ];
319
+ }
320
+ if (evt.data.defaultValue === false) {
321
+ return [
322
+ ...ctx.warnings,
323
+ { warning: 'W_DYNAMIC_DEFAULT_VALUE', line: ctx.line },
324
+ ];
325
+ }
326
+ return ctx.warnings;
327
+ },
328
+ keys: (ctx, evt) => {
329
+ const ns = evt.data.namespace === null ? ctx.getTranslate : evt.data.namespace;
330
+ if (!evt.data.keyName || ns === false)
331
+ return ctx.keys;
332
+ return [
333
+ ...ctx.keys,
334
+ {
335
+ keyName: evt.data.keyName,
336
+ namespace: ns || undefined,
337
+ defaultValue: evt.data.defaultValue || undefined,
338
+ line: ctx.line,
339
+ },
340
+ ];
341
+ },
342
+ }),
384
343
  consumeParameters: assign({
385
344
  key: (ctx, evt) => ({
386
345
  keyName: ctx.key.keyName || evt.data.keyName,
@@ -407,50 +366,30 @@ export default createMachine({
407
366
  line: ctx.line,
408
367
  },
409
368
  ],
410
- key: (_ctx, _evt) => VOID_KEY,
411
- }),
412
- storeKeyName: assign({
413
- key: (ctx, evt) => ({ ...ctx.key, keyName: evt.token }),
414
- }),
415
- storeKeyDefault: assign({
416
- key: (ctx, evt) => ({ ...ctx.key, defaultValue: evt.token }),
417
- }),
418
- storeKeyCurrentNamespace: assign({
419
- key: (ctx, _evt) => ({
420
- ...ctx.key,
421
- namespace: ctx.getTranslate !== null ? ctx.getTranslate : undefined,
422
- }),
369
+ key: VOID_KEY,
423
370
  }),
424
371
  dynamicKeyName: assign({
425
372
  warnings: (ctx, _evt) => [
426
373
  ...ctx.warnings,
427
374
  { warning: 'W_DYNAMIC_KEY', line: ctx.line },
428
375
  ],
429
- key: (_ctx, _evt) => VOID_KEY,
376
+ key: VOID_KEY,
430
377
  }),
431
- dynamicKeyDefault: assign({
432
- key: (ctx, _evt) => ({ ...ctx.key, defaultValue: undefined }),
378
+ dynamicNamespace: assign({
433
379
  warnings: (ctx, _evt) => [
434
380
  ...ctx.warnings,
435
- { warning: 'W_DYNAMIC_DEFAULT_VALUE', line: ctx.line },
381
+ { warning: 'W_DYNAMIC_NAMESPACE', line: ctx.line },
436
382
  ],
383
+ key: VOID_KEY,
437
384
  }),
438
385
  dynamicOptions: assign({
439
- key: (_ctx, _evt) => VOID_KEY,
386
+ key: VOID_KEY,
440
387
  warnings: (ctx, _evt) => [
441
388
  ...ctx.warnings,
442
389
  { warning: 'W_DYNAMIC_OPTIONS', line: ctx.line },
443
390
  ],
444
391
  }),
445
392
  pushKey: assign({
446
- warnings: (ctx, _evt) => {
447
- if (!ctx.key.keyName || ctx.key.namespace !== false)
448
- return ctx.warnings;
449
- return [
450
- ...ctx.warnings,
451
- { warning: 'W_UNRESOLVABLE_NAMESPACE', line: ctx.line },
452
- ];
453
- },
454
393
  keys: (ctx, _evt) => {
455
394
  if (!ctx.key.keyName || ctx.key.namespace === false)
456
395
  return ctx.keys;
@@ -0,0 +1,194 @@
1
+ // This machine is responsible for decoding a Vue SFC file.
2
+ // It extracts the tokens in 3 different categories:
3
+ // - The setup function tokens
4
+ // - The scripts (excluding setup)
5
+ // - The template
6
+ //
7
+ // Property of the machine: will always include an
8
+ // extra token for all categories. Consumers must be
9
+ // aware of this!
10
+ import { createMachine, assign } from 'xstate';
11
+ // This state machine is responsible for extracting translation key properties from an object/props
12
+ export default createMachine({
13
+ predictableActionArguments: true,
14
+ id: 'properties',
15
+ initial: 'idle',
16
+ context: {
17
+ setup: [],
18
+ script: [],
19
+ template: [],
20
+ scriptSetupConsumed: false,
21
+ invalidSetup: null,
22
+ depth: 0,
23
+ memoizedDepth: 0,
24
+ },
25
+ states: {
26
+ idle: {
27
+ on: {
28
+ 'punctuation.definition.tag.begin.html.vue': 'beginTag',
29
+ },
30
+ },
31
+ beginTag: {
32
+ on: {
33
+ 'entity.name.tag.script.html.vue': 'scriptTag',
34
+ 'entity.name.tag.template.html.vue': {
35
+ cond: (_, evt) => evt.token === 'template',
36
+ actions: 'incrementDepth',
37
+ target: 'templateTag',
38
+ },
39
+ '*': 'idle',
40
+ },
41
+ },
42
+ scriptTag: {
43
+ on: {
44
+ 'entity.other.attribute-name.html': [
45
+ {
46
+ cond: (_, evt) => evt.token === 'setup',
47
+ actions: ['consumeSetupScript'],
48
+ target: 'scriptSetupTag',
49
+ },
50
+ ],
51
+ 'punctuation.definition.tag.end.html.vue': 'script',
52
+ },
53
+ },
54
+ scriptSetupTag: {
55
+ on: {
56
+ 'punctuation.definition.tag.end.html.vue': 'setup',
57
+ },
58
+ },
59
+ templateTag: {
60
+ on: {
61
+ 'punctuation.definition.tag.end.html.vue': 'template',
62
+ },
63
+ },
64
+ setup: {
65
+ on: {
66
+ '*': { actions: ['consumeSetupToken'] },
67
+ 'entity.name.tag.script.html.vue': 'idle',
68
+ },
69
+ },
70
+ script: {
71
+ on: {
72
+ '*': { actions: ['consumeScriptToken'] },
73
+ 'meta.export.default.ts': {
74
+ actions: ['resetDepth'],
75
+ target: 'scriptExport',
76
+ },
77
+ 'entity.name.tag.script.html.vue': 'idle',
78
+ },
79
+ },
80
+ scriptExport: {
81
+ on: {
82
+ '*': { actions: ['consumeScriptToken'] },
83
+ 'punctuation.definition.block.ts': [
84
+ {
85
+ cond: (_, evt) => evt.token === '{',
86
+ actions: ['incrementDepth'],
87
+ },
88
+ {
89
+ cond: (_, evt) => evt.token === '}',
90
+ actions: ['decrementDepth'],
91
+ },
92
+ ],
93
+ 'entity.name.function.ts': {
94
+ cond: (_, evt) => evt.token === 'setup',
95
+ actions: ['storeDepth'],
96
+ target: 'scriptSetup',
97
+ },
98
+ 'meta.object-literal.key.ts': {
99
+ cond: (_, evt) => evt.token === 'setup',
100
+ actions: ['markBadSetupUse'],
101
+ },
102
+ 'entity.name.tag.script.html.vue': 'idle',
103
+ },
104
+ },
105
+ scriptSetup: {
106
+ on: {
107
+ '*': {
108
+ cond: (ctx) => !ctx.scriptSetupConsumed,
109
+ actions: ['consumeSetupToken'],
110
+ },
111
+ 'punctuation.definition.block.ts': [
112
+ {
113
+ cond: (_, evt) => evt.token === '{',
114
+ actions: ['consumeSetupToken', 'incrementDepth'],
115
+ },
116
+ {
117
+ cond: (ctx, evt) => evt.token === '}' && ctx.depth - 1 === ctx.memoizedDepth,
118
+ actions: ['consumeSetupToken', 'decrementDepth'],
119
+ target: 'scriptExport',
120
+ },
121
+ {
122
+ cond: (_, evt) => evt.token === '}',
123
+ actions: ['consumeSetupToken', 'decrementDepth'],
124
+ },
125
+ ],
126
+ },
127
+ },
128
+ template: {
129
+ on: {
130
+ '*': { actions: ['consumeTemplateToken'] },
131
+ 'punctuation.definition.tag.begin.html.vue': {
132
+ cond: (_, evt) => evt.token === '<',
133
+ target: 'nestedTemplateTag',
134
+ },
135
+ 'entity.name.tag.template.html.vue': [
136
+ {
137
+ cond: (ctx, evt) => evt.token === 'template' && ctx.depth === 1,
138
+ actions: 'decrementDepth',
139
+ target: 'idle',
140
+ },
141
+ {
142
+ cond: (_, evt) => evt.token === 'template',
143
+ actions: 'decrementDepth',
144
+ },
145
+ ],
146
+ },
147
+ },
148
+ nestedTemplateTag: {
149
+ on: {
150
+ 'entity.name.tag.template.html.vue': [
151
+ {
152
+ cond: (_, evt) => evt.token === 'template',
153
+ actions: 'incrementDepth',
154
+ target: 'template',
155
+ },
156
+ {
157
+ target: 'template',
158
+ },
159
+ ],
160
+ },
161
+ },
162
+ },
163
+ }, {
164
+ actions: {
165
+ consumeSetupScript: assign({
166
+ setup: () => [],
167
+ scriptSetupConsumed: () => true,
168
+ }),
169
+ consumeSetupToken: assign({
170
+ setup: (ctx, evt) => [...ctx.setup, evt],
171
+ }),
172
+ consumeScriptToken: assign({
173
+ script: (ctx, evt) => [...ctx.script, evt],
174
+ }),
175
+ consumeTemplateToken: assign({
176
+ template: (ctx, evt) => [...ctx.template, evt],
177
+ }),
178
+ resetDepth: assign({
179
+ depth: () => 0,
180
+ }),
181
+ incrementDepth: assign({
182
+ depth: (ctx) => ctx.depth + 1,
183
+ }),
184
+ decrementDepth: assign({
185
+ depth: (ctx) => ctx.depth - 1,
186
+ }),
187
+ storeDepth: assign({
188
+ memoizedDepth: (ctx) => ctx.depth,
189
+ }),
190
+ markBadSetupUse: assign({
191
+ invalidSetup: (_, evt) => evt.line,
192
+ }),
193
+ },
194
+ });