gtx-cli 2.6.0 → 2.6.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#960](https://github.com/generaltranslation/gt/pull/960) [`eb07e8c`](https://github.com/generaltranslation/gt/commit/eb07e8ce1b610551437b40f96c72ac76d0af7b67) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - chore: upload shared id for static content
8
+
9
+ - Updated dependencies [[`eb07e8c`](https://github.com/generaltranslation/gt/commit/eb07e8ce1b610551437b40f96c72ac76d0af7b67)]:
10
+ - generaltranslation@8.1.7
11
+
3
12
  ## 2.6.0
4
13
 
5
14
  ### Minor Changes
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "2.6.0";
1
+ export declare const PACKAGE_VERSION = "2.6.1";
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const PACKAGE_VERSION = '2.6.0';
2
+ export const PACKAGE_VERSION = '2.6.1';
@@ -1,9 +1,6 @@
1
1
  import { Updates } from '../../../../types/index.js';
2
- import * as t from '@babel/types';
3
- import { NodePath } from '@babel/traverse';
4
2
  import { ParsingConfigOptions } from '../../../../types/parsing.js';
5
3
  import traverseModule from '@babel/traverse';
6
- import { MultiplicationNode, JsxTree } from './types.js';
7
4
  import { GTLibrary } from '../constants.js';
8
5
  /**
9
6
  * Entry point for JSX parsing
@@ -21,44 +18,3 @@ export declare function parseTranslationComponent({ originalName, importAliases,
21
18
  file: string;
22
19
  parsingOptions: ParsingConfigOptions;
23
20
  }): void;
24
- /**
25
- * Builds a JSX tree from a given node, recursively handling children.
26
- * @param node - The node to build the tree from
27
- * @param unwrappedExpressions - An array to store unwrapped expressions
28
- * @param updates - The updates array
29
- * @param errors - The errors array
30
- * @param file - The file name
31
- * @param insideT - Whether the current node is inside a <T> component
32
- * @returns The built JSX tree
33
- */
34
- export declare function buildJSXTree({ importAliases, node, unwrappedExpressions, inStatic, visited, callStack, updates, errors, warnings, file, insideT, parsingOptions, scopeNode, importedFunctionsMap, pkgs, helperPath, }: {
35
- importAliases: Record<string, string>;
36
- node: any;
37
- callStack: string[];
38
- unwrappedExpressions: string[];
39
- updates: Updates;
40
- errors: string[];
41
- warnings: Set<string>;
42
- file: string;
43
- insideT: boolean;
44
- parsingOptions: ParsingConfigOptions;
45
- scopeNode: NodePath;
46
- importedFunctionsMap: Map<string, string>;
47
- pkgs: GTLibrary[];
48
- inStatic: boolean;
49
- visited: Set<string> | null;
50
- helperPath: NodePath;
51
- }): JsxTree | MultiplicationNode;
52
- export declare function parseJSXElement({ importAliases, node, originalName, pkgs, updates, errors, warnings, file, parsingOptions, scopeNode, importedFunctionsMap, }: {
53
- importAliases: Record<string, string>;
54
- node: t.JSXElement;
55
- originalName: string;
56
- pkgs: GTLibrary[];
57
- updates: Updates;
58
- errors: string[];
59
- warnings: Set<string>;
60
- file: string;
61
- parsingOptions: ParsingConfigOptions;
62
- scopeNode: NodePath<t.JSXElement>;
63
- importedFunctionsMap: Map<string, string>;
64
- }): void;
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import generateModule from '@babel/generator';
2
3
  // Handle CommonJS/ESM interop
3
4
  const generate = generateModule.default || generateModule;
@@ -77,7 +78,7 @@ export function parseTranslationComponent({ originalName, importAliases, localNa
77
78
  * @param insideT - Whether the current node is inside a <T> component
78
79
  * @returns The built JSX tree
79
80
  */
80
- export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStatic, visited, callStack, updates, errors, warnings, file, insideT, parsingOptions, scopeNode, importedFunctionsMap, pkgs, helperPath, }) {
81
+ function buildJSXTree({ importAliases, node, unwrappedExpressions, inStatic, visited, callStack, errors, warnings, file, insideT, parsingOptions, scopeNode, importedFunctionsMap, pkgs, helperPath, staticTracker, }) {
81
82
  if (t.isJSXExpressionContainer(node)) {
82
83
  // Skip JSX comments
83
84
  if (t.isJSXEmptyExpression(node.expression)) {
@@ -91,13 +92,13 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
91
92
  importAliases,
92
93
  visited: visited,
93
94
  callStack,
94
- updates,
95
95
  errors,
96
96
  warnings,
97
97
  file,
98
98
  parsingOptions,
99
99
  importedFunctionsMap,
100
100
  pkgs,
101
+ staticTracker,
101
102
  });
102
103
  }
103
104
  const expr = node.expression;
@@ -108,7 +109,6 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
108
109
  unwrappedExpressions,
109
110
  visited,
110
111
  callStack,
111
- updates,
112
112
  errors,
113
113
  warnings,
114
114
  file,
@@ -119,6 +119,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
119
119
  pkgs,
120
120
  inStatic,
121
121
  helperPath: helperPath.get('expression'),
122
+ staticTracker,
122
123
  });
123
124
  }
124
125
  const staticAnalysis = isStaticExpression(expr, true);
@@ -197,7 +198,6 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
197
198
  unwrappedExpressions,
198
199
  visited,
199
200
  callStack,
200
- updates,
201
201
  errors: errors,
202
202
  warnings: warnings,
203
203
  file: file,
@@ -208,6 +208,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
208
208
  pkgs,
209
209
  inStatic,
210
210
  helperPath: helperValue,
211
+ staticTracker,
211
212
  });
212
213
  }
213
214
  // For HTML content props, only accept static string expressions
@@ -247,7 +248,6 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
247
248
  unwrappedExpressions,
248
249
  visited,
249
250
  callStack,
250
- updates,
251
251
  errors,
252
252
  warnings,
253
253
  file,
@@ -258,6 +258,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
258
258
  pkgs,
259
259
  inStatic: true,
260
260
  helperPath: helperChild,
261
+ staticTracker,
261
262
  });
262
263
  results.props.children.push(result);
263
264
  }
@@ -278,7 +279,6 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
278
279
  unwrappedExpressions,
279
280
  visited,
280
281
  callStack,
281
- updates,
282
282
  errors,
283
283
  warnings,
284
284
  file,
@@ -289,6 +289,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
289
289
  pkgs,
290
290
  inStatic,
291
291
  helperPath: helperPath.get('children')[index],
292
+ staticTracker,
292
293
  }))
293
294
  .filter((child) => child !== null && child !== '');
294
295
  if (children.length === 1) {
@@ -314,7 +315,6 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
314
315
  unwrappedExpressions,
315
316
  visited,
316
317
  callStack,
317
- updates,
318
318
  errors,
319
319
  warnings,
320
320
  file,
@@ -325,6 +325,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
325
325
  pkgs,
326
326
  inStatic,
327
327
  helperPath: helperPath.get('children')[index],
328
+ staticTracker,
328
329
  }))
329
330
  .filter((child) => child !== null && child !== '');
330
331
  const props = {};
@@ -393,13 +394,13 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
393
394
  visited: visited, // we know this is true bc of inStatic
394
395
  callStack,
395
396
  file,
396
- updates,
397
397
  errors,
398
398
  warnings,
399
399
  unwrappedExpressions,
400
400
  pkgs,
401
401
  parsingOptions,
402
402
  importedFunctionsMap,
403
+ staticTracker,
403
404
  });
404
405
  }
405
406
  else {
@@ -414,7 +415,6 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
414
415
  unwrappedExpressions,
415
416
  visited,
416
417
  callStack,
417
- updates,
418
418
  errors,
419
419
  warnings,
420
420
  file,
@@ -425,6 +425,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
425
425
  pkgs,
426
426
  inStatic,
427
427
  helperPath: helperPath.get('expression'),
428
+ staticTracker,
428
429
  });
429
430
  }
430
431
  // If it's some other JS expression
@@ -448,7 +449,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStat
448
449
  }
449
450
  // end buildJSXTree
450
451
  // Parses a JSX element and adds it to the updates array
451
- export function parseJSXElement({ importAliases, node, originalName, pkgs, updates, errors, warnings, file, parsingOptions, scopeNode, importedFunctionsMap, }) {
452
+ function parseJSXElement({ importAliases, node, originalName, pkgs, updates, errors, warnings, file, parsingOptions, scopeNode, importedFunctionsMap, }) {
452
453
  const openingElement = node.openingElement;
453
454
  const name = openingElement.name;
454
455
  // Only proceed if it's <T> ...
@@ -470,6 +471,10 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
470
471
  componentErrors,
471
472
  file,
472
473
  });
474
+ // Flag for if contains static content
475
+ const staticTracker = {
476
+ isStatic: false,
477
+ };
473
478
  // Build the JSX tree for this component
474
479
  const treeResult = buildJSXTree({
475
480
  importAliases,
@@ -479,7 +484,6 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
479
484
  callStack: [],
480
485
  pkgs,
481
486
  unwrappedExpressions,
482
- updates,
483
487
  errors: componentErrors,
484
488
  warnings: componentWarnings,
485
489
  file,
@@ -488,6 +492,7 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
488
492
  importedFunctionsMap,
489
493
  inStatic: false,
490
494
  helperPath: scopeNode,
495
+ staticTracker,
491
496
  });
492
497
  // Strip the outer <T> component if necessary
493
498
  const jsxTree = isElementNode(treeResult) && treeResult.props?.children
@@ -521,6 +526,9 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
521
526
  errors.push(warnHasUnwrappedExpressionSync(file, unwrappedExpressions, metadata.id, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
522
527
  return;
523
528
  }
529
+ // Create a temporary unique flag for static content
530
+ const temporaryStaticId = `static-temp-id-${randomUUID()}`;
531
+ const isStatic = staticTracker.isStatic;
524
532
  // <T> is valid here
525
533
  for (const minifiedTree of minifiedTress) {
526
534
  // Clean the tree by removing null 'c' fields from JsxElements
@@ -528,12 +536,15 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
528
536
  updates.push({
529
537
  dataFormat: 'JSX',
530
538
  source: cleanedTree,
531
- // eslint-disable-next-line no-undef
532
- metadata: { ...structuredClone(metadata) },
539
+ metadata: {
540
+ // eslint-disable-next-line no-undef
541
+ ...structuredClone(metadata),
542
+ ...(isStatic && { staticId: temporaryStaticId }),
543
+ },
533
544
  });
534
545
  }
535
546
  }
536
- function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBinding, callee, unwrappedExpressions, visited, callStack, file, updates, errors, warnings, parsingOptions, importedFunctionsMap, pkgs, }) {
547
+ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBinding, callee, unwrappedExpressions, visited, callStack, file, errors, warnings, parsingOptions, importedFunctionsMap, pkgs, staticTracker, }) {
537
548
  function withRecusionGuard({ cb, filename, functionName, }) {
538
549
  const cacheKey = `${filename}::${functionName}`;
539
550
  if (callStack.includes(cacheKey)) {
@@ -559,7 +570,6 @@ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBindi
559
570
  path,
560
571
  unwrappedExpressions,
561
572
  callStack,
562
- updates,
563
573
  errors,
564
574
  warnings,
565
575
  visited,
@@ -567,6 +577,7 @@ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBindi
567
577
  parsingOptions,
568
578
  importedFunctionsMap,
569
579
  pkgs,
580
+ staticTracker,
570
581
  }),
571
582
  });
572
583
  }
@@ -585,7 +596,6 @@ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBindi
585
596
  functionName,
586
597
  path,
587
598
  unwrappedExpressions,
588
- updates,
589
599
  callStack,
590
600
  pkgs,
591
601
  errors,
@@ -594,6 +604,7 @@ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBindi
594
604
  file,
595
605
  parsingOptions,
596
606
  importedFunctionsMap,
607
+ staticTracker,
597
608
  }),
598
609
  });
599
610
  }
@@ -624,12 +635,12 @@ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBindi
624
635
  visited,
625
636
  callStack,
626
637
  unwrappedExpressions,
627
- updates,
628
638
  errors,
629
639
  warnings,
630
640
  file,
631
641
  parsingOptions,
632
642
  pkgs,
643
+ staticTracker,
633
644
  }),
634
645
  });
635
646
  if (result !== null) {
@@ -651,7 +662,7 @@ function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBindi
651
662
  *
652
663
  * If the function is not found in the file, follows re-exports (export * from './other')
653
664
  */
654
- function processFunctionInFile({ filePath, functionName, visited, callStack, parsingOptions, updates, errors, warnings, file, unwrappedExpressions, pkgs, }) {
665
+ function processFunctionInFile({ filePath, functionName, visited, callStack, parsingOptions, errors, warnings, file, unwrappedExpressions, pkgs, staticTracker, }) {
655
666
  // Create a custom key for the function call
656
667
  const cacheKey = `${filePath}::${functionName}`;
657
668
  // Check cache first to avoid redundant parsing
@@ -696,12 +707,12 @@ function processFunctionInFile({ filePath, functionName, visited, callStack, par
696
707
  callStack,
697
708
  visited,
698
709
  pkgs,
699
- updates,
700
710
  errors,
701
711
  warnings,
702
712
  file: filePath,
703
713
  parsingOptions,
704
714
  importedFunctionsMap,
715
+ staticTracker,
705
716
  });
706
717
  }
707
718
  },
@@ -720,7 +731,6 @@ function processFunctionInFile({ filePath, functionName, visited, callStack, par
720
731
  path,
721
732
  callStack,
722
733
  pkgs,
723
- updates,
724
734
  errors,
725
735
  warnings,
726
736
  visited,
@@ -728,6 +738,7 @@ function processFunctionInFile({ filePath, functionName, visited, callStack, par
728
738
  file: filePath,
729
739
  parsingOptions,
730
740
  importedFunctionsMap,
741
+ staticTracker,
731
742
  });
732
743
  }
733
744
  },
@@ -768,11 +779,11 @@ function processFunctionInFile({ filePath, functionName, visited, callStack, par
768
779
  visited,
769
780
  callStack,
770
781
  parsingOptions,
771
- updates,
772
782
  errors,
773
783
  warnings,
774
784
  file: filePath,
775
785
  pkgs,
786
+ staticTracker,
776
787
  });
777
788
  if (foundResult != null) {
778
789
  result = foundResult;
@@ -795,7 +806,7 @@ function processFunctionInFile({ filePath, functionName, visited, callStack, par
795
806
  * Process a function declaration
796
807
  * function getInfo() { ... }
797
808
  */
798
- function processFunctionDeclarationNodePath({ functionName, path, importAliases, unwrappedExpressions, visited, callStack, updates, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, }) {
809
+ function processFunctionDeclarationNodePath({ functionName, path, importAliases, unwrappedExpressions, visited, callStack, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, staticTracker, }) {
799
810
  const result = {
800
811
  nodeType: 'multiplication',
801
812
  branches: [],
@@ -817,12 +828,12 @@ function processFunctionDeclarationNodePath({ functionName, path, importAliases,
817
828
  expressionNodePath: returnNodePath,
818
829
  importAliases,
819
830
  visited,
820
- updates,
821
831
  errors,
822
832
  warnings,
823
833
  file,
824
834
  parsingOptions,
825
835
  importedFunctionsMap,
836
+ staticTracker,
826
837
  }));
827
838
  },
828
839
  });
@@ -837,7 +848,7 @@ function processFunctionDeclarationNodePath({ functionName, path, importAliases,
837
848
  *
838
849
  * IMPORTANT: the RHand value must be the function definition, or this will fail
839
850
  */
840
- function processVariableDeclarationNodePath({ functionName, path, importAliases, unwrappedExpressions, visited, callStack, updates, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, }) {
851
+ function processVariableDeclarationNodePath({ functionName, path, importAliases, unwrappedExpressions, visited, callStack, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, staticTracker, }) {
841
852
  const result = {
842
853
  nodeType: 'multiplication',
843
854
  branches: [],
@@ -859,12 +870,12 @@ function processVariableDeclarationNodePath({ functionName, path, importAliases,
859
870
  importAliases,
860
871
  visited,
861
872
  callStack,
862
- updates,
863
873
  errors,
864
874
  warnings,
865
875
  file,
866
876
  parsingOptions,
867
877
  importedFunctionsMap,
878
+ staticTracker,
868
879
  }));
869
880
  }
870
881
  else {
@@ -886,12 +897,12 @@ function processVariableDeclarationNodePath({ functionName, path, importAliases,
886
897
  importAliases,
887
898
  visited,
888
899
  callStack,
889
- updates,
890
900
  errors,
891
901
  warnings,
892
902
  file,
893
903
  parsingOptions,
894
904
  importedFunctionsMap,
905
+ staticTracker,
895
906
  }));
896
907
  },
897
908
  });
@@ -905,9 +916,9 @@ function processVariableDeclarationNodePath({ functionName, path, importAliases,
905
916
  /**
906
917
  * Process a <Static> expression
907
918
  */
908
- function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNodePath, importAliases, visited, callStack, updates, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, }) {
909
- // // If the node is null, return
910
- // if (expressionNodePath == null) return null;
919
+ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNodePath, importAliases, visited, callStack, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, staticTracker, }) {
920
+ // Mark the static tracker as true
921
+ staticTracker.isStatic = true;
911
922
  // Remove parentheses if they exist
912
923
  if (t.isParenthesizedExpression(expressionNodePath.node)) {
913
924
  // ex: return (value)
@@ -918,13 +929,13 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
918
929
  expressionNodePath: expressionNodePath.get('expression'),
919
930
  visited,
920
931
  callStack,
921
- updates,
922
932
  errors,
923
933
  warnings,
924
934
  file,
925
935
  parsingOptions,
926
936
  importedFunctionsMap,
927
937
  pkgs,
938
+ staticTracker,
928
939
  });
929
940
  }
930
941
  else if (t.isCallExpression(expressionNodePath.node) &&
@@ -945,12 +956,12 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
945
956
  callStack,
946
957
  visited,
947
958
  file,
948
- updates,
949
959
  errors,
950
960
  warnings,
951
961
  pkgs,
952
962
  parsingOptions,
953
963
  importedFunctionsMap,
964
+ staticTracker,
954
965
  });
955
966
  }
956
967
  else if (t.isAwaitExpression(expressionNodePath.node) &&
@@ -972,12 +983,12 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
972
983
  visited,
973
984
  callStack,
974
985
  file,
975
- updates,
976
986
  errors,
977
987
  warnings,
978
988
  pkgs,
979
989
  parsingOptions,
980
990
  importedFunctionsMap,
991
+ staticTracker,
981
992
  });
982
993
  }
983
994
  else if (t.isJSXElement(expressionNodePath.node) ||
@@ -989,7 +1000,6 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
989
1000
  unwrappedExpressions,
990
1001
  visited,
991
1002
  callStack,
992
- updates,
993
1003
  errors,
994
1004
  warnings,
995
1005
  file,
@@ -1000,6 +1010,7 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
1000
1010
  pkgs,
1001
1011
  inStatic: true,
1002
1012
  helperPath: expressionNodePath,
1013
+ staticTracker,
1003
1014
  });
1004
1015
  }
1005
1016
  else if (t.isConditionalExpression(expressionNodePath.node)) {
@@ -1016,13 +1027,13 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
1016
1027
  expressionNodePath,
1017
1028
  visited,
1018
1029
  callStack,
1019
- updates,
1020
1030
  errors,
1021
1031
  warnings,
1022
1032
  file,
1023
1033
  parsingOptions,
1024
1034
  importedFunctionsMap,
1025
1035
  pkgs,
1036
+ staticTracker,
1026
1037
  })),
1027
1038
  };
1028
1039
  return result;
@@ -1034,7 +1045,6 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
1034
1045
  unwrappedExpressions,
1035
1046
  visited,
1036
1047
  callStack,
1037
- updates,
1038
1048
  errors,
1039
1049
  warnings,
1040
1050
  file,
@@ -1045,6 +1055,7 @@ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNo
1045
1055
  pkgs,
1046
1056
  inStatic: true,
1047
1057
  helperPath: expressionNodePath,
1058
+ staticTracker,
1048
1059
  });
1049
1060
  }
1050
1061
  }
@@ -16,6 +16,7 @@ import { handleStaticExpression } from './parseDeclareStatic.js';
16
16
  import { nodeToStrings } from './parseString.js';
17
17
  import { isNumberLiteral } from './isNumberLiteral.js';
18
18
  import { indexVars } from 'generaltranslation/internal';
19
+ import { randomUUID } from 'node:crypto';
19
20
  /**
20
21
  * Cache for resolved import paths to avoid redundant I/O operations.
21
22
  * Key: `${currentFile}::${importPath}`
@@ -87,11 +88,12 @@ function processTranslationCall(tPath, updates, errors, warnings, file, ignoreAd
87
88
  }
88
89
  });
89
90
  }
91
+ const temporaryStaticId = `static-temp-id-${randomUUID()}`;
90
92
  for (const string of strings) {
91
93
  updates.push({
92
94
  dataFormat: 'ICU',
93
95
  source: string,
94
- metadata: { ...metadata },
96
+ metadata: { ...metadata, staticId: temporaryStaticId },
95
97
  });
96
98
  }
97
99
  return;
@@ -6,4 +6,8 @@ export declare function createInlineUpdates(pkg: GTLibrary, validate: boolean, f
6
6
  errors: string[];
7
7
  warnings: string[];
8
8
  }>;
9
- export declare function mergeUpdatesByHash(updates: Updates): void;
9
+ /**
10
+ * Dedupe entries
11
+ */
12
+ declare function dedupeUpdates(updates: Updates): void;
13
+ export { dedupeUpdates as _test_dedupeUpdates };
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import { parse } from '@babel/parser';
3
- import { hashSource } from 'generaltranslation/id';
3
+ import { hashSource, hashString } from 'generaltranslation/id';
4
4
  import { parseTranslationComponent } from '../jsx/utils/jsxParsing/parseJsx.js';
5
5
  import { parseStrings } from '../jsx/utils/parseStringFunction.js';
6
6
  import { logger } from '../../console/logger.js';
@@ -50,15 +50,25 @@ export async function createInlineUpdates(pkg, validate, filePatterns, parsingOp
50
50
  parsingOptions,
51
51
  });
52
52
  }
53
- // Extra validation (for Locadex)
54
- // Done in parseStrings() atm
55
- // if (validate) {
56
- // for (const { localName: name, path, originalName } of translationPaths) {
57
- // validateStringFunction(name, path, updates, errors, file, originalName);
58
- // }
59
- // }
60
53
  }
61
- // Post-process to add a hash to each update
54
+ // Post processing steps:
55
+ await calculateHashes(updates);
56
+ dedupeUpdates(updates);
57
+ linkStaticUpdates(updates);
58
+ return { updates, errors, warnings: [...warnings] };
59
+ }
60
+ /**
61
+ * Given a package name, return the upstream packages that it depends on
62
+ * @param pkg
63
+ */
64
+ function getUpstreamPackages(pkg) {
65
+ return GT_LIBRARIES_UPSTREAM[pkg];
66
+ }
67
+ /**
68
+ * Calculate hashes
69
+ */
70
+ async function calculateHashes(updates) {
71
+ // parallel calculation of hashes
62
72
  await Promise.all(updates.map(async (update) => {
63
73
  const hash = hashSource({
64
74
  source: update.source,
@@ -71,17 +81,11 @@ export async function createInlineUpdates(pkg, validate, filePatterns, parsingOp
71
81
  });
72
82
  update.metadata.hash = hash;
73
83
  }));
74
- mergeUpdatesByHash(updates);
75
- return { updates, errors, warnings: [...warnings] };
76
84
  }
77
85
  /**
78
- * Given a package name, return the upstream packages that it depends on
79
- * @param pkg
86
+ * Dedupe entries
80
87
  */
81
- function getUpstreamPackages(pkg) {
82
- return GT_LIBRARIES_UPSTREAM[pkg];
83
- }
84
- export function mergeUpdatesByHash(updates) {
88
+ function dedupeUpdates(updates) {
85
89
  const mergedByHash = new Map();
86
90
  const noHashUpdates = [];
87
91
  for (const update of updates) {
@@ -113,3 +117,31 @@ export function mergeUpdatesByHash(updates) {
113
117
  const mergedUpdates = [...mergedByHash.values(), ...noHashUpdates];
114
118
  updates.splice(0, updates.length, ...mergedUpdates);
115
119
  }
120
+ /**
121
+ * Mark static updates as the related by attaching a shared id to static content
122
+ * Id is calculated as the hash of the static children's combined hashes
123
+ */
124
+ function linkStaticUpdates(updates) {
125
+ // construct map of temporary static ids to updates
126
+ const temporaryStaticIdToUpdates = updates.reduce((acc, update) => {
127
+ if (update.metadata.staticId) {
128
+ if (!acc[update.metadata.staticId]) {
129
+ acc[update.metadata.staticId] = [];
130
+ }
131
+ acc[update.metadata.staticId].push(update);
132
+ }
133
+ return acc;
134
+ }, {});
135
+ // Calculate shared static ids
136
+ Object.values(temporaryStaticIdToUpdates).forEach((staticUpdates) => {
137
+ const hashes = staticUpdates
138
+ .map((update) => update.metadata.hash)
139
+ .sort()
140
+ .join('-');
141
+ const sharedStaticId = hashString(hashes);
142
+ staticUpdates.forEach((update) => {
143
+ update.metadata.staticId = sharedStaticId;
144
+ });
145
+ });
146
+ }
147
+ export { dedupeUpdates as _test_dedupeUpdates };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.6.0",
3
+ "version": "2.6.1",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -106,7 +106,7 @@
106
106
  "unified": "^11.0.5",
107
107
  "unist-util-visit": "^5.0.0",
108
108
  "yaml": "^2.8.0",
109
- "generaltranslation": "8.1.6"
109
+ "generaltranslation": "8.1.7"
110
110
  },
111
111
  "devDependencies": {
112
112
  "@babel/types": "^7.28.4",