@diplodoc/cli 4.13.4 → 4.13.6
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/assets/vendor.js +1 -1
- package/build/index.js +175 -287
- package/build/index.js.map +4 -4
- package/package.json +4 -4
- package/src/cmd/translate/handler.ts +311 -0
- package/src/cmd/translate/index.ts +14 -320
- package/src/cmd/xliff/compose.ts +71 -177
- package/src/cmd/xliff/extract.ts +97 -168
package/src/cmd/xliff/compose.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import {ok} from 'assert';
|
|
2
|
+
import {argvValidator} from '../../validator';
|
|
3
|
+
import glob from 'glob';
|
|
4
|
+
|
|
1
5
|
const {
|
|
2
6
|
promises: {readFile, writeFile, mkdir},
|
|
3
7
|
} = require('fs');
|
|
4
|
-
import {dirname,
|
|
8
|
+
import {dirname, join} from 'path';
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
import {ComposeParams, compose as composeMD} from '@diplodoc/markdown-translation';
|
|
7
12
|
import {Arguments, Argv} from 'yargs';
|
|
8
13
|
import {eachLimit} from 'async';
|
|
9
14
|
|
|
10
15
|
import {ArgvService} from '../../services';
|
|
11
|
-
import {glob, logger} from '../../utils';
|
|
12
16
|
|
|
13
17
|
const command = 'compose';
|
|
14
18
|
|
|
@@ -16,25 +20,8 @@ const description = 'compose xliff and skeleton into documentation';
|
|
|
16
20
|
|
|
17
21
|
const compose = {command, description, handler, builder};
|
|
18
22
|
|
|
19
|
-
const SKL_MD_GLOB = '**/*.skl.md';
|
|
20
|
-
const XLF_GLOB = '**/*.xliff';
|
|
21
23
|
const MAX_CONCURRENCY = 50;
|
|
22
24
|
|
|
23
|
-
class ComposeError extends Error {
|
|
24
|
-
path: string;
|
|
25
|
-
|
|
26
|
-
constructor(message: string, path: string) {
|
|
27
|
-
super(message);
|
|
28
|
-
|
|
29
|
-
this.path = path;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const USAGE =
|
|
34
|
-
'yfm xliff compose \
|
|
35
|
-
--input <folder-with-xliff-and-skeleton> \
|
|
36
|
-
--ouput <folder-to-store-translated-markdown>';
|
|
37
|
-
|
|
38
25
|
function builder<T>(argv: Argv<T>) {
|
|
39
26
|
return argv
|
|
40
27
|
.option('input', {
|
|
@@ -47,183 +34,90 @@ function builder<T>(argv: Argv<T>) {
|
|
|
47
34
|
describe: 'output folder where translated markdown will be stored',
|
|
48
35
|
type: 'string',
|
|
49
36
|
})
|
|
50
|
-
.
|
|
37
|
+
.option('target-language', {
|
|
38
|
+
alias: 'tl',
|
|
39
|
+
describe: 'target language',
|
|
40
|
+
type: 'string',
|
|
41
|
+
})
|
|
42
|
+
.option('use-source', {
|
|
43
|
+
describe: 'for debug',
|
|
44
|
+
type: 'boolean',
|
|
45
|
+
})
|
|
46
|
+
.check(argvValidator);
|
|
51
47
|
}
|
|
52
48
|
|
|
49
|
+
type HandlerParams = {
|
|
50
|
+
input: string;
|
|
51
|
+
output: string;
|
|
52
|
+
targetLanguage: string;
|
|
53
|
+
exclude?: string[];
|
|
54
|
+
useSource?: boolean;
|
|
55
|
+
};
|
|
56
|
+
|
|
53
57
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
54
|
-
async function handler(args: Arguments<
|
|
58
|
+
async function handler(args: Arguments<HandlerParams>) {
|
|
59
|
+
args = Object.assign({}, args.translate || {}, args);
|
|
60
|
+
delete args.translate;
|
|
61
|
+
|
|
55
62
|
ArgvService.init({
|
|
56
63
|
...args,
|
|
57
64
|
});
|
|
58
65
|
|
|
59
|
-
const {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (xliffPaths.length !== skeletonPaths.length) {
|
|
81
|
-
throw new ComposeError("number of xliff and skeleton files does'not match", input);
|
|
82
|
-
}
|
|
83
|
-
} catch (err) {
|
|
84
|
-
if (err instanceof Error || err instanceof ComposeError) {
|
|
85
|
-
const file = err instanceof ComposeError ? err.path : input;
|
|
86
|
-
|
|
87
|
-
logger.error(file, err.message);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const pipelineParameters = {input, output};
|
|
92
|
-
const configuredPipeline = pipeline(pipelineParameters);
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
logger.info(input, 'staring translated markdown composition pipeline');
|
|
66
|
+
const {
|
|
67
|
+
input,
|
|
68
|
+
output,
|
|
69
|
+
exclude = [],
|
|
70
|
+
targetLanguage,
|
|
71
|
+
useSource = false,
|
|
72
|
+
} = ArgvService.getConfig() as unknown as HandlerParams;
|
|
73
|
+
|
|
74
|
+
ok(input);
|
|
75
|
+
ok(output);
|
|
76
|
+
ok(targetLanguage);
|
|
77
|
+
|
|
78
|
+
const skeletons = glob.sync('**/*.skl', {
|
|
79
|
+
cwd: join(input, targetLanguage),
|
|
80
|
+
ignore: exclude,
|
|
81
|
+
});
|
|
82
|
+
const xliffs = glob.sync('**/*.xliff', {
|
|
83
|
+
cwd: join(input, targetLanguage),
|
|
84
|
+
ignore: exclude,
|
|
85
|
+
});
|
|
96
86
|
|
|
97
|
-
|
|
87
|
+
ok(xliffs.length === skeletons.length, 'Inconsistent number of xliff and skeleton files.');
|
|
98
88
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (err instanceof Error || err instanceof ComposeError) {
|
|
102
|
-
const file = err instanceof ComposeError ? err.path : input;
|
|
89
|
+
const pipelineParameters = {input, output, targetLanguage, useSource};
|
|
90
|
+
const configuredPipeline = pipeline(pipelineParameters);
|
|
103
91
|
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
}
|
|
92
|
+
await eachLimit(skeletons, MAX_CONCURRENCY, configuredPipeline);
|
|
107
93
|
}
|
|
108
94
|
|
|
109
|
-
export type PipelineParameters =
|
|
110
|
-
input: string;
|
|
111
|
-
output: string;
|
|
112
|
-
};
|
|
95
|
+
export type PipelineParameters = ComposeParams;
|
|
113
96
|
|
|
114
97
|
function pipeline(params: PipelineParameters) {
|
|
115
|
-
const {input, output} = params;
|
|
116
|
-
|
|
117
|
-
return async (
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
98
|
+
const {input, output, targetLanguage, useSource} = params;
|
|
99
|
+
|
|
100
|
+
return async (skeletonPath: string) => {
|
|
101
|
+
const fileName = skeletonPath.split('.').slice(0, -1).join('.');
|
|
102
|
+
const xliffPath = fileName + '.xliff';
|
|
103
|
+
|
|
104
|
+
const [skeleton, xliff] = await Promise.all<string[]>([
|
|
105
|
+
readFile(join(input, targetLanguage, skeletonPath), 'utf-8'),
|
|
106
|
+
readFile(join(input, targetLanguage, xliffPath), 'utf-8'),
|
|
107
|
+
]);
|
|
108
|
+
const markdown = composeMD({
|
|
109
|
+
skeleton,
|
|
110
|
+
xliff,
|
|
127
111
|
skeletonPath,
|
|
128
112
|
xliffPath,
|
|
129
|
-
|
|
130
|
-
|
|
113
|
+
useSource,
|
|
114
|
+
});
|
|
131
115
|
|
|
132
|
-
const
|
|
133
|
-
const markdownPath = join(output, inputRelativePath) + '.md';
|
|
134
|
-
|
|
135
|
-
const writerParameters = {
|
|
136
|
-
markdown,
|
|
137
|
-
markdownPath,
|
|
138
|
-
};
|
|
139
|
-
await writer(writerParameters);
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export type ReaderParameters = {
|
|
144
|
-
skeletonPath: string;
|
|
145
|
-
xliffPath: string;
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
async function reader(params: ReaderParameters) {
|
|
149
|
-
const {skeletonPath, xliffPath} = params;
|
|
150
|
-
|
|
151
|
-
let skeleton;
|
|
152
|
-
let xlf;
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
logger.info(skeletonPath, 'reading skeleton file');
|
|
156
|
-
|
|
157
|
-
skeleton = await readFile(skeletonPath, {encoding: 'utf-8'});
|
|
158
|
-
|
|
159
|
-
logger.info(skeletonPath, 'finished reading skeleton file');
|
|
160
|
-
} catch (err) {
|
|
161
|
-
if (err instanceof Error) {
|
|
162
|
-
throw new ComposeError(err.message, skeletonPath);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
logger.info(xliffPath, 'reading xliff file');
|
|
168
|
-
|
|
169
|
-
xlf = await readFile(xliffPath, {encoding: 'utf-8'});
|
|
170
|
-
|
|
171
|
-
logger.info(xliffPath, 'finished reading xliff file');
|
|
172
|
-
} catch (err) {
|
|
173
|
-
if (err instanceof Error) {
|
|
174
|
-
throw new ComposeError(err.message, xliffPath);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return {skeleton, xlf};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export type ComposerParameters = {
|
|
182
|
-
skeletonPath: string;
|
|
183
|
-
xliffPath: string;
|
|
184
|
-
} & ComposeParameters;
|
|
185
|
-
|
|
186
|
-
async function composer(params: ComposerParameters) {
|
|
187
|
-
const {skeletonPath, xliffPath} = params;
|
|
188
|
-
let markdown;
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
logger.info(skeletonPath, 'composing markdown from xliff and skeleton');
|
|
192
|
-
logger.info(xliffPath, 'composing markdown from xliff and skeleton');
|
|
193
|
-
|
|
194
|
-
markdown = markdownTranslation.compose(params);
|
|
195
|
-
|
|
196
|
-
logger.info(skeletonPath, 'finished composing markdown from xliff and skeleton');
|
|
197
|
-
logger.info(xliffPath, 'finished composing markdown from xliff and skeleton');
|
|
198
|
-
} catch (err) {
|
|
199
|
-
if (err instanceof Error) {
|
|
200
|
-
throw new ComposeError(err.message, `${xliffPath} ${skeletonPath}`);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return {markdown};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export type WriterParameters = {
|
|
208
|
-
markdown: string;
|
|
209
|
-
markdownPath: string;
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
async function writer(params: WriterParameters) {
|
|
213
|
-
const {markdown, markdownPath} = params;
|
|
214
|
-
|
|
215
|
-
try {
|
|
216
|
-
logger.info(markdownPath, 'writing markdown file');
|
|
116
|
+
const markdownPath = join(output, targetLanguage, fileName);
|
|
217
117
|
|
|
218
118
|
await mkdir(dirname(markdownPath), {recursive: true});
|
|
219
119
|
await writeFile(markdownPath, markdown);
|
|
220
|
-
|
|
221
|
-
logger.info(markdownPath, 'finished writing markdown file');
|
|
222
|
-
} catch (err) {
|
|
223
|
-
if (err instanceof Error) {
|
|
224
|
-
throw new ComposeError(err.message, markdownPath);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
120
|
+
};
|
|
227
121
|
}
|
|
228
122
|
|
|
229
123
|
export {compose};
|
package/src/cmd/xliff/extract.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import {ok} from 'assert';
|
|
2
|
+
import glob from 'glob';
|
|
3
|
+
import {argvValidator} from '../../validator';
|
|
4
|
+
|
|
1
5
|
const {
|
|
2
6
|
promises: {readFile, writeFile, mkdir},
|
|
3
7
|
} = require('fs');
|
|
4
|
-
import {dirname,
|
|
8
|
+
import {basename, dirname, join, resolve} from 'path';
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
import {ExtractParams, extract as extractMD} from '@diplodoc/markdown-translation';
|
|
7
12
|
import {Arguments, Argv} from 'yargs';
|
|
8
13
|
import {asyncify, eachLimit} from 'async';
|
|
9
14
|
|
|
10
15
|
import {ArgvService} from '../../services';
|
|
11
|
-
import {glob, logger} from '../../utils';
|
|
12
16
|
|
|
13
17
|
const command = 'extract';
|
|
14
18
|
|
|
@@ -16,30 +20,8 @@ const description = 'extract xliff and skeleton from yfm documentation';
|
|
|
16
20
|
|
|
17
21
|
const extract = {command, description, handler, builder};
|
|
18
22
|
|
|
19
|
-
const MD_GLOB = '**/*.md';
|
|
20
|
-
|
|
21
23
|
const MAX_CONCURRENCY = 50;
|
|
22
24
|
|
|
23
|
-
class ExtractError extends Error {
|
|
24
|
-
path: string;
|
|
25
|
-
|
|
26
|
-
constructor(message: string, path: string) {
|
|
27
|
-
super(message);
|
|
28
|
-
|
|
29
|
-
this.path = path;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const USAGE = `yfm xliff extract \
|
|
34
|
-
--input <folder-with-markdown> \
|
|
35
|
-
--output <folder-to-store-xlff-and-skeleton> \
|
|
36
|
-
--sll <source-language>-<source-locale> \
|
|
37
|
-
--tll <target-language>-<target-locale>
|
|
38
|
-
|
|
39
|
-
where <source/target-language> is the language code, as described in ISO 639-1.
|
|
40
|
-
|
|
41
|
-
where <source/target-locale> is the locale code in alpha-2 format, as described in ISO 3166-1`;
|
|
42
|
-
|
|
43
25
|
function builder<T>(argv: Argv<T>) {
|
|
44
26
|
return argv
|
|
45
27
|
.option('source-language-locale', {
|
|
@@ -62,185 +44,132 @@ function builder<T>(argv: Argv<T>) {
|
|
|
62
44
|
describe: 'output folder to store xliff and skeleton files',
|
|
63
45
|
type: 'string',
|
|
64
46
|
})
|
|
65
|
-
.
|
|
66
|
-
['source-language-locale', 'target-language-locale', 'input', 'output'],
|
|
67
|
-
USAGE,
|
|
68
|
-
);
|
|
47
|
+
.check(argvValidator);
|
|
69
48
|
}
|
|
70
49
|
|
|
50
|
+
type HandlerParams = {
|
|
51
|
+
input: string;
|
|
52
|
+
output: string;
|
|
53
|
+
include?: string[];
|
|
54
|
+
exclude?: string[];
|
|
55
|
+
sourceLanguage?: string;
|
|
56
|
+
sourceLocale?: string;
|
|
57
|
+
sourceLanguageLocale?: string;
|
|
58
|
+
targetLanguage?: string;
|
|
59
|
+
targetLocale?: string;
|
|
60
|
+
targetLanguageLocale?: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
71
63
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
-
async function handler(args: Arguments<
|
|
64
|
+
async function handler(args: Arguments<HandlerParams>) {
|
|
65
|
+
args = Object.assign({}, args.translate || {}, args);
|
|
66
|
+
delete args.translate;
|
|
67
|
+
|
|
73
68
|
ArgvService.init({
|
|
74
69
|
...args,
|
|
75
70
|
});
|
|
76
71
|
|
|
77
|
-
const {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
72
|
+
const {
|
|
73
|
+
output,
|
|
74
|
+
exclude = [],
|
|
75
|
+
sourceLanguage,
|
|
76
|
+
sourceLocale,
|
|
77
|
+
targetLanguage,
|
|
78
|
+
targetLocale,
|
|
79
|
+
} = ArgvService.getConfig() as HandlerParams;
|
|
80
|
+
|
|
81
|
+
let {
|
|
82
|
+
input,
|
|
83
|
+
include = [],
|
|
84
|
+
sourceLanguageLocale,
|
|
85
|
+
targetLanguageLocale,
|
|
86
|
+
} = ArgvService.getConfig() as HandlerParams;
|
|
87
|
+
|
|
88
|
+
ok(input);
|
|
89
|
+
ok(output);
|
|
90
|
+
|
|
91
|
+
ok(
|
|
92
|
+
sourceLanguageLocale || (sourceLanguage && sourceLocale),
|
|
93
|
+
'Source language and locale should be configured',
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
ok(
|
|
97
|
+
targetLanguageLocale || (targetLanguage && targetLocale),
|
|
98
|
+
'Source language and locale should be configured',
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
sourceLanguageLocale = sourceLanguageLocale || sourceLanguage + '-' + sourceLocale;
|
|
102
|
+
targetLanguageLocale = targetLanguageLocale || targetLanguage + '-' + targetLocale;
|
|
103
|
+
|
|
104
|
+
const source = parseLanguageLocale(sourceLanguageLocale);
|
|
105
|
+
const target = parseLanguageLocale(targetLanguageLocale);
|
|
106
|
+
|
|
107
|
+
if (input.endsWith('.md')) {
|
|
108
|
+
include = [basename(input)];
|
|
109
|
+
input = dirname(input);
|
|
110
|
+
} else if (!include.length) {
|
|
111
|
+
include.push('**/*');
|
|
105
112
|
}
|
|
106
113
|
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
logger.error(file, err.message);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
114
|
+
const files = ([] as string[]).concat(
|
|
115
|
+
...include.map((match) =>
|
|
116
|
+
glob.sync(match, {
|
|
117
|
+
cwd: join(input, source.language),
|
|
118
|
+
ignore: exclude,
|
|
119
|
+
}),
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
const found = [...new Set(files)];
|
|
123
|
+
const configuredPipeline = pipeline({source, target, input, output});
|
|
124
|
+
|
|
125
|
+
await eachLimit(found, MAX_CONCURRENCY, asyncify(configuredPipeline));
|
|
123
126
|
}
|
|
124
127
|
|
|
125
128
|
function parseLanguageLocale(languageLocale: string) {
|
|
126
129
|
const [language, locale] = languageLocale.split('-');
|
|
127
|
-
if (language?.length
|
|
128
|
-
|
|
130
|
+
if (!language?.length || !locale?.length) {
|
|
131
|
+
throw new Error('invalid language-locale string');
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
|
|
134
|
+
return {language, locale};
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
export type PipelineParameters = {
|
|
135
138
|
input: string;
|
|
136
139
|
output: string;
|
|
137
|
-
source:
|
|
138
|
-
target:
|
|
140
|
+
source: ExtractParams['source'];
|
|
141
|
+
target: ExtractParams['target'];
|
|
139
142
|
};
|
|
140
143
|
|
|
141
144
|
function pipeline(params: PipelineParameters) {
|
|
142
145
|
const {input, output, source, target} = params;
|
|
146
|
+
const inputRoot = resolve(input, source.language);
|
|
147
|
+
const outputRoot = resolve(output, target.language);
|
|
143
148
|
|
|
144
|
-
return async (
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
return async (path: string) => {
|
|
150
|
+
if (!path.endsWith('.md')) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
147
153
|
|
|
148
|
-
const
|
|
154
|
+
const inputPath = join(inputRoot, path);
|
|
155
|
+
const xliffPath = join(outputRoot, path + '.xliff');
|
|
156
|
+
const skeletonPath = join(outputRoot, path + '.skl');
|
|
157
|
+
const markdown = await readFile(inputPath, 'utf-8');
|
|
149
158
|
|
|
150
|
-
|
|
151
|
-
const xlfPath = outputPath + '.xliff';
|
|
152
|
-
const skeletonPath = outputPath + '.skl.md';
|
|
159
|
+
await mkdir(dirname(xliffPath), {recursive: true});
|
|
153
160
|
|
|
154
|
-
const
|
|
155
|
-
markdownPath,
|
|
161
|
+
const {xliff, skeleton} = await extractMD({
|
|
162
|
+
markdownPath: path,
|
|
156
163
|
skeletonPath,
|
|
157
164
|
markdown,
|
|
158
165
|
source,
|
|
159
166
|
target,
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const extracted = await extractor(extractParameters);
|
|
167
|
+
});
|
|
163
168
|
|
|
164
|
-
|
|
165
|
-
...extracted,
|
|
166
|
-
xlfPath,
|
|
167
|
-
skeletonPath,
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
await writer(writerParameters);
|
|
169
|
+
await Promise.all([writeFile(skeletonPath, skeleton), writeFile(xliffPath, xliff)]);
|
|
171
170
|
};
|
|
172
171
|
}
|
|
173
172
|
|
|
174
|
-
export type ReaderParameters = {
|
|
175
|
-
path: string;
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
async function reader(params: ReaderParameters) {
|
|
179
|
-
const {path} = params;
|
|
180
|
-
|
|
181
|
-
let markdown;
|
|
182
|
-
try {
|
|
183
|
-
logger.info(path, 'reading markdown file');
|
|
184
|
-
|
|
185
|
-
markdown = await readFile(path, {encoding: 'utf-8'});
|
|
186
|
-
|
|
187
|
-
logger.info(path, 'finished reading markdown file');
|
|
188
|
-
} catch (err) {
|
|
189
|
-
if (err instanceof Error) {
|
|
190
|
-
throw new ExtractError(err.message, path);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return markdown;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export type ExtractorParameters = {
|
|
198
|
-
source: ExtractParameters['source'];
|
|
199
|
-
target: ExtractParameters['target'];
|
|
200
|
-
skeletonPath: string;
|
|
201
|
-
markdownPath: string;
|
|
202
|
-
markdown: string;
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
async function extractor(params: ExtractorParameters) {
|
|
206
|
-
let extracted;
|
|
207
|
-
|
|
208
|
-
logger.info(params.markdownPath, 'generating skeleton and xliff from markdown');
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
extracted = markdownTranslation.extract(params);
|
|
212
|
-
} catch (err) {
|
|
213
|
-
if (err instanceof Error) {
|
|
214
|
-
throw new ExtractError(err.message, params.markdownPath);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
logger.info(params.markdownPath, 'finished generating skeleton and xliff from markdown');
|
|
219
|
-
|
|
220
|
-
return extracted;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export type WriterParameters = {
|
|
224
|
-
skeletonPath: string;
|
|
225
|
-
skeleton: string;
|
|
226
|
-
xlfPath: string;
|
|
227
|
-
xlf: string;
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
async function writer(params: WriterParameters) {
|
|
231
|
-
const {xlfPath, skeletonPath, xlf, skeleton} = params;
|
|
232
|
-
|
|
233
|
-
logger.info(params.xlfPath, 'writing xliff file');
|
|
234
|
-
logger.info(params.skeletonPath, 'writing skeleton file');
|
|
235
|
-
|
|
236
|
-
await mkdir(dirname(xlfPath), {recursive: true});
|
|
237
|
-
|
|
238
|
-
await Promise.all([writeFile(skeletonPath, skeleton), writeFile(xlfPath, xlf)]);
|
|
239
|
-
|
|
240
|
-
logger.info(params.xlfPath, 'finished writing xliff file');
|
|
241
|
-
logger.info(params.skeletonPath, 'finished writing skeleton file');
|
|
242
|
-
}
|
|
243
|
-
|
|
244
173
|
export {extract};
|
|
245
174
|
|
|
246
175
|
export default {extract};
|