gt 2.14.33 → 2.14.34

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 (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli/inline.js +1 -1
  3. package/dist/formats/files/collectFiles.js +1 -1
  4. package/dist/formats/json/extractJson.js +4 -2
  5. package/dist/formats/json/flattenJson.d.ts +3 -2
  6. package/dist/formats/json/flattenJson.js +3 -15
  7. package/dist/formats/json/jsonPath.d.ts +8 -0
  8. package/dist/formats/json/jsonPath.js +19 -0
  9. package/dist/formats/json/jsonPointer.d.ts +4 -0
  10. package/dist/formats/json/jsonPointer.js +20 -0
  11. package/dist/formats/json/mergeJson.d.ts +2 -1
  12. package/dist/formats/json/mergeJson.js +23 -32
  13. package/dist/formats/json/parseJson.js +5 -13
  14. package/dist/formats/json/transformJson.d.ts +3 -2
  15. package/dist/formats/json/transformJson.js +7 -31
  16. package/dist/formats/json/utils.d.ts +14 -10
  17. package/dist/formats/json/utils.js +13 -13
  18. package/dist/fs/copyFile.d.ts +4 -2
  19. package/dist/generated/version.d.ts +1 -1
  20. package/dist/generated/version.js +1 -1
  21. package/dist/translation/parse.js +27 -8
  22. package/dist/types/data/json.d.ts +1 -2
  23. package/dist/types/index.d.ts +4 -0
  24. package/dist/utils/addExplicitAnchorIds.d.ts +6 -1
  25. package/dist/utils/localizeRelativeAssets.d.ts +3 -2
  26. package/dist/utils/localizeRelativeAssets.js +16 -15
  27. package/dist/utils/localizeStaticImports.d.ts +3 -2
  28. package/dist/utils/localizeStaticImports.js +1 -1
  29. package/dist/utils/localizeStaticUrls.d.ts +3 -2
  30. package/dist/utils/localizeStaticUrls.js +1 -1
  31. package/dist/utils/sharedStaticAssets.js +20 -21
  32. package/dist/workflows/steps/BranchStep.d.ts +6 -3
  33. package/dist/workflows/steps/UploadSourcesStep.d.ts +6 -3
  34. package/package.json +12 -11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.14.34
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1385](https://github.com/generaltranslation/gt/pull/1385) [`bcb2b91`](https://github.com/generaltranslation/gt/commit/bcb2b91581d1edb134a451f9713c3a899e32282a) Thanks [@bgub](https://github.com/bgub)! - Warn when duplicate source update IDs include hashless entries.
8
+
9
+ - [#1379](https://github.com/generaltranslation/gt/pull/1379) [`e88fd39`](https://github.com/generaltranslation/gt/commit/e88fd399683868d5af1fe2b0ba2974fe5b17d7a7) Thanks [@bgub](https://github.com/bgub)! - Tighten public and API metadata types, and handle metadata entries without hashes in the CLI.
10
+
11
+ - Updated dependencies [[`e88fd39`](https://github.com/generaltranslation/gt/commit/e88fd399683868d5af1fe2b0ba2974fe5b17d7a7), [`95f852a`](https://github.com/generaltranslation/gt/commit/95f852ae086ac79d2c446f4d3072d8fd18688796)]:
12
+ - generaltranslation@8.2.13
13
+ - @generaltranslation/python-extractor@0.2.19
14
+
3
15
  ## 2.14.33
4
16
 
5
17
  ### Patch Changes
@@ -77,7 +77,7 @@ export class InlineCLI extends BaseCLI {
77
77
  if (id) {
78
78
  newData[id] = source;
79
79
  }
80
- else {
80
+ else if (hash) {
81
81
  newData[hash] = source;
82
82
  }
83
83
  }
@@ -29,7 +29,7 @@ export async function collectFiles(options, settings, library) {
29
29
  fileData[id] = source;
30
30
  fileMetadata[id] = metadata;
31
31
  }
32
- else {
32
+ else if (hash) {
33
33
  fileData[hash] = source;
34
34
  fileMetadata[hash] = metadata;
35
35
  }
@@ -80,7 +80,8 @@ export function extractJson(localContent, inputPath, options, targetLocale, defa
80
80
  const extractedValues = flattenJsonWithStringFilter(sourceItem, sourceObjectOptions.include);
81
81
  // Use default locale key
82
82
  const outputKey = i < defaultKeys.length ? defaultKeys[i] : targetEntries[i][0];
83
- compositeResult[sourceObjectPointer][outputKey] = extractedValues;
83
+ compositeResult[sourceObjectPointer][outputKey] =
84
+ extractedValues;
84
85
  }
85
86
  }
86
87
  else {
@@ -89,8 +90,9 @@ export function extractJson(localContent, inputPath, options, targetLocale, defa
89
90
  logger.warn(`Source object value is not an object at path: ${sourceObjectPointer}`);
90
91
  continue;
91
92
  }
93
+ const sourceObjectRecord = sourceObjectValue;
92
94
  // Find the matching item for the target locale
93
- const matchingTargetItem = findMatchingItemObject(canonicalTargetLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectValue);
95
+ const matchingTargetItem = findMatchingItemObject(canonicalTargetLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectRecord);
94
96
  if (!matchingTargetItem.sourceItem) {
95
97
  logger.warn(`No matching item found for locale ${targetLocale} at path: ${sourceObjectPointer}`);
96
98
  continue;
@@ -1,14 +1,15 @@
1
+ import type { JSONValue } from '../../types/data/json.js';
1
2
  /**
2
3
  * Flattens a JSON object according to a list of JSON paths.
3
4
  * @param json - The JSON object to flatten
4
5
  * @param jsonPaths - The list of JSON paths to flatten
5
6
  * @returns A mapping of json pointers to their values
6
7
  */
7
- export declare function flattenJson(json: any, jsonPaths: string[]): Record<string, any>;
8
+ export declare function flattenJson(json: unknown, jsonPaths: string[]): Record<string, JSONValue>;
8
9
  /**
9
10
  * Flattens a JSON object according to a list of JSON paths, only including strings
10
11
  * @param json - The JSON object to flatten
11
12
  * @param jsonPaths - The list of JSON paths to flatten
12
13
  * @returns A mapping of json pointers to their values
13
14
  */
14
- export declare function flattenJsonWithStringFilter(json: any, jsonPaths: string[]): Record<string, any>;
15
+ export declare function flattenJsonWithStringFilter(json: unknown, jsonPaths: string[]): Record<string, string>;
@@ -1,5 +1,5 @@
1
- import { JSONPath } from 'jsonpath-plus';
2
1
  import { logger } from '../../console/logger.js';
2
+ import { getJSONPathMatches } from './jsonPath.js';
3
3
  /**
4
4
  * Flattens a JSON object according to a list of JSON paths.
5
5
  * @param json - The JSON object to flatten
@@ -10,13 +10,7 @@ export function flattenJson(json, jsonPaths) {
10
10
  const extractedJson = {};
11
11
  for (const jsonPath of jsonPaths) {
12
12
  try {
13
- const results = JSONPath({
14
- json,
15
- path: jsonPath,
16
- resultType: 'all',
17
- flatten: true,
18
- wrap: true,
19
- });
13
+ const results = getJSONPathMatches(json, jsonPath);
20
14
  if (!results || results.length === 0) {
21
15
  continue;
22
16
  }
@@ -40,13 +34,7 @@ export function flattenJsonWithStringFilter(json, jsonPaths) {
40
34
  const extractedJson = {};
41
35
  for (const jsonPath of jsonPaths) {
42
36
  try {
43
- const results = JSONPath({
44
- json,
45
- path: jsonPath,
46
- resultType: 'all',
47
- flatten: true,
48
- wrap: true,
49
- });
37
+ const results = getJSONPathMatches(json, jsonPath);
50
38
  if (!results || results.length === 0) {
51
39
  continue;
52
40
  }
@@ -0,0 +1,8 @@
1
+ import type { JSONValue } from '../../types/data/json.js';
2
+ export type JSONPathMatch = {
3
+ pointer: string;
4
+ value: JSONValue;
5
+ parentProperty: string | number | null;
6
+ };
7
+ export declare function getJSONPathMatches(json: JSONValue, path: string): JSONPathMatch[] | undefined;
8
+ export declare function getJSONPathValues(json: JSONValue, path: string): JSONValue[] | undefined;
@@ -0,0 +1,19 @@
1
+ import { JSONPath } from 'jsonpath-plus';
2
+ const jsonPathOptions = (json, path) => ({
3
+ json,
4
+ path,
5
+ flatten: true,
6
+ wrap: true,
7
+ });
8
+ export function getJSONPathMatches(json, path) {
9
+ return JSONPath({
10
+ ...jsonPathOptions(json, path),
11
+ resultType: 'all',
12
+ });
13
+ }
14
+ export function getJSONPathValues(json, path) {
15
+ return JSONPath({
16
+ ...jsonPathOptions(json, path),
17
+ resultType: 'value',
18
+ });
19
+ }
@@ -0,0 +1,4 @@
1
+ import type { JSONValue } from '../../types/data/json.js';
2
+ export declare function getJSONPointerValue(json: JSONValue, pointer: string): JSONValue;
3
+ export declare function setJSONPointerValue(json: JSONValue, pointer: string, value: JSONValue): void;
4
+ export declare function deleteJSONPointerValue(json: JSONValue, pointer: string): void;
@@ -0,0 +1,20 @@
1
+ import JSONPointer from 'jsonpointer';
2
+ export function getJSONPointerValue(json, pointer) {
3
+ return JSONPointer.get(json, pointer);
4
+ }
5
+ export function setJSONPointerValue(json, pointer, value) {
6
+ JSONPointer.set(json, pointer, value);
7
+ }
8
+ export function deleteJSONPointerValue(json, pointer) {
9
+ const lastSlash = pointer.lastIndexOf('/');
10
+ if (lastSlash < 0)
11
+ return;
12
+ const parentPointer = pointer.substring(0, lastSlash) || '';
13
+ const leafKey = pointer.substring(lastSlash + 1);
14
+ const parent = parentPointer
15
+ ? getJSONPointerValue(json, parentPointer)
16
+ : json;
17
+ if (parent && typeof parent === 'object' && leafKey in parent) {
18
+ delete parent[leafKey];
19
+ }
20
+ }
@@ -1,4 +1,5 @@
1
1
  import { AdditionalOptions, SourceObjectOptions } from '../../types/index.js';
2
+ import type { JSONValue } from '../../types/data/json.js';
2
3
  export declare function mergeJson(originalContent: string, inputPath: string, options: AdditionalOptions, targets: {
3
4
  translatedContent: string;
4
5
  targetLocale: string;
@@ -10,4 +11,4 @@ export declare function mergeJson(originalContent: string, inputPath: string, op
10
11
  * @param targetLocale - The target locale
11
12
  * @param defaultLocale - The default locale
12
13
  */
13
- export declare function applyTransformations(sourceItem: any, transform: SourceObjectOptions['transform'], targetLocale: string, defaultLocale: string): void;
14
+ export declare function applyTransformations(sourceItem: JSONValue, transform: SourceObjectOptions['transform'], targetLocale: string, defaultLocale: string): void;
@@ -1,12 +1,12 @@
1
- import JSONPointer from 'jsonpointer';
2
1
  import { exitSync } from '../../console/logging.js';
3
2
  import { logger } from '../../console/logger.js';
4
3
  import { findMatchingItemArray, findMatchingItemObject, generateSourceObjectPointers, getIdentifyingLocaleProperty, getSourceObjectOptionsArray, validateJsonSchema, } from './utils.js';
5
- import { JSONPath } from 'jsonpath-plus';
6
4
  import { getLocaleProperties } from 'generaltranslation';
7
5
  import { replaceLocalePlaceholders } from '../utils.js';
8
6
  import { gt } from '../../utils/gt.js';
9
7
  import { applyStructuralTransforms, unapplyStructuralTransforms, } from './transformJson.js';
8
+ import { getJSONPathMatches, getJSONPathValues } from './jsonPath.js';
9
+ import { getJSONPointerValue, setJSONPointerValue } from './jsonPointer.js';
10
10
  export function mergeJson(originalContent, inputPath, options, targets, defaultLocale, localeOrder = []) {
11
11
  const jsonSchema = validateJsonSchema(options, inputPath);
12
12
  if (!jsonSchema) {
@@ -39,10 +39,10 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
39
39
  const translatedJson = JSON.parse(target.translatedContent);
40
40
  for (const [jsonPointer, translatedValue] of Object.entries(translatedJson)) {
41
41
  try {
42
- const value = JSONPointer.get(mergedJson, jsonPointer);
42
+ const value = getJSONPointerValue(mergedJson, jsonPointer);
43
43
  if (!value)
44
44
  continue;
45
- JSONPointer.set(mergedJson, jsonPointer, translatedValue);
45
+ setJSONPointerValue(mergedJson, jsonPointer, translatedValue);
46
46
  }
47
47
  catch {
48
48
  /* empty */
@@ -146,18 +146,18 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
146
146
  const { identifyingLocaleProperty: targetLocaleKeyProperty } = getSourceObjectOptionsArray(useCanonicalLocaleKeys
147
147
  ? gt.resolveCanonicalLocale(target.targetLocale)
148
148
  : target.targetLocale, sourceObjectPointer, sourceObjectOptions);
149
- JSONPointer.set(mutatedSourceItem, defaultLocaleKeyPointer, targetLocaleKeyProperty);
150
- for (const [translatedKeyJsonPointer, translatedValue,] of Object.entries(targetItem || {})) {
149
+ setJSONPointerValue(mutatedSourceItem, defaultLocaleKeyPointer, targetLocaleKeyProperty);
150
+ for (const [translatedKeyJsonPointer, translatedValue,] of Object.entries((targetItem || {}))) {
151
151
  const valueToSet = useCanonicalLocaleKeys &&
152
152
  defaultLocaleKeyPointer &&
153
153
  translatedKeyJsonPointer === defaultLocaleKeyPointer
154
154
  ? targetLocaleKeyProperty
155
155
  : translatedValue;
156
156
  try {
157
- const value = JSONPointer.get(mutatedSourceItem, translatedKeyJsonPointer);
157
+ const value = getJSONPointerValue(mutatedSourceItem, translatedKeyJsonPointer);
158
158
  if (!value)
159
159
  continue;
160
- JSONPointer.set(mutatedSourceItem, translatedKeyJsonPointer, valueToSet);
160
+ setJSONPointerValue(mutatedSourceItem, translatedKeyJsonPointer, valueToSet);
161
161
  }
162
162
  catch {
163
163
  /* empty */
@@ -176,7 +176,7 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
176
176
  const filteredSourceObjectValue = sourceObjectValue.filter((_, index) => !indiciesToRemove.has(index));
177
177
  // 10. Add all items to the original JSON
178
178
  filteredSourceObjectValue.push(...itemsToAdd);
179
- JSONPointer.set(mergedJson, sourceObjectPointer, sortByLocaleOrder(filteredSourceObjectValue, sourceObjectOptions, canonicalLocaleOrder, sourceObjectPointer, canonicalDefaultLocale));
179
+ setJSONPointerValue(mergedJson, sourceObjectPointer, sortByLocaleOrder(filteredSourceObjectValue, sourceObjectOptions, canonicalLocaleOrder, sourceObjectPointer, canonicalDefaultLocale));
180
180
  }
181
181
  else {
182
182
  // Validate type
@@ -184,8 +184,9 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
184
184
  logger.error(`Source object value is not an object at path: ${sourceObjectPointer}`);
185
185
  return exitSync(1);
186
186
  }
187
+ const sourceObjectRecord = sourceObjectValue;
187
188
  // Validate localeProperty
188
- const matchingDefaultLocaleItem = findMatchingItemObject(canonicalDefaultLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectValue);
189
+ const matchingDefaultLocaleItem = findMatchingItemObject(canonicalDefaultLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectRecord);
189
190
  // Validate source item exists
190
191
  if (!matchingDefaultLocaleItem.sourceItem) {
191
192
  logger.error(`Source item not found at path: ${sourceObjectPointer}. You must specify a source item where its key matches the default locale`);
@@ -209,12 +210,12 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
209
210
  // 2. Find the source item for the target locale
210
211
  const matchingTargetItem = findMatchingItemObject(useCanonicalLocaleKeys
211
212
  ? gt.resolveCanonicalLocale(target.targetLocale)
212
- : target.targetLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectValue);
213
+ : target.targetLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectRecord);
213
214
  const mutateSourceItemKey = matchingTargetItem.keyParentProperty;
214
215
  // If the source item is a string, use the translated string directly
215
216
  if (typeof defaultLocaleSourceItem === 'string') {
216
217
  if (typeof targetItems === 'string') {
217
- sourceObjectValue[mutateSourceItemKey] = targetItems;
218
+ sourceObjectRecord[mutateSourceItemKey] = targetItems;
218
219
  }
219
220
  // If no translation found, leave the locale slot unchanged
220
221
  continue;
@@ -224,7 +225,9 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
224
225
  const mutateSourceItem = structuredClone(defaultLocaleSourceItem);
225
226
  // 3. Merge the target items with the source item (if there are transformations to perform)
226
227
  const mergedItems = {
227
- ...(sourceObjectOptions.transform ? defaultLocaleSourceItem : {}),
228
+ ...(sourceObjectOptions.transform
229
+ ? defaultLocaleSourceItem
230
+ : {}),
228
231
  ...targetItems,
229
232
  };
230
233
  // 4. Validate that the mergedItems is not empty
@@ -235,10 +238,10 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
235
238
  // 5. Override the source item with the translated values
236
239
  for (const [translatedKeyJsonPointer, translatedValue,] of Object.entries(mergedItems || {})) {
237
240
  try {
238
- const value = JSONPointer.get(mutateSourceItem, translatedKeyJsonPointer);
241
+ const value = getJSONPointerValue(mutateSourceItem, translatedKeyJsonPointer);
239
242
  if (!value)
240
243
  continue;
241
- JSONPointer.set(mutateSourceItem, translatedKeyJsonPointer, translatedValue);
244
+ setJSONPointerValue(mutateSourceItem, translatedKeyJsonPointer, translatedValue);
242
245
  }
243
246
  catch {
244
247
  /* empty */
@@ -247,9 +250,9 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
247
250
  // 6. Apply additional mutations to the sourceItem
248
251
  applyTransformations(mutateSourceItem, sourceObjectOptions.transform, target.targetLocale, defaultLocale);
249
252
  // 7. Merge the source item with the original JSON
250
- sourceObjectValue[mutateSourceItemKey] = mutateSourceItem;
253
+ sourceObjectRecord[mutateSourceItemKey] = mutateSourceItem;
251
254
  }
252
- JSONPointer.set(mergedJson, sourceObjectPointer, sourceObjectValue);
255
+ setJSONPointerValue(mergedJson, sourceObjectPointer, sourceObjectValue);
253
256
  }
254
257
  }
255
258
  if (jsonSchema.structuralTransform && jsonSchema.composite) {
@@ -265,13 +268,7 @@ function sortByLocaleOrder(items, sourceObjectOptions, localeOrder, sourceObject
265
268
  const itemsWithLocale = items.map((item) => {
266
269
  let localeValue;
267
270
  try {
268
- const values = JSONPath({
269
- json: item,
270
- path: sourceObjectOptions.key,
271
- resultType: 'value',
272
- flatten: true,
273
- wrap: true,
274
- });
271
+ const values = getJSONPathValues(item, sourceObjectOptions.key);
275
272
  const value = values?.[0];
276
273
  if (typeof value === 'string') {
277
274
  localeValue = value;
@@ -350,13 +347,7 @@ export function applyTransformations(sourceItem, transform, targetLocale, defaul
350
347
  typeof transformOptions.replace !== 'string') {
351
348
  continue;
352
349
  }
353
- const results = JSONPath({
354
- json: sourceItem,
355
- path: transformPath,
356
- resultType: 'all',
357
- flatten: true,
358
- wrap: true,
359
- });
350
+ const results = getJSONPathMatches(sourceItem, transformPath);
360
351
  if (!results || results.length === 0) {
361
352
  continue;
362
353
  }
@@ -379,7 +370,7 @@ export function applyTransformations(sourceItem, transform, targetLocale, defaul
379
370
  result.value = replaceString;
380
371
  }
381
372
  // Update the actual sourceItem using JSONPointer
382
- JSONPointer.set(sourceItem, result.pointer, result.value);
373
+ setJSONPointerValue(sourceItem, result.pointer, result.value);
383
374
  });
384
375
  }
385
376
  }
@@ -1,9 +1,9 @@
1
1
  import { flattenJson, flattenJsonWithStringFilter } from './flattenJson.js';
2
- import { JSONPath } from 'jsonpath-plus';
3
2
  import { exitSync } from '../../console/logging.js';
4
3
  import { logger } from '../../console/logger.js';
5
4
  import { findMatchingItemArray, findMatchingItemObject, generateSourceObjectPointers, validateJsonSchema, } from './utils.js';
6
5
  import { applyStructuralTransforms } from './transformJson.js';
6
+ import { getJSONPathMatches } from './jsonPath.js';
7
7
  // Parse a JSON file according to a JSON schema
8
8
  export function parseJson(content, filePath, options, defaultLocale, filterStrings = true) {
9
9
  const jsonSchema = validateJsonSchema(options, filePath);
@@ -63,13 +63,7 @@ export function parseJson(content, filePath, options, defaultLocale, filterStrin
63
63
  const matchingItemsToTranslate = [];
64
64
  for (const include of sourceObjectOptions.include) {
65
65
  try {
66
- const matchingItems = JSONPath({
67
- json: sourceItem,
68
- path: include,
69
- resultType: 'all',
70
- flatten: true,
71
- wrap: true,
72
- });
66
+ const matchingItems = getJSONPathMatches(sourceItem, include);
73
67
  if (matchingItems) {
74
68
  matchingItemsToTranslate.push(...matchingItems);
75
69
  }
@@ -81,10 +75,7 @@ export function parseJson(content, filePath, options, defaultLocale, filterStrin
81
75
  // Filter out the key pointer
82
76
  sourceItemsToTranslate[arrayPointer] = Object.fromEntries(matchingItemsToTranslate
83
77
  .filter((item) => item.pointer !== keyPointer)
84
- .map((item) => [
85
- item.pointer,
86
- item.value,
87
- ]));
78
+ .map((item) => [item.pointer, item.value]));
88
79
  }
89
80
  // Add the items to translate to the result
90
81
  sourceObjectsToTranslate[sourceObjectPointer] = sourceItemsToTranslate;
@@ -96,8 +87,9 @@ export function parseJson(content, filePath, options, defaultLocale, filterStrin
96
87
  logger.error(`Source object value is not an object at path: ${sourceObjectPointer}`);
97
88
  return exitSync(1);
98
89
  }
90
+ const sourceObjectRecord = sourceObjectValue;
99
91
  // Validate localeProperty
100
- const matchingItem = findMatchingItemObject(defaultLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectValue);
92
+ const matchingItem = findMatchingItemObject(defaultLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectRecord);
101
93
  // Validate source item exists
102
94
  if (!matchingItem.sourceItem) {
103
95
  logger.error(`Source item not found at path: ${sourceObjectPointer}. You must specify a source item where its key matches the default locale`);
@@ -1,13 +1,14 @@
1
1
  import { StructuralTransform, SourceObjectOptions } from '../../types/index.js';
2
+ import type { JSONValue } from '../../types/data/json.js';
2
3
  /**
3
4
  * Apply structural transforms: copy values from sourcePointer to destinationPointer
4
5
  * for each entry resolved by the composite config's parent paths.
5
6
  * Mutates json in-place.
6
7
  */
7
- export declare function applyStructuralTransforms(json: any, transforms: StructuralTransform[], compositeConfig: Record<string, SourceObjectOptions>): any;
8
+ export declare function applyStructuralTransforms(json: JSONValue, transforms: StructuralTransform[], compositeConfig: Record<string, SourceObjectOptions>): JSONValue;
8
9
  /**
9
10
  * Unapply structural transforms: delete the value at destinationPointer
10
11
  * for each entry resolved by the composite config's parent paths.
11
12
  * Leaves sourcePointer untouched. Mutates json in-place.
12
13
  */
13
- export declare function unapplyStructuralTransforms(json: any, transforms: StructuralTransform[], compositeConfig: Record<string, SourceObjectOptions>): any;
14
+ export declare function unapplyStructuralTransforms(json: JSONValue, transforms: StructuralTransform[], compositeConfig: Record<string, SourceObjectOptions>): JSONValue;
@@ -1,5 +1,5 @@
1
- import JSONPointer from 'jsonpointer';
2
- import { JSONPath } from 'jsonpath-plus';
1
+ import { getJSONPathMatches } from './jsonPath.js';
2
+ import { deleteJSONPointerValue, getJSONPointerValue, setJSONPointerValue, } from './jsonPointer.js';
3
3
  /**
4
4
  * Derive entry parent paths from composite sourceObjectPaths by trimming the last segment.
5
5
  * e.g., "$.*.translations" → "$.*"
@@ -22,13 +22,7 @@ function deriveEntryPaths(compositeConfig) {
22
22
  export function applyStructuralTransforms(json, transforms, compositeConfig) {
23
23
  const entryPaths = deriveEntryPaths(compositeConfig);
24
24
  for (const entryPath of entryPaths) {
25
- const entries = JSONPath({
26
- json,
27
- path: entryPath,
28
- resultType: 'all',
29
- flatten: true,
30
- wrap: true,
31
- });
25
+ const entries = getJSONPathMatches(json, entryPath);
32
26
  if (!entries)
33
27
  continue;
34
28
  for (const entry of entries) {
@@ -36,9 +30,9 @@ export function applyStructuralTransforms(json, transforms, compositeConfig) {
36
30
  if (typeof entryObj !== 'object' || entryObj === null)
37
31
  continue;
38
32
  for (const transform of transforms) {
39
- const sourceValue = JSONPointer.get(entryObj, transform.sourcePointer);
33
+ const sourceValue = getJSONPointerValue(entryObj, transform.sourcePointer);
40
34
  if (sourceValue !== undefined) {
41
- JSONPointer.set(entryObj, transform.destinationPointer, sourceValue);
35
+ setJSONPointerValue(entryObj, transform.destinationPointer, sourceValue);
42
36
  }
43
37
  }
44
38
  }
@@ -53,13 +47,7 @@ export function applyStructuralTransforms(json, transforms, compositeConfig) {
53
47
  export function unapplyStructuralTransforms(json, transforms, compositeConfig) {
54
48
  const entryPaths = deriveEntryPaths(compositeConfig);
55
49
  for (const entryPath of entryPaths) {
56
- const entries = JSONPath({
57
- json,
58
- path: entryPath,
59
- resultType: 'all',
60
- flatten: true,
61
- wrap: true,
62
- });
50
+ const entries = getJSONPathMatches(json, entryPath);
63
51
  if (!entries)
64
52
  continue;
65
53
  for (const entry of entries) {
@@ -67,20 +55,8 @@ export function unapplyStructuralTransforms(json, transforms, compositeConfig) {
67
55
  if (typeof entryObj !== 'object' || entryObj === null)
68
56
  continue;
69
57
  for (const transform of transforms) {
70
- // Navigate to parent of destinationPointer and delete the leaf key
71
- const pointer = transform.destinationPointer;
72
- const lastSlash = pointer.lastIndexOf('/');
73
- if (lastSlash < 0)
74
- continue;
75
- const parentPointer = pointer.substring(0, lastSlash) || '';
76
- const leafKey = pointer.substring(lastSlash + 1);
77
58
  try {
78
- const parent = parentPointer
79
- ? JSONPointer.get(entryObj, parentPointer)
80
- : entryObj;
81
- if (parent && typeof parent === 'object' && leafKey in parent) {
82
- delete parent[leafKey];
83
- }
59
+ deleteJSONPointerValue(entryObj, transform.destinationPointer);
84
60
  }
85
61
  catch {
86
62
  /* entry may not have the destination path */
@@ -1,12 +1,18 @@
1
1
  import { AdditionalOptions, JsonSchema, SourceObjectOptions } from '../../types/index.js';
2
- export declare function findMatchingItemArray(locale: string, sourceObjectOptions: SourceObjectOptions, sourceObjectPointer: string, sourceObjectValue: any): Record<string, {
3
- sourceItem: any;
4
- keyParentProperty: string;
2
+ import type { JSONObject, JSONValue } from '../../types/data/json.js';
3
+ type MatchingArrayItem = {
4
+ sourceItem: JSONValue;
5
+ keyParentProperty: string | number;
5
6
  keyPointer: string;
6
7
  index: number;
8
+ };
9
+ type SourceObjectPointerMap = Record<string, {
10
+ sourceObjectValue: JSONValue;
11
+ sourceObjectOptions: SourceObjectOptions;
7
12
  }>;
8
- export declare function findMatchingItemObject(locale: string, sourceObjectPointer: string, sourceObjectOptions: SourceObjectOptions, sourceObjectValue: any): {
9
- sourceItem: any | undefined;
13
+ export declare function findMatchingItemArray(locale: string, sourceObjectOptions: SourceObjectOptions, sourceObjectPointer: string, sourceObjectValue: JSONValue[]): Record<string, MatchingArrayItem>;
14
+ export declare function findMatchingItemObject(locale: string, sourceObjectPointer: string, sourceObjectOptions: SourceObjectOptions, sourceObjectValue: JSONObject): {
15
+ sourceItem: JSONValue | undefined;
10
16
  keyParentProperty: string;
11
17
  };
12
18
  /**
@@ -40,10 +46,7 @@ export declare function getSourceObjectOptionsObject(defaultLocale: string, sour
40
46
  */
41
47
  export declare function generateSourceObjectPointers(jsonSchema: {
42
48
  [sourceObjectPath: string]: SourceObjectOptions;
43
- }, originalJson: any): Record<string, {
44
- sourceObjectValue: any;
45
- sourceObjectOptions: SourceObjectOptions;
46
- }>;
49
+ }, originalJson: JSONValue): SourceObjectPointerMap;
47
50
  /**
48
51
  * Validate the json schema for composite or include schemas
49
52
  * @param options - Additional options containing jsonSchema config
@@ -56,4 +59,5 @@ export declare function validateJsonSchema(options: AdditionalOptions, filePath:
56
59
  * Detect unsupported fields (e.g. $ref) in Mintlify docs.json files.
57
60
  * Logs a warning listing the fields found.
58
61
  */
59
- export declare function detectMintlifyUnsupportedFields(json: any, filePath: string): void;
62
+ export declare function detectMintlifyUnsupportedFields(json: JSONValue, filePath: string): void;
63
+ export {};
@@ -1,11 +1,11 @@
1
1
  import { getLocaleProperties } from 'generaltranslation';
2
2
  import { exitSync } from '../../console/logging.js';
3
3
  import { logger } from '../../console/logger.js';
4
- import { JSONPath } from 'jsonpath-plus';
5
4
  import { flattenJson } from './flattenJson.js';
6
5
  import chalk from 'chalk';
7
6
  import path from 'node:path';
8
7
  import micromatch from 'micromatch';
8
+ import { getJSONPathMatches } from './jsonPath.js';
9
9
  const { isMatch } = micromatch;
10
10
  // Find the matching source item in an array
11
11
  // where the key matches the identifying locale property
@@ -16,13 +16,7 @@ export function findMatchingItemArray(locale, sourceObjectOptions, sourceObjectP
16
16
  const matchingItems = {};
17
17
  for (const [index, item] of sourceObjectValue.entries()) {
18
18
  // Get the key candidates
19
- const keyCandidates = JSONPath({
20
- json: item,
21
- path: localeKeyJsonPath,
22
- resultType: 'all',
23
- flatten: true,
24
- wrap: true,
25
- });
19
+ const keyCandidates = getJSONPathMatches(item, localeKeyJsonPath);
26
20
  if (!keyCandidates) {
27
21
  logger.error(`Source item at path: ${sourceObjectPointer} does not have a key value at path: ${localeKeyJsonPath}`);
28
22
  return exitSync(1);
@@ -40,10 +34,15 @@ export function findMatchingItemArray(locale, sourceObjectOptions, sourceObjectP
40
34
  // Validate the key is the identifying locale property
41
35
  continue;
42
36
  }
37
+ const keyParentProperty = keyCandidates[0].parentProperty;
38
+ if (keyParentProperty === null) {
39
+ logger.error(`Source item at path: ${sourceObjectPointer} has a root-level key match with path: ${localeKeyJsonPath}`);
40
+ return exitSync(1);
41
+ }
43
42
  // Map the index to the source item
44
43
  matchingItems[`/${index}`] = {
45
44
  sourceItem: item,
46
- keyParentProperty: keyCandidates[0].parentProperty,
45
+ keyParentProperty,
47
46
  keyPointer: keyCandidates[0].pointer,
48
47
  index,
49
48
  };
@@ -174,15 +173,16 @@ function findMintlifyUnsupportedFields(value, fieldNames, pointer = '') {
174
173
  return results;
175
174
  }
176
175
  // Check if this object contains an unsupported field
176
+ const objectValue = value;
177
177
  for (const field of fieldNames) {
178
- if (typeof value[field] === 'string') {
179
- return [{ pointer, field, fieldValue: value[field] }];
178
+ if (typeof objectValue[field] === 'string') {
179
+ return [{ pointer, field, fieldValue: objectValue[field] }];
180
180
  }
181
181
  }
182
182
  // Recurse into child properties
183
183
  const results = [];
184
- for (const key of Object.keys(value)) {
185
- results.push(...findMintlifyUnsupportedFields(value[key], fieldNames, `${pointer}/${key}`));
184
+ for (const key of Object.keys(objectValue)) {
185
+ results.push(...findMintlifyUnsupportedFields(objectValue[key], fieldNames, `${pointer}/${key}`));
186
186
  }
187
187
  return results;
188
188
  }
@@ -1,7 +1,9 @@
1
- import { Settings } from '../types/index.js';
1
+ import type { Settings } from '../types/index.js';
2
+ type CopyFileSettings = Pick<Settings, 'defaultLocale' | 'locales' | 'options'>;
2
3
  /**
3
4
  * Copy a file to target locale without translation
4
5
  *
5
6
  * This is a naive approach, does not allow for wild cards
6
7
  */
7
- export default function copyFile(settings: Settings): Promise<void>;
8
+ export default function copyFile(settings: CopyFileSettings): Promise<void>;
9
+ export {};
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "2.14.33";
1
+ export declare const PACKAGE_VERSION = "2.14.34";
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const PACKAGE_VERSION = '2.14.33';
2
+ export const PACKAGE_VERSION = '2.14.34';
@@ -59,23 +59,42 @@ export async function createUpdates(options, src, sourceDictionary, pkg, validat
59
59
  updates = [...updates, ...newUpdates];
60
60
  // Metadata addition and validation
61
61
  const idHashMap = new Map();
62
+ const hashlessIds = new Set();
63
+ const warnedHashlessDuplicateIds = new Set();
62
64
  const duplicateIds = new Set();
65
+ const warnHashlessDuplicateId = (id) => {
66
+ if (warnedHashlessDuplicateIds.has(id))
67
+ return;
68
+ warnings.push(`Duplicate id ${chalk.blue(id)} includes at least one entry without a hash. Hashless duplicate IDs cannot be compared, and later entries may overwrite earlier entries.`);
69
+ warnedHashlessDuplicateIds.add(id);
70
+ };
63
71
  updates = updates.map((update) => {
64
- if (!update.metadata.id)
72
+ const { id, hash } = update.metadata;
73
+ if (!id)
65
74
  return update;
66
- const existingHash = idHashMap.get(update.metadata.id);
67
- if (existingHash) {
68
- if (existingHash !== update.metadata.hash) {
69
- errors.push(`Hashes don't match on two components with the same id: ${chalk.blue(update.metadata.id)}. Check your ${chalk.green('<T>')} tags and dictionary entries and make sure you're not accidentally duplicating IDs.`);
70
- duplicateIds.add(update.metadata.id);
75
+ if (!hash) {
76
+ if (hashlessIds.has(id) || idHashMap.has(id)) {
77
+ warnHashlessDuplicateId(id);
78
+ }
79
+ hashlessIds.add(id);
80
+ return update;
81
+ }
82
+ if (hashlessIds.has(id)) {
83
+ warnHashlessDuplicateId(id);
84
+ }
85
+ const existingHash = idHashMap.get(id);
86
+ if (existingHash !== undefined) {
87
+ if (existingHash !== hash) {
88
+ errors.push(`Hashes don't match on two components with the same id: ${chalk.blue(id)}. Check your ${chalk.green('<T>')} tags and dictionary entries and make sure you're not accidentally duplicating IDs.`);
89
+ duplicateIds.add(id);
71
90
  }
72
91
  }
73
92
  else {
74
- idHashMap.set(update.metadata.id, update.metadata.hash);
93
+ idHashMap.set(id, hash);
75
94
  }
76
95
  return update;
77
96
  });
78
97
  // Filter out updates with duplicate IDs
79
- updates = updates.filter((update) => !duplicateIds.has(update.metadata.id));
98
+ updates = updates.filter((update) => !update.metadata.id || !duplicateIds.has(update.metadata.id));
80
99
  return { updates, errors, warnings };
81
100
  }
@@ -1,6 +1,5 @@
1
- type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
1
+ export type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
2
2
  export type JSONObject = {
3
3
  [key: string]: JSONValue;
4
4
  };
5
5
  export type JSONArray = JSONValue[];
6
- export {};
@@ -206,6 +206,10 @@ export type Settings = {
206
206
  branchOptions: BranchOptions;
207
207
  sharedStaticAssets?: SharedStaticAssetsConfig;
208
208
  };
209
+ export type StaticLocalizationFiles = Pick<Settings['files'], 'placeholderPaths' | 'resolvedPaths'> & Partial<Pick<Settings['files'], 'transformPaths' | 'transformFormats'>>;
210
+ export type StaticLocalizationSettings = Pick<Settings, 'defaultLocale' | 'locales' | 'options'> & {
211
+ files?: StaticLocalizationFiles | null;
212
+ };
209
213
  export type BranchOptions = {
210
214
  currentBranch?: string;
211
215
  autoDetectBranches?: boolean;
@@ -1,3 +1,7 @@
1
+ import type { AdditionalOptions } from '../types/index.js';
2
+ type AnchorIdSettings = {
3
+ options?: Pick<AdditionalOptions, 'experimentalAddHeaderAnchorIds'>;
4
+ };
1
5
  /**
2
6
  * Represents a heading with its position and metadata
3
7
  */
@@ -14,7 +18,7 @@ export declare function extractHeadingInfo(mdxContent: string): HeadingInfo[];
14
18
  /**
15
19
  * Applies anchor IDs to translated content based on source heading mapping
16
20
  */
17
- export declare function addExplicitAnchorIds(translatedContent: string, sourceHeadingMap: HeadingInfo[], settings?: any, sourcePath?: string, translatedPath?: string, fileTypeHint?: 'md' | 'mdx'): {
21
+ export declare function addExplicitAnchorIds(translatedContent: string, sourceHeadingMap: HeadingInfo[], settings?: AnchorIdSettings, sourcePath?: string, translatedPath?: string, fileTypeHint?: 'md' | 'mdx'): {
18
22
  content: string;
19
23
  hasChanges: boolean;
20
24
  addedIds: Array<{
@@ -22,3 +26,4 @@ export declare function addExplicitAnchorIds(translatedContent: string, sourceHe
22
26
  id: string;
23
27
  }>;
24
28
  };
29
+ export {};
@@ -1,8 +1,9 @@
1
- import { Settings } from '../types/index.js';
1
+ import type { StaticLocalizationSettings } from '../types/index.js';
2
2
  type RewriteResult = {
3
3
  content: string;
4
4
  hasChanges: boolean;
5
5
  };
6
+ export type RelativeAssetSettings = StaticLocalizationSettings;
6
7
  export declare function localizeRelativeAssetsForContent(content: string, sourcePath: string, targetPath: string, cwd: string): RewriteResult;
7
- export default function localizeRelativeAssets(settings: Settings, targetLocales?: string[], includeFiles?: Set<string>): Promise<void>;
8
+ export default function localizeRelativeAssets(settings: RelativeAssetSettings, targetLocales?: string[], includeFiles?: Set<string>): Promise<void>;
8
9
  export {};
@@ -81,24 +81,25 @@ export function localizeRelativeAssetsForContent(content, sourcePath, targetPath
81
81
  return newPath + suffix;
82
82
  };
83
83
  visit(ast, (node) => {
84
- if (node.type === 'image' && typeof node.url === 'string') {
85
- const newUrl = maybeRewrite(node.url);
84
+ const assetNode = node;
85
+ if (assetNode.type === 'image' && typeof assetNode.url === 'string') {
86
+ const newUrl = maybeRewrite(assetNode.url);
86
87
  if (newUrl)
87
- node.url = newUrl;
88
+ assetNode.url = newUrl;
88
89
  return;
89
90
  }
90
- if ((node.type === 'mdxJsxFlowElement' ||
91
- node.type === 'mdxJsxTextElement') &&
92
- node.name === 'img' &&
93
- Array.isArray(node.attributes)) {
94
- for (const attr of node.attributes) {
95
- if (attr &&
96
- attr.type === 'mdxJsxAttribute' &&
97
- attr.name === 'src' &&
98
- typeof attr.value === 'string') {
99
- const newUrl = maybeRewrite(attr.value);
91
+ if ((assetNode.type === 'mdxJsxFlowElement' ||
92
+ assetNode.type === 'mdxJsxTextElement') &&
93
+ assetNode.name === 'img' &&
94
+ Array.isArray(assetNode.attributes)) {
95
+ for (const attr of assetNode.attributes) {
96
+ const attribute = attr;
97
+ if (attribute.type === 'mdxJsxAttribute' &&
98
+ attribute.name === 'src' &&
99
+ typeof attribute.value === 'string') {
100
+ const newUrl = maybeRewrite(attribute.value);
100
101
  if (newUrl)
101
- attr.value = newUrl;
102
+ attribute.value = newUrl;
102
103
  }
103
104
  }
104
105
  }
@@ -136,7 +137,7 @@ export default async function localizeRelativeAssets(settings, targetLocales, in
136
137
  }
137
138
  const { resolvedPaths: sourceFiles } = settings.files;
138
139
  const locales = targetLocales || settings.locales;
139
- const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.files.transformFormats, settings.locales, settings.defaultLocale);
140
+ const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths ?? {}, settings.files.transformFormats ?? {}, settings.locales, settings.defaultLocale);
140
141
  const cwd = process.cwd();
141
142
  const processPromises = Object.entries(fileMapping)
142
143
  .filter(([locale]) => locales.includes(locale))
@@ -1,4 +1,5 @@
1
- import { Settings } from '../types/index.js';
1
+ import type { StaticLocalizationSettings } from '../types/index.js';
2
+ export type StaticImportSettings = StaticLocalizationSettings;
2
3
  /**
3
4
  * Localizes static imports in content files.
4
5
  * Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
@@ -12,4 +13,4 @@ import { Settings } from '../types/index.js';
12
13
  * - Support more file types
13
14
  * - Support more complex paths
14
15
  */
15
- export default function localizeStaticImports(settings: Settings, includeFiles?: Set<string>): Promise<void>;
16
+ export default function localizeStaticImports(settings: StaticImportSettings, includeFiles?: Set<string>): Promise<void>;
@@ -28,7 +28,7 @@ export default async function localizeStaticImports(settings, includeFiles) {
28
28
  return;
29
29
  }
30
30
  const { resolvedPaths: sourceFiles } = settings.files;
31
- const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.files.transformFormats, settings.locales, settings.defaultLocale);
31
+ const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths ?? {}, settings.files.transformFormats ?? {}, settings.locales, settings.defaultLocale);
32
32
  // Process all file types at once with a single call
33
33
  const processPromises = [];
34
34
  // First, process default locale files (from source files)
@@ -1,4 +1,5 @@
1
- import { Settings } from '../types/index.js';
1
+ import type { StaticLocalizationSettings } from '../types/index.js';
2
+ export type StaticUrlSettings = StaticLocalizationSettings;
2
3
  /**
3
4
  * Localizes static urls in content files.
4
5
  * Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
@@ -12,7 +13,7 @@ import { Settings } from '../types/index.js';
12
13
  * - Support more file types
13
14
  * - Support more complex paths
14
15
  */
15
- export default function localizeStaticUrls(settings: Settings, targetLocales?: string[], includeFiles?: Set<string>): Promise<void>;
16
+ export default function localizeStaticUrls(settings: StaticUrlSettings, targetLocales?: string[], includeFiles?: Set<string>): Promise<void>;
16
17
  /**
17
18
  * Main URL transformation function that delegates to specific scenarios
18
19
  */
@@ -31,7 +31,7 @@ export default async function localizeStaticUrls(settings, targetLocales, includ
31
31
  const { resolvedPaths: sourceFiles } = settings.files;
32
32
  // Use filtered locales if provided, otherwise use all locales
33
33
  const locales = targetLocales || settings.locales;
34
- const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.files.transformFormats, settings.locales, // Always use all locales for mapping, filter later
34
+ const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths ?? {}, settings.files.transformFormats ?? {}, settings.locales, // Always use all locales for mapping, filter later
35
35
  settings.defaultLocale);
36
36
  // Process all file types at once with a single call
37
37
  const processPromises = [];
@@ -38,11 +38,9 @@ async function moveFile(src, dest) {
38
38
  await fs.promises.rename(src, dest);
39
39
  }
40
40
  catch (err) {
41
+ const code = err?.code;
41
42
  // Fallback to copy+unlink for cross-device or existing files
42
- if (err &&
43
- (err.code === 'EXDEV' ||
44
- err.code === 'EEXIST' ||
45
- err.code === 'ENOTEMPTY')) {
43
+ if (code === 'EXDEV' || code === 'EEXIST' || code === 'ENOTEMPTY') {
46
44
  const data = await fs.promises.readFile(src);
47
45
  await ensureDir(path.dirname(dest));
48
46
  await fs.promises.writeFile(dest, data);
@@ -53,7 +51,7 @@ async function moveFile(src, dest) {
53
51
  // Ignore cleanup errors for source files that were already moved.
54
52
  }
55
53
  }
56
- else if (err && err.code === 'ENOENT') {
54
+ else if (code === 'ENOENT') {
57
55
  // already moved or missing; ignore
58
56
  return;
59
57
  }
@@ -148,32 +146,33 @@ function rewriteMdxContent(content, filePath, pathMap) {
148
146
  return null;
149
147
  };
150
148
  visit(ast, (node) => {
149
+ const assetNode = node;
151
150
  // Markdown image: ![alt](url)
152
- if (node.type === 'image' && typeof node.url === 'string') {
153
- const newUrl = maybeRewrite(node.url);
151
+ if (assetNode.type === 'image' && typeof assetNode.url === 'string') {
152
+ const newUrl = maybeRewrite(assetNode.url);
154
153
  if (newUrl)
155
- node.url = newUrl;
154
+ assetNode.url = newUrl;
156
155
  return;
157
156
  }
158
157
  // Markdown link: [text](url) — useful for PDFs and other downloadable assets
159
- if (node.type === 'link' && typeof node.url === 'string') {
160
- const newUrl = maybeRewrite(node.url);
158
+ if (assetNode.type === 'link' && typeof assetNode.url === 'string') {
159
+ const newUrl = maybeRewrite(assetNode.url);
161
160
  if (newUrl)
162
- node.url = newUrl;
161
+ assetNode.url = newUrl;
163
162
  return;
164
163
  }
165
164
  // MDX <img src="..." />
166
- if ((node.type === 'mdxJsxFlowElement' ||
167
- node.type === 'mdxJsxTextElement') &&
168
- Array.isArray(node.attributes)) {
169
- for (const attr of node.attributes) {
170
- if (attr &&
171
- attr.type === 'mdxJsxAttribute' &&
172
- (attr.name === 'src' || attr.name === 'href') &&
173
- typeof attr.value === 'string') {
174
- const newUrl = maybeRewrite(attr.value);
165
+ if ((assetNode.type === 'mdxJsxFlowElement' ||
166
+ assetNode.type === 'mdxJsxTextElement') &&
167
+ Array.isArray(assetNode.attributes)) {
168
+ for (const attr of assetNode.attributes) {
169
+ const attribute = attr;
170
+ if (attribute.type === 'mdxJsxAttribute' &&
171
+ (attribute.name === 'src' || attribute.name === 'href') &&
172
+ typeof attribute.value === 'string') {
173
+ const newUrl = maybeRewrite(attribute.value);
175
174
  if (newUrl)
176
- attr.value = newUrl;
175
+ attribute.value = newUrl;
177
176
  }
178
177
  }
179
178
  }
@@ -1,13 +1,16 @@
1
1
  import { WorkflowStep } from './WorkflowStep.js';
2
- import { GT } from 'generaltranslation';
3
- import { Settings } from '../../types/index.js';
2
+ import type { GT } from 'generaltranslation';
3
+ import type { Settings } from '../../types/index.js';
4
4
  import { BranchData } from '../../types/branch.js';
5
+ type BranchStepClient = Pick<GT, 'queryBranchData' | 'createBranch'>;
6
+ type BranchStepSettings = Pick<Settings, 'branchOptions'>;
5
7
  export declare class BranchStep extends WorkflowStep<null, BranchData | null> {
6
8
  private spinner;
7
9
  private branchData;
8
10
  private settings;
9
11
  private gt;
10
- constructor(gt: GT, settings: Settings);
12
+ constructor(gt: BranchStepClient, settings: BranchStepSettings);
11
13
  run(): Promise<BranchData | null>;
12
14
  wait(): Promise<void>;
13
15
  }
16
+ export {};
@@ -1,9 +1,11 @@
1
1
  import type { FileToUpload } from 'generaltranslation/types';
2
2
  import { WorkflowStep } from './WorkflowStep.js';
3
- import { GT } from 'generaltranslation';
4
- import { Settings } from '../../types/index.js';
3
+ import type { GT } from 'generaltranslation';
4
+ import type { Settings } from '../../types/index.js';
5
5
  import { BranchData } from '../../types/branch.js';
6
6
  import type { FileReference } from 'generaltranslation/types';
7
+ type UploadSourcesClient = Pick<GT, 'queryFileData' | 'getOrphanedFiles' | 'processFileMoves' | 'uploadSourceFiles'>;
8
+ type UploadSourcesSettings = Pick<Settings, 'defaultLocale' | 'modelProvider'>;
7
9
  export declare class UploadSourcesStep extends WorkflowStep<{
8
10
  files: FileToUpload[];
9
11
  branchData: BranchData;
@@ -12,7 +14,7 @@ export declare class UploadSourcesStep extends WorkflowStep<{
12
14
  private settings;
13
15
  private spinner;
14
16
  private result;
15
- constructor(gt: GT, settings: Settings);
17
+ constructor(gt: UploadSourcesClient, settings: UploadSourcesSettings);
16
18
  /**
17
19
  * Detects file moves by comparing local files against orphaned files.
18
20
  * A move is detected when a local file has the same versionId (content hash)
@@ -25,3 +27,4 @@ export declare class UploadSourcesStep extends WorkflowStep<{
25
27
  }): Promise<FileReference[]>;
26
28
  wait(): Promise<void>;
27
29
  }
30
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gt",
3
- "version": "2.14.33",
3
+ "version": "2.14.34",
4
4
  "main": "dist/index.js",
5
5
  "bin": "bin/main.js",
6
6
  "files": [
@@ -111,8 +111,8 @@
111
111
  "unified": "^11.0.5",
112
112
  "unist-util-visit": "^5.0.0",
113
113
  "yaml": "^2.8.0",
114
- "@generaltranslation/python-extractor": "0.2.18",
115
- "generaltranslation": "8.2.12",
114
+ "@generaltranslation/python-extractor": "0.2.19",
115
+ "generaltranslation": "8.2.13",
116
116
  "gt-remark": "1.0.7"
117
117
  },
118
118
  "devDependencies": {
@@ -123,7 +123,7 @@
123
123
  "@types/mdast": "^4.0.0",
124
124
  "@types/micromatch": "^4.0.9",
125
125
  "@types/mock-require": "^2.0.3",
126
- "@types/node": "^22.5.1",
126
+ "@types/node": "^22.13.5",
127
127
  "@types/react": "^18.3.4",
128
128
  "@types/resolve": "^1.20.2",
129
129
  "eslint": "^9.20.0",
@@ -133,14 +133,15 @@
133
133
  "prettier": "^3.4.2",
134
134
  "ts-node": "^10.9.2",
135
135
  "tslib": "^2.8.1",
136
- "typescript": "^5.5.4",
137
- "vitest": "^2.0.0"
136
+ "typescript": "^5.9.2",
137
+ "vitest": "^3.2.4"
138
138
  },
139
139
  "scripts": {
140
- "build": "node scripts/generate-version.js && tsc && rm -rf dist/setup/instructions && cp -r src/setup/instructions dist/setup/instructions",
140
+ "generate-version": "node scripts/generate-version.js",
141
+ "build": "pnpm run generate-version && tsc && rm -rf dist/setup/instructions && cp -r src/setup/instructions dist/setup/instructions",
141
142
  "build:clean": "sh ../../scripts/clean.sh && pnpm bin:restore && rm -rf binaries && pnpm run build",
142
143
  "build:release": "pnpm run build:clean",
143
- "build:bin": "node scripts/generate-version.js && tsc && rm -rf dist/setup/instructions && cp -r src/setup/instructions dist/setup/instructions && sh scripts/build-exe.sh all",
144
+ "build:bin": "pnpm run generate-version && tsc && rm -rf dist/setup/instructions && cp -r src/setup/instructions dist/setup/instructions && sh scripts/build-exe.sh all",
144
145
  "build:bin:clean": "sh ../../scripts/clean.sh && rm -rf binaries && pnpm run build:bin",
145
146
  "build:bin:release": "pnpm run build:bin:clean && pnpm run build:bin",
146
147
  "build:bin:darwin-x64": "sh scripts/build-exe.sh darwin-x64",
@@ -148,8 +149,8 @@
148
149
  "build:bin:linux-x64": "sh scripts/build-exe.sh linux-x64",
149
150
  "build:bin:linux-arm64": "sh scripts/build-exe.sh linux-arm64",
150
151
  "build:bin:windows-x64": "sh scripts/build-exe.sh windows-x64",
151
- "test": "vitest run --config=./vitest.config.ts",
152
- "test:watch": "vitest --config=./vitest.config.ts",
152
+ "test": "pnpm run generate-version && vitest run --config=./vitest.config.ts",
153
+ "test:watch": "pnpm run generate-version && vitest --config=./vitest.config.ts",
153
154
  "release": "pnpm run release:normal && pnpm run release:bin",
154
155
  "release:normal": "pnpm run build:clean && pnpm publish",
155
156
  "release:bin": "pnpm run bin:prep && pnpm run build:bin:clean && pnpm publish --tag bin --no-git-checks && pnpm run bin:restore && pnpm run build:clean",
@@ -158,6 +159,6 @@
158
159
  "release:latest": "pnpm run build:clean && pnpm publish --tag latest",
159
160
  "bin:restore": "node scripts/restore-package-json.js",
160
161
  "bin:prep": "node scripts/prepare-binary-release.js",
161
- "typecheck": "tsc --noEmit"
162
+ "typecheck": "pnpm run generate-version && tsc --noEmit"
162
163
  }
163
164
  }