@tolgee/cli 1.1.1 → 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 };
@@ -10,7 +11,7 @@ export default createMachine({
10
11
  children: '',
11
12
  line: 0,
12
13
  key: VOID_KEY,
13
- useTranslate: null,
14
+ getTranslate: null,
14
15
  ignore: null,
15
16
  keys: [],
16
17
  warnings: [],
@@ -64,7 +65,7 @@ export default createMachine({
64
65
  },
65
66
  },
66
67
  },
67
- useTranslate: {
68
+ getTranslate: {
68
69
  initial: 'idle',
69
70
  states: {
70
71
  idle: {
@@ -72,7 +73,7 @@ export default createMachine({
72
73
  'entity.name.function.ts': {
73
74
  target: 'func',
74
75
  actions: 'storeLine',
75
- cond: (_ctx, evt) => evt.token === 'useTranslate',
76
+ cond: (_ctx, evt) => evt.token === 'getTranslate',
76
77
  },
77
78
  },
78
79
  },
@@ -103,12 +104,12 @@ export default createMachine({
103
104
  'punctuation.definition.string.template.begin.ts': 'namespace',
104
105
  'variable.other.readwrite.ts': {
105
106
  target: 'idle',
106
- actions: ['storeUseTranslate', 'markUseTranslateAsDynamic'],
107
+ actions: ['storeGetTranslate', 'markGetTranslateAsDynamic'],
107
108
  },
108
109
  'meta.brace.round.ts': {
109
110
  target: 'idle',
110
111
  cond: (_ctx, evt) => evt.token === ')',
111
- actions: 'storeUseTranslate',
112
+ actions: 'storeGetTranslate',
112
113
  },
113
114
  },
114
115
  },
@@ -116,7 +117,7 @@ export default createMachine({
116
117
  on: {
117
118
  '*': {
118
119
  target: 'namespace_end',
119
- actions: 'storeNamespacedUseTranslate',
120
+ actions: 'storeNamespacedGetTranslate',
120
121
  },
121
122
  },
122
123
  },
@@ -126,11 +127,11 @@ export default createMachine({
126
127
  'meta.brace.round.ts': 'idle',
127
128
  'punctuation.definition.template-expression.begin.ts': {
128
129
  target: 'idle',
129
- actions: 'markUseTranslateAsDynamic',
130
+ actions: 'markGetTranslateAsDynamic',
130
131
  },
131
132
  'keyword.operator.arithmetic.ts': {
132
133
  target: 'idle',
133
- actions: 'markUseTranslateAsDynamic',
134
+ actions: 'markGetTranslateAsDynamic',
134
135
  },
135
136
  },
136
137
  },
@@ -204,7 +205,7 @@ export default createMachine({
204
205
  on: {
205
206
  'punctuation.definition.variable.svelte': {
206
207
  target: 'dollar',
207
- cond: (ctx, evt) => ctx.useTranslate !== null && evt.token === '$',
208
+ cond: (ctx, evt) => ctx.getTranslate !== null && evt.token === '$',
208
209
  },
209
210
  },
210
211
  },
@@ -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
  },
@@ -368,19 +296,50 @@ export default createMachine({
368
296
  { warning: 'W_UNUSED_IGNORE', line: evt.line - 1 },
369
297
  ],
370
298
  }),
371
- storeUseTranslate: assign({
372
- useTranslate: (_ctx, _evt) => '',
299
+ storeGetTranslate: assign({
300
+ getTranslate: (_ctx, _evt) => '',
373
301
  }),
374
- storeNamespacedUseTranslate: assign({
375
- useTranslate: (_ctx, evt) => evt.token,
302
+ storeNamespacedGetTranslate: assign({
303
+ getTranslate: (_ctx, evt) => evt.token,
376
304
  }),
377
- markUseTranslateAsDynamic: assign({
378
- useTranslate: (_ctx, _evt) => false,
305
+ markGetTranslateAsDynamic: assign({
306
+ getTranslate: (_ctx, _evt) => false,
379
307
  warnings: (ctx, _evt) => [
380
308
  ...ctx.warnings,
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.useTranslate !== null ? ctx.useTranslate : 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
+ });