@lang-tag/cli 0.16.0 → 0.18.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,9 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const flexibleImportAlgorithm = require("../flexible-import-algorithm-Fa-l4jWj.cjs");
4
- const path = require("pathe");
3
+ const caseLib = require("case");
5
4
  const process = require("node:process");
6
- class DictionaryCollector extends flexibleImportAlgorithm.TranslationsCollector {
5
+ const promises = require("fs/promises");
6
+ const path = require("pathe");
7
+ const namespaceCollector = require("../chunks/namespace-collector.cjs");
8
+ const micromatch = require("micromatch");
9
+ function _interopNamespaceDefault(e) {
10
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
11
+ if (e) {
12
+ for (const k in e) {
13
+ if (k !== "default") {
14
+ const d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: () => e[k]
18
+ });
19
+ }
20
+ }
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+ const caseLib__namespace = /* @__PURE__ */ _interopNamespaceDefault(caseLib);
26
+ function applyCaseTransform(str, caseType) {
27
+ if (caseType === "no") {
28
+ return str;
29
+ }
30
+ const caseFunction = caseLib__namespace[caseType];
31
+ if (typeof caseFunction === "function") {
32
+ return caseFunction(str);
33
+ }
34
+ return str;
35
+ }
36
+ class DictionaryCollector extends namespaceCollector.TranslationsCollector {
7
37
  constructor(options = {
8
38
  appendNamespaceToPath: false
9
39
  }) {
@@ -36,12 +66,15 @@ class DictionaryCollector extends flexibleImportAlgorithm.TranslationsCollector
36
66
  }
37
67
  async preWrite(clean) {
38
68
  this.clean = clean;
39
- const baseDictionaryFile = path.join(this.config.localesDirectory, `${this.config.baseLanguageCode}.json`);
69
+ const baseDictionaryFile = path.join(
70
+ this.config.localesDirectory,
71
+ `${this.config.baseLanguageCode}.json`
72
+ );
40
73
  if (clean) {
41
74
  this.logger.info("Removing {file}", { file: baseDictionaryFile });
42
- await flexibleImportAlgorithm.$LT_RemoveFile(baseDictionaryFile);
75
+ await removeFile(baseDictionaryFile);
43
76
  }
44
- await flexibleImportAlgorithm.$LT_EnsureDirectoryExists(this.config.localesDirectory);
77
+ await ensureDirectoryExists(this.config.localesDirectory);
45
78
  }
46
79
  async resolveCollectionFilePath(baseLanguageCode) {
47
80
  return path.resolve(
@@ -52,16 +85,23 @@ class DictionaryCollector extends flexibleImportAlgorithm.TranslationsCollector
52
85
  }
53
86
  async onMissingCollection(baseLanguageCode) {
54
87
  if (!this.clean) {
55
- this.logger.warn(`Original dictionary file "{namespace}.json" not found. A new one will be created.`, { namespace: baseLanguageCode });
88
+ this.logger.warn(
89
+ `Original dictionary file "{namespace}.json" not found. A new one will be created.`,
90
+ { namespace: baseLanguageCode }
91
+ );
56
92
  }
57
93
  }
58
94
  async postWrite(changedCollections) {
59
95
  if (!changedCollections?.length) {
60
- this.logger.info("No changes were made based on the current configuration and files");
96
+ this.logger.info(
97
+ "No changes were made based on the current configuration and files"
98
+ );
61
99
  return;
62
100
  }
63
101
  if (changedCollections.length > 1) {
64
- throw new Error("Should not write more than 1 collection! Only 1 base language dictionary expected!");
102
+ throw new Error(
103
+ "Should not write more than 1 collection! Only 1 base language dictionary expected!"
104
+ );
65
105
  }
66
106
  const dict = path.resolve(
67
107
  this.config.localesDirectory,
@@ -70,6 +110,21 @@ class DictionaryCollector extends flexibleImportAlgorithm.TranslationsCollector
70
110
  this.logger.success("Updated dictionary {dict}", { dict });
71
111
  }
72
112
  }
113
+ async function ensureDirectoryExists(filePath) {
114
+ try {
115
+ await promises.mkdir(filePath, { recursive: true });
116
+ } catch (error) {
117
+ if (error.code !== "EEXIST") {
118
+ throw error;
119
+ }
120
+ }
121
+ }
122
+ async function removeFile(filePath) {
123
+ try {
124
+ await promises.rm(filePath, { force: true });
125
+ } catch (error) {
126
+ }
127
+ }
73
128
  const TRIGGER_NAME$2 = "path-based-config-generator";
74
129
  function pathBasedConfigGenerator(options = {}) {
75
130
  const {
@@ -116,15 +171,22 @@ function pathBasedConfigGenerator(options = {}) {
116
171
  if (hasPathRules) {
117
172
  pathSegments = applyPathRules(pathSegments, pathRules);
118
173
  } else {
119
- pathSegments = applyStructuredIgnore(pathSegments, ignoreStructured);
174
+ pathSegments = applyStructuredIgnore(
175
+ pathSegments,
176
+ ignoreStructured
177
+ );
120
178
  }
121
179
  if (ignoreIncludesRootDirectories && langTagConfig.includes && pathSegments.length > 0) {
122
- const extractedDirectories = extractRootDirectoriesFromIncludes(langTagConfig.includes);
180
+ const extractedDirectories = extractRootDirectoriesFromIncludes(
181
+ langTagConfig.includes
182
+ );
123
183
  if (extractedDirectories.includes(pathSegments[0])) {
124
184
  pathSegments = pathSegments.slice(1);
125
185
  }
126
186
  }
127
- pathSegments = pathSegments.filter((seg) => !ignoreDirectories.includes(seg));
187
+ pathSegments = pathSegments.filter(
188
+ (seg) => !ignoreDirectories.includes(seg)
189
+ );
128
190
  let namespace;
129
191
  let path$1;
130
192
  if (pathSegments.length >= 1) {
@@ -142,12 +204,14 @@ function pathBasedConfigGenerator(options = {}) {
142
204
  namespace = namespace.toLowerCase();
143
205
  }
144
206
  if (namespaceCase) {
145
- namespace = flexibleImportAlgorithm.applyCaseTransform(namespace, namespaceCase);
207
+ namespace = applyCaseTransform(namespace, namespaceCase);
146
208
  }
147
209
  }
148
210
  if (path$1 && pathCase) {
149
211
  const pathParts = path$1.split(".");
150
- const transformedParts = pathParts.map((part) => flexibleImportAlgorithm.applyCaseTransform(part, pathCase));
212
+ const transformedParts = pathParts.map(
213
+ (part) => applyCaseTransform(part, pathCase)
214
+ );
151
215
  path$1 = transformedParts.join(".");
152
216
  }
153
217
  const newConfig = event.config ? { ...event.config } : {};
@@ -306,7 +370,10 @@ function applyPathRules(segments, structure) {
306
370
  const remainingSegments = segments.slice(i + 1);
307
371
  const ruleWithoutRedirect = { ...rule };
308
372
  delete ruleWithoutRedirect[">>"];
309
- const processedRemaining = applyPathRules(remainingSegments, ruleWithoutRedirect);
373
+ const processedRemaining = applyPathRules(
374
+ remainingSegments,
375
+ ruleWithoutRedirect
376
+ );
310
377
  deepestRedirect = {
311
378
  rule: redirectRule,
312
379
  remainingSegments: processedRemaining,
@@ -432,13 +499,291 @@ function prependNamespaceToPath(options = {}) {
432
499
  } else {
433
500
  newPath = actualNamespace;
434
501
  }
435
- event.save({
436
- ...currentConfig || {},
437
- path: newPath,
438
- namespace: void 0
439
- }, TRIGGER_NAME);
502
+ event.save(
503
+ {
504
+ ...currentConfig || {},
505
+ path: newPath,
506
+ namespace: void 0
507
+ },
508
+ TRIGGER_NAME
509
+ );
440
510
  };
441
511
  }
512
+ function flexibleImportAlgorithm(options = {}) {
513
+ const {
514
+ variableName = {},
515
+ filePath = {},
516
+ include,
517
+ exclude = {},
518
+ configRemap
519
+ } = options;
520
+ const { packages: includePackages, namespaces: includeNamespaces } = include || {};
521
+ const {
522
+ packages: excludePackages = [],
523
+ namespaces: excludeNamespaces = []
524
+ } = exclude;
525
+ return (event) => {
526
+ const { exports: exports2, importManager, logger } = event;
527
+ for (const { packageJSON, exportData } of exports2) {
528
+ const packageName = packageJSON.name || "unknown-package";
529
+ if (includePackages && !matchesAnyPattern(packageName, includePackages)) {
530
+ logger.debug(
531
+ `Skipping package not in include list: ${packageName}`
532
+ );
533
+ continue;
534
+ }
535
+ if (matchesAnyPattern(packageName, excludePackages)) {
536
+ logger.debug(`Skipping excluded package: ${packageName}`);
537
+ continue;
538
+ }
539
+ logger.debug(`Processing library: ${packageName}`);
540
+ for (const file of exportData.files) {
541
+ const originalFileName = file.relativeFilePath;
542
+ const targetFilePath = generateFilePath(
543
+ packageName,
544
+ originalFileName,
545
+ filePath
546
+ );
547
+ for (let i = 0; i < file.tags.length; i++) {
548
+ const tag = file.tags[i];
549
+ const tagNamespace = tag.config?.namespace;
550
+ if (includeNamespaces && tagNamespace && !matchesAnyPattern(tagNamespace, includeNamespaces)) {
551
+ logger.debug(
552
+ `Skipping namespace not in include list: ${tagNamespace}`
553
+ );
554
+ continue;
555
+ }
556
+ if (tagNamespace && matchesAnyPattern(tagNamespace, excludeNamespaces)) {
557
+ logger.debug(
558
+ `Skipping excluded namespace: ${tagNamespace}`
559
+ );
560
+ continue;
561
+ }
562
+ const finalVariableName = generateVariableName(
563
+ tag.variableName,
564
+ packageName,
565
+ originalFileName,
566
+ i,
567
+ variableName,
568
+ tag
569
+ );
570
+ if (finalVariableName === null) {
571
+ logger.debug(
572
+ `Skipping tag without variableName in ${path.join(packageName, originalFileName)}`
573
+ );
574
+ continue;
575
+ }
576
+ let finalConfig = tag.config;
577
+ if (configRemap) {
578
+ const remappedConfig = configRemap(tag.config, {
579
+ packageName,
580
+ fileName: originalFileName,
581
+ variableName: finalVariableName,
582
+ tagIndex: i
583
+ });
584
+ if (remappedConfig === null) {
585
+ logger.debug(
586
+ `Removing config due to configRemap returning null in ${path.join(packageName, originalFileName)}`
587
+ );
588
+ finalConfig = null;
589
+ } else {
590
+ finalConfig = remappedConfig;
591
+ }
592
+ }
593
+ importManager.importTag(targetFilePath, {
594
+ variableName: finalVariableName,
595
+ translations: tag.translations,
596
+ config: finalConfig
597
+ });
598
+ logger.debug(
599
+ `Imported: ${finalVariableName} -> ${targetFilePath}`
600
+ );
601
+ }
602
+ }
603
+ }
604
+ };
605
+ }
606
+ function sanitizeVariableName(name) {
607
+ let sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "$");
608
+ if (/^[0-9]/.test(sanitized)) {
609
+ sanitized = "$" + sanitized;
610
+ }
611
+ if (sanitized === "") {
612
+ sanitized = "$";
613
+ }
614
+ return sanitized;
615
+ }
616
+ function applyCaseTransformToPath(filePath, caseType) {
617
+ if (typeof caseType === "string") {
618
+ const segments = filePath.split("/");
619
+ const fileName = segments[segments.length - 1];
620
+ const directorySegments = segments.slice(0, -1);
621
+ const transformedDirectories = directorySegments.map(
622
+ (dir) => applyCaseTransform(dir, caseType)
623
+ );
624
+ const transformedFileName = applyCaseTransformToFileName(
625
+ fileName,
626
+ caseType
627
+ );
628
+ if (transformedDirectories.length === 0) {
629
+ return transformedFileName;
630
+ }
631
+ return [...transformedDirectories, transformedFileName].join("/");
632
+ }
633
+ if (typeof caseType === "object") {
634
+ const { directories = "no", files = "no" } = caseType;
635
+ const segments = filePath.split("/");
636
+ const fileName = segments[segments.length - 1];
637
+ const directorySegments = segments.slice(0, -1);
638
+ const transformedDirectories = directorySegments.map(
639
+ (dir) => applyCaseTransform(dir, directories)
640
+ );
641
+ const transformedFileName = applyCaseTransformToFileName(
642
+ fileName,
643
+ files
644
+ );
645
+ if (transformedDirectories.length === 0) {
646
+ return transformedFileName;
647
+ }
648
+ return [...transformedDirectories, transformedFileName].join("/");
649
+ }
650
+ return filePath;
651
+ }
652
+ function normalizePackageName(packageName, scopedPackageHandling = "replace", context = "variableName") {
653
+ switch (scopedPackageHandling) {
654
+ case "remove-scope":
655
+ let result = packageName.replace(/^@[^/]+\//, "");
656
+ if (context === "variableName") {
657
+ result = result.replace(/[^a-zA-Z0-9_$]/g, "_");
658
+ }
659
+ return result;
660
+ case "replace":
661
+ default:
662
+ let normalized = packageName.replace(/@/g, "").replace(/\//g, context === "variableName" ? "_" : "-");
663
+ if (context === "variableName") {
664
+ normalized = normalized.replace(/[^a-zA-Z0-9_$]/g, "_");
665
+ }
666
+ return normalized;
667
+ }
668
+ }
669
+ function generateVariableName(originalVariableName, packageName, fileName, index, options, tag) {
670
+ const {
671
+ prefixWithPackageName = false,
672
+ scopedPackageHandling = "replace",
673
+ case: caseType = "no",
674
+ sanitizeVariableName: shouldSanitize = true,
675
+ handleMissingVariableName = "auto-generate",
676
+ customVariableName
677
+ } = options;
678
+ if (customVariableName) {
679
+ const customName = customVariableName({
680
+ packageName,
681
+ fileName,
682
+ originalVariableName,
683
+ tagIndex: index,
684
+ tag
685
+ });
686
+ if (customName !== null) {
687
+ originalVariableName = customName;
688
+ }
689
+ }
690
+ if (!originalVariableName) {
691
+ switch (handleMissingVariableName) {
692
+ case "skip":
693
+ return null;
694
+ case "auto-generate":
695
+ originalVariableName = `translations${index + 1}`;
696
+ break;
697
+ default:
698
+ if (typeof handleMissingVariableName === "function") {
699
+ originalVariableName = handleMissingVariableName(
700
+ {},
701
+ packageName,
702
+ fileName,
703
+ index
704
+ );
705
+ } else {
706
+ return null;
707
+ }
708
+ }
709
+ }
710
+ let finalName = originalVariableName;
711
+ if (prefixWithPackageName) {
712
+ const normalizedPackageName = normalizePackageName(
713
+ packageName,
714
+ scopedPackageHandling,
715
+ "variableName"
716
+ );
717
+ finalName = `${normalizedPackageName}_${originalVariableName}`;
718
+ }
719
+ const transformedName = applyCaseTransform(finalName, caseType);
720
+ return shouldSanitize ? sanitizeVariableName(transformedName) : transformedName;
721
+ }
722
+ function generateFilePath(packageName, originalFileName, options) {
723
+ const {
724
+ groupByPackage = false,
725
+ includePackageInPath = false,
726
+ scopedPackageHandling = "replace",
727
+ case: caseType = "no"
728
+ } = options;
729
+ if (groupByPackage) {
730
+ const normalizedPackageName = normalizePackageName(
731
+ packageName,
732
+ scopedPackageHandling,
733
+ "filePath"
734
+ );
735
+ const fileName = `${normalizedPackageName}.ts`;
736
+ return applyCaseTransformToFileName(
737
+ fileName,
738
+ typeof caseType === "string" ? caseType : caseType.files || "no"
739
+ );
740
+ } else if (includePackageInPath) {
741
+ const normalizedPackageName = normalizePackageName(
742
+ packageName,
743
+ scopedPackageHandling,
744
+ "filePath"
745
+ );
746
+ if (typeof caseType === "string") {
747
+ const transformedPackageName = applyCaseTransform(
748
+ normalizedPackageName,
749
+ caseType
750
+ );
751
+ const transformedFilePath = applyCaseTransformToPath(
752
+ originalFileName,
753
+ caseType
754
+ );
755
+ return path.join(transformedPackageName, transformedFilePath);
756
+ } else {
757
+ const transformedPackageName = applyCaseTransform(
758
+ normalizedPackageName,
759
+ caseType.directories || "no"
760
+ );
761
+ const transformedFilePath = applyCaseTransformToPath(
762
+ originalFileName,
763
+ caseType
764
+ );
765
+ return path.join(transformedPackageName, transformedFilePath);
766
+ }
767
+ } else {
768
+ return applyCaseTransformToPath(originalFileName, caseType);
769
+ }
770
+ }
771
+ function applyCaseTransformToFileName(fileName, caseType) {
772
+ if (caseType === "no") {
773
+ return fileName;
774
+ }
775
+ const lastDotIndex = fileName.lastIndexOf(".");
776
+ if (lastDotIndex === -1) {
777
+ return applyCaseTransform(fileName, caseType);
778
+ }
779
+ const nameWithoutExt = fileName.substring(0, lastDotIndex);
780
+ const extension = fileName.substring(lastDotIndex);
781
+ const transformedName = applyCaseTransform(nameWithoutExt, caseType);
782
+ return transformedName + extension;
783
+ }
784
+ function matchesAnyPattern(str, patterns) {
785
+ return micromatch.isMatch(str, patterns);
786
+ }
442
787
  function simpleMappingImportAlgorithm(options) {
443
788
  const { mappings, configRemap } = options;
444
789
  const packageMap = /* @__PURE__ */ new Map();
@@ -467,14 +812,20 @@ function simpleMappingImportAlgorithm(options) {
467
812
  if (!packageFiles) continue;
468
813
  const fileMapping = packageFiles.get(sourceFile);
469
814
  if (!fileMapping) {
470
- logger.debug(`Skipping unmapped file: ${packageName}/${sourceFile}`);
815
+ logger.debug(
816
+ `Skipping unmapped file: ${packageName}/${sourceFile}`
817
+ );
471
818
  continue;
472
819
  }
473
- logger.debug(`Processing mapped file: ${packageName}/${sourceFile} -> ${fileMapping.targetFile}`);
820
+ logger.debug(
821
+ `Processing mapped file: ${packageName}/${sourceFile} -> ${fileMapping.targetFile}`
822
+ );
474
823
  for (const tag of file.tags) {
475
824
  const originalVariableName = tag.variableName;
476
825
  if (!originalVariableName || !(originalVariableName in fileMapping.variables)) {
477
- logger.debug(`Skipping unmapped variable: ${originalVariableName} in ${packageName}/${sourceFile}`);
826
+ logger.debug(
827
+ `Skipping unmapped variable: ${originalVariableName} in ${packageName}/${sourceFile}`
828
+ );
478
829
  continue;
479
830
  }
480
831
  const newVariableName = fileMapping.variables[originalVariableName] || originalVariableName;
@@ -494,17 +845,19 @@ function simpleMappingImportAlgorithm(options) {
494
845
  translations: tag.translations,
495
846
  config: finalConfig
496
847
  });
497
- logger.debug(`Imported: ${originalVariableName} -> ${newVariableName} in ${targetFilePath}`);
848
+ logger.debug(
849
+ `Imported: ${originalVariableName} -> ${newVariableName} in ${targetFilePath}`
850
+ );
498
851
  }
499
852
  }
500
853
  }
501
854
  };
502
855
  }
503
- exports.NamespaceCollector = flexibleImportAlgorithm.NamespaceCollector;
504
- exports.applyCaseTransform = flexibleImportAlgorithm.applyCaseTransform;
505
- exports.flexibleImportAlgorithm = flexibleImportAlgorithm.flexibleImportAlgorithm;
856
+ exports.NamespaceCollector = namespaceCollector.NamespaceCollector;
506
857
  exports.DictionaryCollector = DictionaryCollector;
858
+ exports.applyCaseTransform = applyCaseTransform;
507
859
  exports.configKeeper = configKeeper;
860
+ exports.flexibleImportAlgorithm = flexibleImportAlgorithm;
508
861
  exports.pathBasedConfigGenerator = pathBasedConfigGenerator;
509
862
  exports.prependNamespaceToPath = prependNamespaceToPath;
510
863
  exports.simpleMappingImportAlgorithm = simpleMappingImportAlgorithm;
@@ -8,6 +8,6 @@
8
8
  * - Case Utils: Common case transformation utilities
9
9
  */
10
10
  export * from './case-utils';
11
- export * from './collector/index.ts';
12
- export * from './config-generation/index.ts';
13
- export * from './import/index.ts';
11
+ export * from './collector/index';
12
+ export * from './config-generation/index';
13
+ export * from './import/index';