@diplodoc/cli 4.6.3 → 4.6.5
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/build/app.client.css +65 -53
- package/build/app.client.js +1 -1
- package/build/index.js +60 -30
- package/build/index.js.map +3 -3
- package/package.json +14 -25
- package/src/cmd/translate/index.ts +77 -34
- package/src/steps/publishFilesToS3.ts +0 -51
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Yandex Data UI Team <data-ui@yandex-team.ru>",
|
|
4
4
|
"description": "Make documentation using yfm-docs in Markdown and HTML formats",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "4.6.
|
|
6
|
+
"version": "4.6.5",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git@github.com:diplodoc-platform/cli.git"
|
|
@@ -29,23 +29,17 @@
|
|
|
29
29
|
"npm:": ">=9.*"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@apidevtools/swagger-parser": "^10.1.0",
|
|
33
32
|
"@aws-sdk/client-s3": "^3.369.0",
|
|
34
|
-
"@diplodoc/client": "^1.0
|
|
35
|
-
"@diplodoc/markdown-translation": "^1.0.
|
|
36
|
-
"@diplodoc/mermaid-extension": "^1.1
|
|
37
|
-
"@diplodoc/openapi-extension": "^1.4.
|
|
38
|
-
"@diplodoc/transform": "^4.3
|
|
33
|
+
"@diplodoc/client": "^1.2.0",
|
|
34
|
+
"@diplodoc/markdown-translation": "^1.0.2",
|
|
35
|
+
"@diplodoc/mermaid-extension": "^1.2.1",
|
|
36
|
+
"@diplodoc/openapi-extension": "^1.4.10",
|
|
37
|
+
"@diplodoc/transform": "^4.7.3",
|
|
39
38
|
"@octokit/core": "4.2.4",
|
|
40
|
-
"@types/glob": "^8.0.0",
|
|
41
|
-
"@types/json-stringify-safe": "^5.0.0",
|
|
42
39
|
"@yandex-cloud/nodejs-sdk": "^2.2.2",
|
|
43
40
|
"ajv": "^8.11.0",
|
|
44
41
|
"async": "^3.2.4",
|
|
45
|
-
"aws-sdk": "^2.1425.0",
|
|
46
|
-
"bem-cn-lite": "^4.1.0",
|
|
47
42
|
"chalk": "4.1.2",
|
|
48
|
-
"dotenv": "^16.0.3",
|
|
49
43
|
"fast-xml-parser": "^4.0.11",
|
|
50
44
|
"glob": "^8.0.3",
|
|
51
45
|
"highlight.js": "^11.7.0",
|
|
@@ -66,13 +60,15 @@
|
|
|
66
60
|
"yargs": "17.7.2"
|
|
67
61
|
},
|
|
68
62
|
"devDependencies": {
|
|
69
|
-
"@diplodoc/eslint-config": "^
|
|
70
|
-
"@diplodoc/prettier-config": "^
|
|
63
|
+
"@diplodoc/eslint-config": "^2.0.0",
|
|
64
|
+
"@diplodoc/prettier-config": "^2.0.0",
|
|
71
65
|
"@diplodoc/tsconfig": "^1.0.2",
|
|
72
66
|
"@types/async": "^3.2.15",
|
|
73
67
|
"@types/chalk": "2.2.0",
|
|
68
|
+
"@types/glob": "^8.1.0",
|
|
74
69
|
"@types/html-escaper": "^3.0.0",
|
|
75
70
|
"@types/js-yaml": "4.0.5",
|
|
71
|
+
"@types/json-stringify-safe": "^5.0.3",
|
|
76
72
|
"@types/lodash": "4.14.195",
|
|
77
73
|
"@types/mime-types": "2.1.1",
|
|
78
74
|
"@types/node": "14.*",
|
|
@@ -80,21 +76,11 @@
|
|
|
80
76
|
"@types/tar-stream": "^2.2.2",
|
|
81
77
|
"@types/yargs": "17.0.24",
|
|
82
78
|
"esbuild": "^0.17.17",
|
|
83
|
-
"eslint": "^8.0.0",
|
|
84
79
|
"husky": "8.0.3",
|
|
85
80
|
"lint-staged": "13.2.2",
|
|
86
81
|
"lodash": "4.17.21",
|
|
87
|
-
"prettier": "^3.0.3",
|
|
88
|
-
"ts-jest": "29.1.0",
|
|
89
|
-
"ts-node": "^10.9.1",
|
|
90
82
|
"typescript": "4.9.5"
|
|
91
83
|
},
|
|
92
|
-
"overrides": {
|
|
93
|
-
"react-sortable-hoc": {
|
|
94
|
-
"react": "^18.2.0",
|
|
95
|
-
"react-dom": "^18.2.0"
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
84
|
"husky": {
|
|
99
85
|
"hooks": {
|
|
100
86
|
"pre-commit": "lint-staged"
|
|
@@ -129,5 +115,8 @@
|
|
|
129
115
|
"tool",
|
|
130
116
|
"tools",
|
|
131
117
|
"generator"
|
|
132
|
-
]
|
|
118
|
+
],
|
|
119
|
+
"overrides": {
|
|
120
|
+
"markdown-it": "^13.0.2"
|
|
121
|
+
}
|
|
133
122
|
}
|
|
@@ -34,7 +34,8 @@ const translate = {
|
|
|
34
34
|
|
|
35
35
|
const MD_GLOB = '**/*.md';
|
|
36
36
|
const REQUESTS_LIMIT = 20;
|
|
37
|
-
const
|
|
37
|
+
const BYTES_LIMIT = 10000;
|
|
38
|
+
const RETRY_LIMIT = 3;
|
|
38
39
|
const MTRANS_LOCALE = 'MTRANS';
|
|
39
40
|
|
|
40
41
|
function builder<T>(argv: Argv<T>) {
|
|
@@ -148,6 +149,23 @@ function translator(params: TranslatorParams) {
|
|
|
148
149
|
|
|
149
150
|
const session = new Session({oauthToken});
|
|
150
151
|
const client = session.client(TranslationServiceClient);
|
|
152
|
+
const request = (texts: string[]) => () =>
|
|
153
|
+
client
|
|
154
|
+
.translate(
|
|
155
|
+
TranslateRequest.fromPartial({
|
|
156
|
+
texts,
|
|
157
|
+
folderId,
|
|
158
|
+
sourceLanguageCode: sourceLanguage,
|
|
159
|
+
targetLanguageCode: targetLanguage,
|
|
160
|
+
glossaryConfig: {
|
|
161
|
+
glossaryData: {
|
|
162
|
+
glossaryPairs: yandexCloudTranslateGlossaryPairs,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
format: Format.PLAIN_TEXT,
|
|
166
|
+
}),
|
|
167
|
+
)
|
|
168
|
+
.then((results) => results.translations.map(({text}) => text));
|
|
151
169
|
|
|
152
170
|
return async (mdPath: string) => {
|
|
153
171
|
try {
|
|
@@ -171,45 +189,57 @@ function translator(params: TranslatorParams) {
|
|
|
171
189
|
|
|
172
190
|
const texts = parseSourcesFromXLIFF(xlf);
|
|
173
191
|
|
|
174
|
-
const
|
|
175
|
-
texts
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
const parts = await Promise.all(
|
|
193
|
+
texts.reduce(
|
|
194
|
+
(
|
|
195
|
+
{
|
|
196
|
+
promises,
|
|
197
|
+
buffer,
|
|
198
|
+
bufferSize,
|
|
199
|
+
}: {
|
|
200
|
+
promises: Promise<string[]>[];
|
|
201
|
+
buffer: string[];
|
|
202
|
+
bufferSize: number;
|
|
203
|
+
},
|
|
204
|
+
text,
|
|
205
|
+
index,
|
|
206
|
+
) => {
|
|
207
|
+
if (text.length >= BYTES_LIMIT) {
|
|
208
|
+
logger.warn(
|
|
209
|
+
mdPath,
|
|
210
|
+
'Skip document part for translation. Part is too big.',
|
|
211
|
+
);
|
|
212
|
+
promises.push(Promise.resolve([text]));
|
|
213
|
+
return {promises, buffer, bufferSize};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (bufferSize + text.length > BYTES_LIMIT || index === texts.length - 1) {
|
|
217
|
+
promises.push(backoff(request(buffer)));
|
|
218
|
+
buffer = [];
|
|
219
|
+
bufferSize = 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
buffer.push(text);
|
|
223
|
+
bufferSize += text.length;
|
|
224
|
+
|
|
225
|
+
return {promises, buffer, bufferSize};
|
|
182
226
|
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const translations = await retry(
|
|
188
|
-
{
|
|
189
|
-
times: RETRY_LIMIT,
|
|
190
|
-
interval: (count: number) => {
|
|
191
|
-
// eslint-disable-next-line no-bitwise
|
|
192
|
-
return (1 << count) * 1000;
|
|
227
|
+
{
|
|
228
|
+
promises: [],
|
|
229
|
+
buffer: [],
|
|
230
|
+
bufferSize: 0,
|
|
193
231
|
},
|
|
194
|
-
|
|
195
|
-
asyncify(
|
|
196
|
-
async () =>
|
|
197
|
-
await client
|
|
198
|
-
.translate(machineTranslateParams)
|
|
199
|
-
.then((results: {translations: {text: string}[]}) =>
|
|
200
|
-
results.translations.map(({text}: {text: string}) => text),
|
|
201
|
-
),
|
|
202
|
-
),
|
|
232
|
+
).promises,
|
|
203
233
|
);
|
|
204
234
|
|
|
205
|
-
const
|
|
235
|
+
const translations = ([] as string[]).concat(...parts);
|
|
236
|
+
|
|
237
|
+
const translatedXLIFF = createXLIFFDocument({
|
|
206
238
|
sourceLanguage: sourceLanguage + '-' + MTRANS_LOCALE,
|
|
207
239
|
targetLanguage: targetLanguage + '-' + MTRANS_LOCALE,
|
|
208
240
|
sources: texts,
|
|
209
|
-
targets: translations
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
const translatedXLIFF = createXLIFFDocument(createXLIFFDocumentParams);
|
|
241
|
+
targets: translations,
|
|
242
|
+
});
|
|
213
243
|
|
|
214
244
|
const composed = await markdownTranslation.compose({
|
|
215
245
|
xlf: translatedXLIFF,
|
|
@@ -230,7 +260,20 @@ function translator(params: TranslatorParams) {
|
|
|
230
260
|
};
|
|
231
261
|
}
|
|
232
262
|
|
|
233
|
-
function
|
|
263
|
+
function backoff(action: () => Promise<string[]>): Promise<string[]> {
|
|
264
|
+
return retry(
|
|
265
|
+
{
|
|
266
|
+
times: RETRY_LIMIT,
|
|
267
|
+
interval: (count: number) => {
|
|
268
|
+
// eslint-disable-next-line no-bitwise
|
|
269
|
+
return (1 << count) * 1000;
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
asyncify(action),
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function parseSourcesFromXLIFF(xliff: string): string[] {
|
|
234
277
|
const parser = new XMLParser();
|
|
235
278
|
|
|
236
279
|
const inputs = parser.parse(xliff)?.xliff?.file?.body['trans-unit'] ?? [];
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import {readFileSync} from 'fs';
|
|
2
|
-
import walkSync from 'walk-sync';
|
|
3
|
-
import {join, resolve} from 'path';
|
|
4
|
-
import S3 from 'aws-sdk/clients/s3';
|
|
5
|
-
import mime from 'mime-types';
|
|
6
|
-
|
|
7
|
-
import {ArgvService} from '../services';
|
|
8
|
-
import {convertBackSlashToSlash, logger} from '../utils';
|
|
9
|
-
|
|
10
|
-
const DEFAULT_PREFIX = process.env.YFM_STORAGE_PREFIX ?? '';
|
|
11
|
-
|
|
12
|
-
export async function publishFilesToS3(): Promise<void> {
|
|
13
|
-
const {
|
|
14
|
-
output: outputFolderPath,
|
|
15
|
-
ignore = [],
|
|
16
|
-
storageEndpoint: endpoint,
|
|
17
|
-
storageBucket: bucket,
|
|
18
|
-
storagePrefix: prefix = DEFAULT_PREFIX,
|
|
19
|
-
storageKeyId: accessKeyId,
|
|
20
|
-
storageSecretKey: secretAccessKey,
|
|
21
|
-
} = ArgvService.getConfig();
|
|
22
|
-
|
|
23
|
-
const s3Client = new S3({
|
|
24
|
-
endpoint,
|
|
25
|
-
accessKeyId,
|
|
26
|
-
secretAccessKey,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const filesToPublish: string[] = walkSync(resolve(outputFolderPath), {
|
|
30
|
-
directories: false,
|
|
31
|
-
includeBasePath: false,
|
|
32
|
-
ignore,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
await Promise.all(
|
|
36
|
-
filesToPublish.map(async (pathToFile) => {
|
|
37
|
-
const mimeType = mime.lookup(pathToFile);
|
|
38
|
-
|
|
39
|
-
const params: S3.Types.PutObjectRequest = {
|
|
40
|
-
ContentType: mimeType ? mimeType : undefined,
|
|
41
|
-
Bucket: bucket,
|
|
42
|
-
Key: convertBackSlashToSlash(join(prefix, pathToFile)),
|
|
43
|
-
Body: readFileSync(resolve(outputFolderPath, pathToFile)),
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
logger.upload(pathToFile);
|
|
47
|
-
|
|
48
|
-
return s3Client.upload(params).promise();
|
|
49
|
-
}),
|
|
50
|
-
);
|
|
51
|
-
}
|