gt 2.14.18 → 2.14.19
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 +10 -0
- package/dist/config/optionPresets.js +32 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/types/index.d.ts +3 -1
- package/dist/utils/resolveMintlifyRefs.d.ts +1 -3
- package/dist/utils/resolveMintlifyRefs.js +3 -6
- package/dist/utils/splitMintlifyLanguageRefs.d.ts +7 -7
- package/dist/utils/splitMintlifyLanguageRefs.js +179 -82
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.14.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1244](https://github.com/generaltranslation/gt/pull/1244) [`c4c8b9c`](https://github.com/generaltranslation/gt/commit/c4c8b9c0429ce10d98ebdfaabc1213bd85a572bf) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Updating Mintlify $ref handling
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`8b75420`](https://github.com/generaltranslation/gt/commit/8b7542091233fb2c87284a365cc9ab8ce70371d3)]:
|
|
10
|
+
- generaltranslation@8.2.6
|
|
11
|
+
- @generaltranslation/python-extractor@0.2.11
|
|
12
|
+
|
|
3
13
|
## 2.14.18
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -4,11 +4,13 @@ export function generatePreset(preset, type) {
|
|
|
4
4
|
case 'mintlify':
|
|
5
5
|
// https://mintlify.com/docs/navigation
|
|
6
6
|
return {
|
|
7
|
+
resolveRefs: true,
|
|
7
8
|
composite: {
|
|
8
9
|
'$.navigation.languages': {
|
|
9
10
|
type: 'array',
|
|
10
11
|
key: '$.language',
|
|
11
12
|
experimentalSort: 'localesAlphabetical',
|
|
13
|
+
splitEntries: true,
|
|
12
14
|
include: [
|
|
13
15
|
'$..group',
|
|
14
16
|
'$..tab',
|
|
@@ -40,6 +42,36 @@ export function generatePreset(preset, type) {
|
|
|
40
42
|
},
|
|
41
43
|
},
|
|
42
44
|
};
|
|
45
|
+
case 'mintlify-hide-default':
|
|
46
|
+
// Mintlify with hideDefaultLocale — paths don't have locale prefix in source
|
|
47
|
+
return {
|
|
48
|
+
resolveRefs: true,
|
|
49
|
+
composite: {
|
|
50
|
+
'$.navigation.languages': {
|
|
51
|
+
type: 'array',
|
|
52
|
+
key: '$.language',
|
|
53
|
+
experimentalSort: 'localesAlphabetical',
|
|
54
|
+
splitEntries: true,
|
|
55
|
+
include: [
|
|
56
|
+
'$..group',
|
|
57
|
+
'$..tab',
|
|
58
|
+
'$..item',
|
|
59
|
+
'$..anchor',
|
|
60
|
+
'$..dropdown',
|
|
61
|
+
],
|
|
62
|
+
transform: {
|
|
63
|
+
'$..pages[*]': {
|
|
64
|
+
match: '^/?(.*)$',
|
|
65
|
+
replace: '{locale}/$1',
|
|
66
|
+
},
|
|
67
|
+
'$..root': {
|
|
68
|
+
match: '^/?(.*)$',
|
|
69
|
+
replace: '{locale}/$1',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
43
75
|
case 'openapi':
|
|
44
76
|
return {
|
|
45
77
|
include: ['$..summary', '$..description'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.14.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.14.19";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.14.
|
|
2
|
+
export const PACKAGE_VERSION = '2.14.19';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -252,8 +252,9 @@ export type StructuralTransform = {
|
|
|
252
252
|
destinationPointer: string;
|
|
253
253
|
};
|
|
254
254
|
export type JsonSchema = {
|
|
255
|
-
preset?: 'mintlify' | 'openapi';
|
|
255
|
+
preset?: 'mintlify' | 'mintlify-hide-default' | 'openapi';
|
|
256
256
|
structuralTransform?: StructuralTransform[];
|
|
257
|
+
resolveRefs?: boolean;
|
|
257
258
|
include?: string[];
|
|
258
259
|
composite?: {
|
|
259
260
|
[sourceObjectPath: string]: SourceObjectOptions;
|
|
@@ -271,6 +272,7 @@ export type SourceObjectOptions = {
|
|
|
271
272
|
localeProperty?: string;
|
|
272
273
|
transform?: TransformOptions;
|
|
273
274
|
experimentalSort?: 'locales' | 'localesAlphabetical';
|
|
275
|
+
splitEntries?: boolean;
|
|
274
276
|
};
|
|
275
277
|
export type TransformOptions = {
|
|
276
278
|
[transformPath: string]: TransformOption;
|
|
@@ -19,10 +19,8 @@ export type ResolvedRefs = {
|
|
|
19
19
|
export declare function resolveMintlifyRefs(json: unknown, filePath: string): ResolvedRefs;
|
|
20
20
|
/**
|
|
21
21
|
* Check if a file should have $ref resolution applied based on the settings.
|
|
22
|
-
* Returns true if the file
|
|
23
|
-
* composite jsonSchema entry.
|
|
22
|
+
* Returns true if the file matches a jsonSchema entry with resolveRefs: true.
|
|
24
23
|
*/
|
|
25
24
|
export declare function shouldResolveRefs(filePath: string, options?: {
|
|
26
|
-
mintlify?: any;
|
|
27
25
|
jsonSchema?: Record<string, any>;
|
|
28
26
|
}): boolean;
|
|
@@ -92,17 +92,14 @@ function resolveRef(obj, baseDir, pointer, visiting, refMap) {
|
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* Check if a file should have $ref resolution applied based on the settings.
|
|
95
|
-
* Returns true if the file
|
|
96
|
-
* composite jsonSchema entry.
|
|
95
|
+
* Returns true if the file matches a jsonSchema entry with resolveRefs: true.
|
|
97
96
|
*/
|
|
98
97
|
export function shouldResolveRefs(filePath, options) {
|
|
99
|
-
if (!options?.
|
|
100
|
-
return false;
|
|
101
|
-
if (!options.jsonSchema)
|
|
98
|
+
if (!options?.jsonSchema)
|
|
102
99
|
return false;
|
|
103
100
|
const relative = path.relative(process.cwd(), filePath);
|
|
104
101
|
for (const [glob, schema] of Object.entries(options.jsonSchema)) {
|
|
105
|
-
if (schema?.
|
|
102
|
+
if (schema?.resolveRefs && micromatch.isMatch(relative, glob)) {
|
|
106
103
|
return true;
|
|
107
104
|
}
|
|
108
105
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Settings } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
|
-
* Post-processing step for
|
|
3
|
+
* Post-processing step for composite JSON files with splitEntries enabled.
|
|
4
4
|
*
|
|
5
|
-
* After mergeJson writes a fully-inlined
|
|
6
|
-
* the original $ref structure
|
|
5
|
+
* After mergeJson writes a fully-inlined composite file, this function:
|
|
6
|
+
* 1. Restores the original $ref structure (if the source used $ref / resolveRefs)
|
|
7
|
+
* 2. Extracts non-default keyed entries into their own ref files
|
|
8
|
+
* to keep the source file compact
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* content to the prefixed paths
|
|
11
|
-
* - Top-level refs (navigation, navbar): restored in docs.json
|
|
10
|
+
* Driven entirely by the jsonSchema config — reads the composite path,
|
|
11
|
+
* key field, and splitEntries flag from the schema.
|
|
12
12
|
*/
|
|
13
13
|
export declare function splitMintlifyLanguageRefs(settings: Settings): Promise<void>;
|
|
@@ -1,74 +1,151 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { logger } from '../console/logger.js';
|
|
4
|
-
import {
|
|
4
|
+
import { validateJsonSchema } from '../formats/json/utils.js';
|
|
5
5
|
import { getStoredRefMap, clearStoredRefMap } from '../state/mintlifyRefMap.js';
|
|
6
|
+
import { JSONPath } from 'jsonpath-plus';
|
|
7
|
+
import { getLocaleProperties } from 'generaltranslation';
|
|
6
8
|
/**
|
|
7
|
-
* Post-processing step for
|
|
9
|
+
* Post-processing step for composite JSON files with splitEntries enabled.
|
|
8
10
|
*
|
|
9
|
-
* After mergeJson writes a fully-inlined
|
|
10
|
-
* the original $ref structure
|
|
11
|
+
* After mergeJson writes a fully-inlined composite file, this function:
|
|
12
|
+
* 1. Restores the original $ref structure (if the source used $ref / resolveRefs)
|
|
13
|
+
* 2. Extracts non-default keyed entries into their own ref files
|
|
14
|
+
* to keep the source file compact
|
|
11
15
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* content to the prefixed paths
|
|
15
|
-
* - Top-level refs (navigation, navbar): restored in docs.json
|
|
16
|
+
* Driven entirely by the jsonSchema config — reads the composite path,
|
|
17
|
+
* key field, and splitEntries flag from the schema.
|
|
16
18
|
*/
|
|
17
19
|
export async function splitMintlifyLanguageRefs(settings) {
|
|
18
|
-
const isMintlify = settings.framework === 'mintlify' || !!settings.options?.mintlify;
|
|
19
|
-
if (!isMintlify)
|
|
20
|
-
return;
|
|
21
20
|
const refMap = getStoredRefMap();
|
|
22
|
-
if (!refMap || refMap.size === 0)
|
|
23
|
-
return;
|
|
24
21
|
try {
|
|
25
22
|
const resolvedJsonPaths = settings.files?.resolvedPaths?.json;
|
|
26
23
|
if (!resolvedJsonPaths)
|
|
27
24
|
return;
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
// Find a JSON file that has splitEntries enabled or resolveRefs
|
|
26
|
+
const targetFile = findTargetFile(resolvedJsonPaths, settings);
|
|
27
|
+
if (!targetFile)
|
|
30
28
|
return;
|
|
31
|
-
|
|
29
|
+
const { filePath: compositeFilePath, splitConfig } = targetFile;
|
|
30
|
+
if (!fs.existsSync(compositeFilePath))
|
|
32
31
|
return;
|
|
33
|
-
let
|
|
32
|
+
let fileJson;
|
|
34
33
|
try {
|
|
35
|
-
|
|
34
|
+
fileJson = JSON.parse(fs.readFileSync(compositeFilePath, 'utf-8'));
|
|
36
35
|
}
|
|
37
36
|
catch {
|
|
38
37
|
return;
|
|
39
38
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
: docsJson?.navigation;
|
|
45
|
-
const languages = navContent?.languages;
|
|
46
|
-
if (!Array.isArray(languages) || languages.length <= 1) {
|
|
47
|
-
restoreTopLevelRefs(docsJson, refMap, docsJsonPath);
|
|
48
|
-
return;
|
|
39
|
+
const docsDir = path.dirname(compositeFilePath);
|
|
40
|
+
// If splitEntries is configured, process it
|
|
41
|
+
if (splitConfig) {
|
|
42
|
+
processSplitEntries(fileJson, compositeFilePath, docsDir, splitConfig, settings, refMap);
|
|
49
43
|
}
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
restoreTopLevelRefs(
|
|
53
|
-
|
|
44
|
+
// Restore top-level refs if any exist
|
|
45
|
+
if (refMap && refMap.size > 0) {
|
|
46
|
+
restoreTopLevelRefs(fileJson, refMap, splitConfig);
|
|
47
|
+
}
|
|
48
|
+
// Always write the composite file back — splitEntries modified the
|
|
49
|
+
// languages array, and restoreTopLevelRefs may not have written it
|
|
50
|
+
// (e.g., when all refs are inside language entries, not top-level)
|
|
51
|
+
fs.writeFileSync(compositeFilePath, JSON.stringify(fileJson, null, 2), 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
clearStoredRefMap();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Find the target file and extract split configuration from the schema.
|
|
59
|
+
*/
|
|
60
|
+
function findTargetFile(resolvedPaths, settings) {
|
|
61
|
+
if (!settings.options?.jsonSchema)
|
|
62
|
+
return null;
|
|
63
|
+
for (const filePath of resolvedPaths) {
|
|
64
|
+
const schema = validateJsonSchema(settings.options, filePath);
|
|
65
|
+
if (!schema)
|
|
66
|
+
continue;
|
|
67
|
+
const hasSplitEntries = schema.composite
|
|
68
|
+
? Object.entries(schema.composite).some(([, opts]) => opts.splitEntries)
|
|
69
|
+
: false;
|
|
70
|
+
const hasResolveRefs = schema.resolveRefs;
|
|
71
|
+
if (!hasSplitEntries && !hasResolveRefs)
|
|
72
|
+
continue;
|
|
73
|
+
// Extract split config if available
|
|
74
|
+
let splitConfig = null;
|
|
75
|
+
if (schema.composite) {
|
|
76
|
+
for (const [compositePath, opts] of Object.entries(schema.composite)) {
|
|
77
|
+
if (opts.splitEntries && opts.type === 'array' && opts.key) {
|
|
78
|
+
splitConfig = {
|
|
79
|
+
compositePath,
|
|
80
|
+
jsonPointer: jsonPathToPointer(compositePath),
|
|
81
|
+
keyField: opts.key,
|
|
82
|
+
keyJsonPath: opts.key,
|
|
83
|
+
sourceObjectOptions: opts,
|
|
84
|
+
};
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
54
88
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
return { filePath, schema, splitConfig };
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Process splitEntries: extract non-default keyed entries into ref files.
|
|
95
|
+
*/
|
|
96
|
+
function processSplitEntries(fileJson, compositeFilePath, docsDir, splitConfig, settings, refMap) {
|
|
97
|
+
const { jsonPointer, keyJsonPath } = splitConfig;
|
|
98
|
+
// Find the composite array — may be behind a $ref
|
|
99
|
+
const parentPointer = jsonPointer.split('/').slice(0, -1).join('/') || '';
|
|
100
|
+
const arrayKey = jsonPointer.split('/').pop() || '';
|
|
101
|
+
const navRefEntry = refMap?.get(parentPointer || undefined);
|
|
102
|
+
// Get the array from the file
|
|
103
|
+
const arrayContainer = parentPointer
|
|
104
|
+
? getAtPointer(fileJson, parentPointer)
|
|
105
|
+
: fileJson;
|
|
106
|
+
if (!arrayContainer)
|
|
107
|
+
return;
|
|
108
|
+
const entries = arrayContainer[arrayKey];
|
|
109
|
+
if (!Array.isArray(entries) || entries.length <= 1)
|
|
110
|
+
return;
|
|
111
|
+
// Determine the default key value (the source entry)
|
|
112
|
+
const defaultKeyValue = getDefaultKeyValue(settings.defaultLocale, splitConfig.sourceObjectOptions);
|
|
113
|
+
const defaultIndex = entries.findIndex((e) => {
|
|
114
|
+
if (!e || typeof e !== 'object')
|
|
115
|
+
return false;
|
|
116
|
+
const values = JSONPath({
|
|
117
|
+
json: e,
|
|
118
|
+
path: keyJsonPath,
|
|
119
|
+
resultType: 'value',
|
|
120
|
+
flatten: true,
|
|
121
|
+
wrap: true,
|
|
122
|
+
});
|
|
123
|
+
return values?.[0] === defaultKeyValue;
|
|
124
|
+
});
|
|
125
|
+
if (defaultIndex < 0)
|
|
126
|
+
return;
|
|
127
|
+
// Determine where the composite array actually lives on disk
|
|
128
|
+
const navDir = navRefEntry ? path.dirname(navRefEntry.sourceFile) : docsDir;
|
|
129
|
+
// Restore $ref structure if the source used $ref
|
|
130
|
+
if (refMap && refMap.size > 0) {
|
|
131
|
+
const defaultPointerPrefix = `${jsonPointer}/${defaultIndex}`;
|
|
59
132
|
const internalRefs = collectInternalRefs(refMap, defaultPointerPrefix);
|
|
60
133
|
if (internalRefs.length > 0) {
|
|
61
|
-
const defaultEntry =
|
|
134
|
+
const defaultEntry = entries[defaultIndex];
|
|
62
135
|
for (const ref of internalRefs) {
|
|
63
136
|
setAtPointer(defaultEntry, ref.relativePointer, {
|
|
64
137
|
$ref: ref.refPath,
|
|
65
138
|
});
|
|
66
139
|
}
|
|
67
|
-
for (const entry of
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
140
|
+
for (const entry of entries) {
|
|
141
|
+
const entryKeyValues = JSONPath({
|
|
142
|
+
json: entry,
|
|
143
|
+
path: keyJsonPath,
|
|
144
|
+
resultType: 'value',
|
|
145
|
+
flatten: true,
|
|
146
|
+
wrap: true,
|
|
147
|
+
});
|
|
148
|
+
if (entryKeyValues?.[0] === defaultKeyValue)
|
|
72
149
|
continue;
|
|
73
150
|
for (const ref of internalRefs) {
|
|
74
151
|
const subtree = getAtPointer(entry, ref.relativePointer);
|
|
@@ -76,66 +153,87 @@ export async function splitMintlifyLanguageRefs(settings) {
|
|
|
76
153
|
continue;
|
|
77
154
|
const originalAbsPath = path.resolve(ref.resolvedDir, ref.refPath);
|
|
78
155
|
const relToNavDir = path.relative(navDir, originalAbsPath);
|
|
79
|
-
const
|
|
156
|
+
const keyValue = entryKeyValues?.[0] || 'unknown';
|
|
157
|
+
const localeRelPath = path.join(keyValue, relToNavDir);
|
|
80
158
|
const outputPath = path.resolve(navDir, localeRelPath);
|
|
81
159
|
writeJsonFile(outputPath, subtree);
|
|
82
|
-
// All refs inside the locale's files use original paths — the locale
|
|
83
|
-
// directory mirrors the source structure, so relative resolution works.
|
|
84
|
-
// The locale prefix only appears in the parent navigation.json entry.
|
|
85
160
|
setAtPointer(entry, ref.relativePointer, { $ref: ref.refPath });
|
|
86
161
|
}
|
|
87
162
|
}
|
|
88
|
-
logger.info(`Restored $ref structure for
|
|
89
|
-
}
|
|
90
|
-
const navFileName = navRefEntry
|
|
91
|
-
? path.basename(navRefEntry.sourceFile)
|
|
92
|
-
: 'navigation.json';
|
|
93
|
-
for (let i = 0; i < languages.length; i++) {
|
|
94
|
-
const entry = languages[i];
|
|
95
|
-
if (!entry || entry.language === defaultLocale)
|
|
96
|
-
continue;
|
|
97
|
-
const locale = entry.language;
|
|
98
|
-
if (!locale)
|
|
99
|
-
continue;
|
|
100
|
-
const { language, ...contentWithoutLanguage } = entry;
|
|
101
|
-
const entryFileName = `${locale}/${navFileName}`;
|
|
102
|
-
const entryFilePath = path.resolve(navDir, entryFileName);
|
|
103
|
-
writeJsonFile(entryFilePath, contentWithoutLanguage);
|
|
104
|
-
languages[i] = { language: locale, $ref: `./${entryFileName}` };
|
|
163
|
+
logger.info(`Restored $ref structure for default entry`);
|
|
105
164
|
}
|
|
106
|
-
logger.info(`Split locale navigation entries into ref files`);
|
|
107
|
-
restoreTopLevelRefs(docsJson, refMap, docsJsonPath);
|
|
108
165
|
}
|
|
109
|
-
|
|
110
|
-
|
|
166
|
+
// Extract each non-default entry into its own ref file
|
|
167
|
+
const navFileName = navRefEntry
|
|
168
|
+
? path.basename(navRefEntry.sourceFile)
|
|
169
|
+
: path.basename(compositeFilePath);
|
|
170
|
+
// Get the actual property name from the key JSONPath (e.g., "$.language" → "language")
|
|
171
|
+
const keyPropertyName = keyJsonPath.replace(/^\$\.?/, '');
|
|
172
|
+
for (let i = 0; i < entries.length; i++) {
|
|
173
|
+
const entry = entries[i];
|
|
174
|
+
if (!entry || typeof entry !== 'object')
|
|
175
|
+
continue;
|
|
176
|
+
const keyValues = JSONPath({
|
|
177
|
+
json: entry,
|
|
178
|
+
path: keyJsonPath,
|
|
179
|
+
resultType: 'value',
|
|
180
|
+
flatten: true,
|
|
181
|
+
wrap: true,
|
|
182
|
+
});
|
|
183
|
+
const keyValue = keyValues?.[0];
|
|
184
|
+
if (!keyValue || keyValue === defaultKeyValue)
|
|
185
|
+
continue;
|
|
186
|
+
const { [keyPropertyName]: _, ...contentWithoutKey } = entry;
|
|
187
|
+
const entryFileName = `${keyValue}/${navFileName}`;
|
|
188
|
+
const entryFilePath = path.resolve(navDir, entryFileName);
|
|
189
|
+
writeJsonFile(entryFilePath, contentWithoutKey);
|
|
190
|
+
entries[i] = { [keyPropertyName]: keyValue, $ref: `./${entryFileName}` };
|
|
111
191
|
}
|
|
192
|
+
logger.info(`Split keyed entries into ref files`);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get the identifying key value for the default locale.
|
|
196
|
+
*/
|
|
197
|
+
function getDefaultKeyValue(defaultLocale, sourceObjectOptions) {
|
|
198
|
+
const localeProperty = sourceObjectOptions.localeProperty || 'code';
|
|
199
|
+
const localeProperties = getLocaleProperties(defaultLocale);
|
|
200
|
+
return (localeProperties[localeProperty] ||
|
|
201
|
+
localeProperties.code ||
|
|
202
|
+
defaultLocale);
|
|
112
203
|
}
|
|
113
204
|
/**
|
|
114
|
-
*
|
|
115
|
-
* Writes each resolved subtree to its original source file and replaces
|
|
116
|
-
* the subtree in docs.json with the $ref pointer.
|
|
205
|
+
* Convert a JSONPath like "$.navigation.languages" to a JSON pointer like "/navigation/languages".
|
|
117
206
|
*/
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
207
|
+
function jsonPathToPointer(jsonPath) {
|
|
208
|
+
return jsonPath
|
|
209
|
+
.replace(/^\$\.?/, '')
|
|
210
|
+
.split('.')
|
|
211
|
+
.filter(Boolean)
|
|
212
|
+
.map((segment) => `/${segment}`)
|
|
213
|
+
.join('');
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Restore top-level $ref pointers in the composite file.
|
|
217
|
+
* Sorted deepest-first so nested refs are written before parents.
|
|
218
|
+
*/
|
|
219
|
+
function restoreTopLevelRefs(fileJson, refMap, splitConfig) {
|
|
220
|
+
// Build a regex to exclude entries inside the composite array
|
|
221
|
+
const arrayPointerPattern = splitConfig
|
|
222
|
+
? new RegExp(`^${splitConfig.jsonPointer.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\/\\d+`)
|
|
223
|
+
: null;
|
|
122
224
|
const entries = [...refMap.entries()]
|
|
123
|
-
.filter(([pointer]) => !
|
|
225
|
+
.filter(([pointer]) => !arrayPointerPattern || !arrayPointerPattern.test(pointer))
|
|
124
226
|
.sort(([a], [b]) => b.length - a.length);
|
|
125
227
|
for (const [pointer, entry] of entries) {
|
|
126
|
-
const subtree = getAtPointer(
|
|
228
|
+
const subtree = getAtPointer(fileJson, pointer);
|
|
127
229
|
if (subtree === undefined)
|
|
128
230
|
continue;
|
|
129
231
|
writeJsonFile(entry.sourceFile, subtree);
|
|
130
|
-
setAtPointer(
|
|
131
|
-
changed = true;
|
|
132
|
-
}
|
|
133
|
-
if (changed) {
|
|
134
|
-
fs.writeFileSync(docsJsonPath, JSON.stringify(docsJson, null, 2), 'utf-8');
|
|
232
|
+
setAtPointer(fileJson, pointer, { $ref: entry.refPath });
|
|
135
233
|
}
|
|
136
234
|
}
|
|
137
235
|
/**
|
|
138
|
-
* Collect refMap entries that describe
|
|
236
|
+
* Collect refMap entries that describe an entry's internal $ref chain.
|
|
139
237
|
* Sorted deepest-first so nested content is extracted before parents.
|
|
140
238
|
*/
|
|
141
239
|
function collectInternalRefs(refMap, entryPointerPrefix) {
|
|
@@ -146,7 +244,6 @@ function collectInternalRefs(refMap, entryPointerPrefix) {
|
|
|
146
244
|
refs.push({
|
|
147
245
|
relativePointer: pointer.slice(entryPointerPrefix.length),
|
|
148
246
|
refPath: entry.refPath,
|
|
149
|
-
// The directory from which this $ref path should be resolved
|
|
150
247
|
resolvedDir: entry.containingDir,
|
|
151
248
|
});
|
|
152
249
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gt",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.19",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"files": [
|
|
@@ -110,9 +110,9 @@
|
|
|
110
110
|
"unified": "^11.0.5",
|
|
111
111
|
"unist-util-visit": "^5.0.0",
|
|
112
112
|
"yaml": "^2.8.0",
|
|
113
|
-
"generaltranslation": "
|
|
114
|
-
"
|
|
115
|
-
"
|
|
113
|
+
"@generaltranslation/python-extractor": "0.2.11",
|
|
114
|
+
"generaltranslation": "8.2.6",
|
|
115
|
+
"gt-remark": "1.0.7"
|
|
116
116
|
},
|
|
117
117
|
"devDependencies": {
|
|
118
118
|
"@babel/types": "^7.28.4",
|