@diplodoc/cli 4.13.7 → 4.13.8
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/index.js +61 -64
- package/build/index.js.map +3 -3
- package/package.json +3 -3
- package/src/cmd/translate/compose.ts +0 -1
- package/src/cmd/translate/extract.ts +0 -1
- package/src/cmd/translate/handler.ts +57 -48
- package/src/cmd/translate/utils/index.ts +2 -6
- package/src/cmd/translate/yandex/auth.ts +20 -31
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.13.
|
|
6
|
+
"version": "4.13.8",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git@github.com:diplodoc-platform/cli.git"
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"@diplodoc/mermaid-extension": "^1.2.1",
|
|
37
37
|
"@diplodoc/openapi-extension": "^1.4.13",
|
|
38
38
|
"@diplodoc/transform": "^4.8.2",
|
|
39
|
-
"@diplodoc/translation": "^1.0.
|
|
39
|
+
"@diplodoc/translation": "^1.0.7",
|
|
40
40
|
"@octokit/core": "4.2.4",
|
|
41
|
-
"@yandex-cloud/nodejs-sdk": "^2.2.2",
|
|
42
41
|
"ajv": "^8.11.0",
|
|
43
42
|
"async": "^3.2.4",
|
|
43
|
+
"axios": "^1.6.7",
|
|
44
44
|
"chalk": "4.1.2",
|
|
45
45
|
"glob": "^8.0.3",
|
|
46
46
|
"highlight.js": "^11.7.0",
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
1
2
|
import {Arguments} from 'yargs';
|
|
2
3
|
import {ArgvService} from '../../services';
|
|
3
4
|
import {logger} from '../../utils';
|
|
4
5
|
import {ok} from 'assert';
|
|
5
|
-
import {dirname, extname, resolve} from 'path';
|
|
6
|
+
import {dirname, extname, join, resolve} from 'path';
|
|
6
7
|
import {mkdir} from 'fs/promises';
|
|
7
|
-
import {
|
|
8
|
+
import {getYandexAuth} from './yandex/auth';
|
|
8
9
|
import {asyncify, eachLimit, retry} from 'async';
|
|
9
|
-
import {Session} from '@yandex-cloud/nodejs-sdk/dist/session';
|
|
10
|
-
import {TranslationServiceClient} from '@yandex-cloud/nodejs-sdk/dist/generated/yandex/cloud/service_clients';
|
|
11
|
-
import {
|
|
12
|
-
TranslateRequest_Format as Format,
|
|
13
|
-
TranslateRequest,
|
|
14
|
-
} from '@yandex-cloud/nodejs-sdk/dist/generated/yandex/cloud/ai/translate/v2/translation_service';
|
|
15
10
|
|
|
16
11
|
import {
|
|
17
12
|
Defer,
|
|
@@ -20,7 +15,6 @@ import {
|
|
|
20
15
|
compose,
|
|
21
16
|
dumpFile,
|
|
22
17
|
extract,
|
|
23
|
-
flat,
|
|
24
18
|
loadFile,
|
|
25
19
|
normalizeParams,
|
|
26
20
|
} from './utils';
|
|
@@ -116,7 +110,7 @@ type TranslatorParams = {
|
|
|
116
110
|
};
|
|
117
111
|
|
|
118
112
|
type RequesterParams = {
|
|
119
|
-
auth:
|
|
113
|
+
auth: string;
|
|
120
114
|
folderId: string | undefined;
|
|
121
115
|
sourceLanguage: string;
|
|
122
116
|
targetLanguage: string;
|
|
@@ -131,18 +125,22 @@ type Request = {
|
|
|
131
125
|
};
|
|
132
126
|
};
|
|
133
127
|
|
|
134
|
-
type Split = (path: string, texts: string[]) => Promise<string
|
|
128
|
+
type Split = (path: string, texts: string[]) => Promise<string>[];
|
|
135
129
|
|
|
136
130
|
type Cache = Map<string, Defer>;
|
|
137
131
|
|
|
132
|
+
type Translations = {
|
|
133
|
+
translations: {
|
|
134
|
+
text: string;
|
|
135
|
+
}[];
|
|
136
|
+
};
|
|
137
|
+
|
|
138
138
|
function requester(params: RequesterParams, cache: Cache) {
|
|
139
139
|
const {auth, folderId, sourceLanguage, targetLanguage, dryRun} = params;
|
|
140
|
-
const session = new Session(auth);
|
|
141
|
-
const client = session.client(TranslationServiceClient);
|
|
142
140
|
const resolve = (text: string, index: number, texts: string[]) => {
|
|
143
141
|
const defer = cache.get(texts[index]);
|
|
144
142
|
if (defer) {
|
|
145
|
-
defer.resolve(
|
|
143
|
+
defer.resolve(text);
|
|
146
144
|
}
|
|
147
145
|
return text;
|
|
148
146
|
};
|
|
@@ -156,23 +154,30 @@ function requester(params: RequesterParams, cache: Cache) {
|
|
|
156
154
|
return texts.map(resolve);
|
|
157
155
|
}
|
|
158
156
|
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
.then((
|
|
175
|
-
|
|
157
|
+
return axios({
|
|
158
|
+
method: 'POST',
|
|
159
|
+
url: 'https://translate.api.cloud.yandex.net/translate/v2/translate',
|
|
160
|
+
headers: {
|
|
161
|
+
'Content-Type': 'application/json',
|
|
162
|
+
Authorization: auth,
|
|
163
|
+
},
|
|
164
|
+
data: {
|
|
165
|
+
folderId,
|
|
166
|
+
texts,
|
|
167
|
+
sourceLanguageCode: sourceLanguage,
|
|
168
|
+
targetLanguageCode: targetLanguage,
|
|
169
|
+
format: 'HTML',
|
|
170
|
+
},
|
|
171
|
+
})
|
|
172
|
+
.then(({data, status}) => {
|
|
173
|
+
if (status === 200) {
|
|
174
|
+
return data;
|
|
175
|
+
} else {
|
|
176
|
+
throw new Error(data.message);
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
.then((result: Translations) => {
|
|
180
|
+
return result.translations.map(({text}, index) => {
|
|
176
181
|
return resolve(text, index, texts);
|
|
177
182
|
});
|
|
178
183
|
})
|
|
@@ -193,6 +198,8 @@ function requester(params: RequesterParams, cache: Cache) {
|
|
|
193
198
|
|
|
194
199
|
function translator(params: TranslatorParams, split: Split) {
|
|
195
200
|
const {input, output, sourceLanguage, targetLanguage} = params;
|
|
201
|
+
const inputRoot = resolve(input);
|
|
202
|
+
const outputRoot = resolve(output);
|
|
196
203
|
|
|
197
204
|
return async (path: string) => {
|
|
198
205
|
const ext = extname(path);
|
|
@@ -200,8 +207,8 @@ function translator(params: TranslatorParams, split: Split) {
|
|
|
200
207
|
return;
|
|
201
208
|
}
|
|
202
209
|
|
|
203
|
-
const inputPath =
|
|
204
|
-
const outputPath =
|
|
210
|
+
const inputPath = join(inputRoot, path);
|
|
211
|
+
const outputPath = join(outputRoot, path.replace(sourceLanguage, targetLanguage));
|
|
205
212
|
const content = await loadFile(inputPath);
|
|
206
213
|
|
|
207
214
|
await mkdir(dirname(outputPath), {recursive: true});
|
|
@@ -227,7 +234,7 @@ function translator(params: TranslatorParams, split: Split) {
|
|
|
227
234
|
return;
|
|
228
235
|
}
|
|
229
236
|
|
|
230
|
-
const parts =
|
|
237
|
+
const parts = await Promise.all(split(path, units));
|
|
231
238
|
const composed = compose(skeleton, parts, {useSource: true});
|
|
232
239
|
|
|
233
240
|
await dumpFile(outputPath, composed);
|
|
@@ -236,37 +243,39 @@ function translator(params: TranslatorParams, split: Split) {
|
|
|
236
243
|
|
|
237
244
|
function splitter(request: Request, cache: Cache): Split {
|
|
238
245
|
return function (path: string, texts: string[]) {
|
|
239
|
-
const promises: Promise<string
|
|
246
|
+
const promises: Promise<string>[] = [];
|
|
240
247
|
let buffer: string[] = [];
|
|
241
248
|
let bufferSize = 0;
|
|
242
249
|
|
|
243
250
|
const release = () => {
|
|
244
|
-
|
|
251
|
+
backoff(request(buffer));
|
|
245
252
|
buffer = [];
|
|
246
253
|
bufferSize = 0;
|
|
247
254
|
};
|
|
248
255
|
|
|
249
256
|
for (const text of texts) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (defer) {
|
|
253
|
-
promises.push(defer.promise);
|
|
254
|
-
} else if (text.length >= BYTES_LIMIT) {
|
|
257
|
+
if (text.length >= BYTES_LIMIT) {
|
|
255
258
|
logger.warn(path, 'Skip document part for translation. Part is too big.');
|
|
256
|
-
promises.push(Promise.resolve(
|
|
259
|
+
promises.push(Promise.resolve(text));
|
|
257
260
|
} else {
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
const defer = cache.get(text) || new Defer();
|
|
262
|
+
promises.push(defer.promise);
|
|
263
|
+
|
|
264
|
+
if (!cache.get(text)) {
|
|
265
|
+
if (bufferSize + text.length > BYTES_LIMIT) {
|
|
266
|
+
release();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
buffer.push(text);
|
|
270
|
+
bufferSize += text.length;
|
|
260
271
|
}
|
|
261
272
|
|
|
262
|
-
|
|
263
|
-
bufferSize += text.length;
|
|
264
|
-
cache.set(text, new Defer());
|
|
273
|
+
cache.set(text, defer);
|
|
265
274
|
}
|
|
266
275
|
}
|
|
267
276
|
|
|
268
277
|
if (bufferSize) {
|
|
269
|
-
|
|
278
|
+
release();
|
|
270
279
|
}
|
|
271
280
|
|
|
272
281
|
return promises;
|
|
@@ -141,16 +141,12 @@ export function resolveSchemas(_path: string) {
|
|
|
141
141
|
return null;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
export function flat<T>(parts: T[][]) {
|
|
145
|
-
return ([] as T[]).concat(...parts);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
144
|
export class Defer {
|
|
149
|
-
resolve!: (text: string
|
|
145
|
+
resolve!: (text: string) => void;
|
|
150
146
|
|
|
151
147
|
reject!: (error: any) => void;
|
|
152
148
|
|
|
153
|
-
promise: Promise<string
|
|
149
|
+
promise: Promise<string>;
|
|
154
150
|
|
|
155
151
|
constructor() {
|
|
156
152
|
this.promise = new Promise((resolve, reject) => {
|
|
@@ -1,41 +1,30 @@
|
|
|
1
1
|
import {readFileSync} from 'fs';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
const resolveKey = (data: string) => {
|
|
4
|
+
switch (true) {
|
|
5
|
+
case data.startsWith('y0_'):
|
|
6
|
+
return 'Bearer ' + data;
|
|
7
|
+
case data.startsWith('t1.'):
|
|
8
|
+
return 'Bearer ' + data;
|
|
9
|
+
case data.startsWith('AQVN'):
|
|
10
|
+
return 'Api-Key ' + data;
|
|
11
|
+
default:
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
8
14
|
};
|
|
9
15
|
|
|
10
|
-
export type AuthInfo = ReturnType<typeof getYandexAuth>;
|
|
11
|
-
|
|
12
16
|
export function getYandexAuth(path: string) {
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
oauthToken: path,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
17
|
+
let auth = resolveKey(path);
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
if (auth !== null) {
|
|
20
|
+
return auth;
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
serviceAccountJson: {
|
|
26
|
-
serviceAccountId: json.service_account_id,
|
|
27
|
-
accessKeyId: json.id,
|
|
28
|
-
privateKey: json.private_key,
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
} catch {}
|
|
23
|
+
auth = resolveKey(readFileSync(path, 'utf8'));
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
25
|
+
if (auth === null) {
|
|
26
|
+
throw new Error('No Auth');
|
|
27
|
+
}
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
return 'private_key' in json;
|
|
29
|
+
return auth;
|
|
41
30
|
}
|