locize-cli 10.3.2 → 11.0.0

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.
@@ -1,163 +1,163 @@
1
- const po2i18next = require('gettext-converter/cjs/po2i18next');
2
- const csvjson = require('csvjson');
3
- const xlsx = require('xlsx');
4
- const yaml = require('yaml');
5
- const asr2js = require('android-string-resource/cjs/asr2js');
6
- const stringsFile = require('strings-file');
7
- const xliff2js = require('xliff/cjs/xliff2js');
8
- const xliff12ToJs = require('xliff/cjs/xliff12ToJs');
9
- const targetOfjs = require('xliff/cjs/targetOfjs');
10
- const sourceOfjs = require('xliff/cjs/sourceOfjs');
11
- const resx2js = require('resx/cjs/resx2js');
12
- const ftl2js = require('fluent_conv/cjs/ftl2js');
13
- const tmx2js = require('tmexchange/cjs/tmx2js');
14
- const laravel2js = require('laravelphp/cjs/laravel2js');
15
- const javaProperties = require('@js.properties/properties');
16
- const xcstrings2locize = require('locize-xcstrings/cjs/xcstrings2locize');
17
- const flatten = require('flat');
18
- const prepareCombinedImport = require('./combineSubkeyPreprocessor').prepareImport;
1
+ const po2i18next = require('gettext-converter/cjs/po2i18next')
2
+ const csvjson = require('csvjson')
3
+ const xlsx = require('xlsx')
4
+ const yaml = require('yaml')
5
+ const asr2js = require('android-string-resource/cjs/asr2js')
6
+ const stringsFile = require('strings-file')
7
+ const xliff2js = require('xliff/cjs/xliff2js')
8
+ const xliff12ToJs = require('xliff/cjs/xliff12ToJs')
9
+ const targetOfjs = require('xliff/cjs/targetOfjs')
10
+ const sourceOfjs = require('xliff/cjs/sourceOfjs')
11
+ const resx2js = require('resx/cjs/resx2js')
12
+ const ftl2js = require('fluent_conv/cjs/ftl2js')
13
+ const tmx2js = require('tmexchange/cjs/tmx2js')
14
+ const laravel2js = require('laravelphp/cjs/laravel2js')
15
+ const javaProperties = require('@js.properties/properties')
16
+ const xcstrings2locize = require('locize-xcstrings/cjs/xcstrings2locize')
17
+ const flatten = require('flat')
18
+ const prepareCombinedImport = require('./combineSubkeyPreprocessor').prepareImport
19
19
 
20
20
  const convertToFlatFormat = (opt, data, lng, cb) => {
21
21
  if (!cb) {
22
- cb = lng;
23
- lng = undefined;
22
+ cb = lng
23
+ lng = undefined
24
24
  }
25
25
  try {
26
26
  if (opt.format === 'json' || opt.format === 'nested' || opt.format === 'flat') {
27
- const dataString = data.toString().trim();
27
+ const dataString = data.toString().trim()
28
28
  if (dataString[0] !== '{' && dataString[0] !== '[') {
29
- return cb(new Error(`Not a valid json file: Content starts with "${dataString[0]}" but should start with "{"`));
29
+ return cb(new Error(`Not a valid json file: Content starts with "${dataString[0]}" but should start with "{"`))
30
30
  }
31
31
  try {
32
- const jsonParsed = JSON.parse(dataString);
33
- cb(null, flatten(jsonParsed));
32
+ const jsonParsed = JSON.parse(dataString)
33
+ cb(null, flatten(jsonParsed))
34
34
  } catch (err) {
35
- return cb(err);
35
+ return cb(err)
36
36
  }
37
- return;
37
+ return
38
38
  }
39
39
  if (opt.format === 'po' || opt.format === 'gettext') {
40
40
  try {
41
41
  const ret = po2i18next(data.toString(), {
42
42
  persistMsgIdPlural: true,
43
43
  ignoreCtx: true
44
- });
45
- cb(null, flatten(ret));
44
+ })
45
+ cb(null, flatten(ret))
46
46
  } catch (err) {
47
- cb(err);
47
+ cb(err)
48
48
  }
49
- return;
49
+ return
50
50
  }
51
51
  if (opt.format === 'po_i18next' || opt.format === 'gettext_i18next') {
52
52
  try {
53
- const potxt = data.toString();
54
- const compatibilityJSON = /msgctxt "(zero|one|two|few|many|other)"/.test(potxt) && 'v4';
55
- const ret = po2i18next(potxt, { compatibilityJSON });
56
- cb(null, flatten(ret));
53
+ const potxt = data.toString()
54
+ const compatibilityJSON = /msgctxt "(zero|one|two|few|many|other)"/.test(potxt) && 'v4'
55
+ const ret = po2i18next(potxt, { compatibilityJSON })
56
+ cb(null, flatten(ret))
57
57
  } catch (err) {
58
- cb(err);
58
+ cb(err)
59
59
  }
60
- return;
60
+ return
61
61
  }
62
62
  if (opt.format === 'csv') {
63
63
  const options = {
64
64
  delimiter: ',',
65
65
  quote: '"'
66
- };
66
+ }
67
67
 
68
68
  // CRLF => LF
69
- var text = data.toString().replace(/\r\n/g, '\n');
69
+ let text = data.toString().replace(/\r\n/g, '\n')
70
70
 
71
71
  // handle multiline stuff
72
- const lines = text.split('\n');
73
- const toHandle = [];
72
+ const lines = text.split('\n')
73
+ const toHandle = []
74
74
  lines.forEach((l) => {
75
- const amountOfOccurrencies = l.split('"').length - 1;
76
- if (amountOfOccurrencies % 2 === 1) toHandle.push(l);
77
- });
75
+ const amountOfOccurrencies = l.split('"').length - 1
76
+ if (amountOfOccurrencies % 2 === 1) toHandle.push(l)
77
+ })
78
78
  while (toHandle.length > 1) {
79
- var firstToHandle = toHandle.shift();
80
- const secondToHandle = toHandle.shift();
81
- const indexOfFirst = lines.indexOf(firstToHandle);
82
- const indexOfSecond = lines.indexOf(secondToHandle);
83
- var handlingIndex = indexOfFirst;
79
+ let firstToHandle = toHandle.shift()
80
+ const secondToHandle = toHandle.shift()
81
+ const indexOfFirst = lines.indexOf(firstToHandle)
82
+ const indexOfSecond = lines.indexOf(secondToHandle)
83
+ let handlingIndex = indexOfFirst
84
84
  while (handlingIndex < indexOfSecond) {
85
- firstToHandle += `\\NeWlInE\\${lines[handlingIndex + 1]}`;
86
- handlingIndex++;
85
+ firstToHandle += `\\NeWlInE\\${lines[handlingIndex + 1]}`
86
+ handlingIndex++
87
87
  }
88
- lines[indexOfFirst] = firstToHandle;
89
- lines.splice(indexOfFirst + 1, indexOfSecond - indexOfFirst);
88
+ lines[indexOfFirst] = firstToHandle
89
+ lines.splice(indexOfFirst + 1, indexOfSecond - indexOfFirst)
90
90
  }
91
- text = lines.join('\n');
91
+ text = lines.join('\n')
92
92
 
93
93
  // https://en.wikipedia.org/wiki/Delimiter-separated_values
94
94
  // temporary replace "" with \_\" so we can revert this 3 lines after
95
- const jsonData = csvjson.toObject(text.replace(/""/g, '\\_\\"'), options);
95
+ const jsonData = csvjson.toObject(text.replace(/""/g, '\\_\\"'), options)
96
96
  data = jsonData.reduce((mem, entry) => {
97
97
  if (entry.key && typeof entry[opt.referenceLanguage] === 'string') {
98
98
  mem[
99
99
  entry.key.replace(/\\_\\"/g, '"').replace(/\\NeWlInE\\/g, '\n')
100
100
  ] = entry[opt.referenceLanguage]
101
101
  .replace(/\\_\\"/g, '"')
102
- .replace(/\\NeWlInE\\/g, '\n');
102
+ .replace(/\\NeWlInE\\/g, '\n')
103
103
  }
104
- return mem;
105
- }, {});
106
- cb(null, data);
107
- return;
104
+ return mem
105
+ }, {})
106
+ cb(null, data)
107
+ return
108
108
  }
109
109
  if (opt.format === 'xlsx') {
110
- const wb = xlsx.read(data, { type: 'buffer' });
111
- const jsonData = xlsx.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
110
+ const wb = xlsx.read(data, { type: 'buffer' })
111
+ const jsonData = xlsx.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])
112
112
  data = jsonData.reduce((mem, entry) => {
113
113
  if (entry.key && typeof entry[opt.referenceLanguage] === 'string') {
114
- mem[entry.key] = entry[opt.referenceLanguage];
114
+ mem[entry.key] = entry[opt.referenceLanguage]
115
115
  }
116
- return mem;
117
- }, {});
118
- cb(null, data);
119
- return;
116
+ return mem
117
+ }, {})
118
+ cb(null, data)
119
+ return
120
120
  }
121
121
  if (
122
122
  opt.format === 'yaml' ||
123
123
  opt.format === 'yml'
124
124
  ) {
125
- const d = data.toString();
126
- if (!d || d === '' || d === '\n') return cb(null, {});
127
- cb(null, flatten(yaml.parse(d)));
128
- return;
125
+ const d = data.toString()
126
+ if (!d || d === '' || d === '\n') return cb(null, {})
127
+ cb(null, flatten(yaml.parse(d)))
128
+ return
129
129
  }
130
130
  if (
131
131
  opt.format === 'yaml-nested' ||
132
132
  opt.format === 'yml-nested'
133
133
  ) {
134
- const d = data.toString();
135
- if (!d || d === '' || d === '\n') return cb(null, {});
136
- cb(null, flatten(yaml.parse(d)));
137
- return;
134
+ const d = data.toString()
135
+ if (!d || d === '' || d === '\n') return cb(null, {})
136
+ cb(null, flatten(yaml.parse(d)))
137
+ return
138
138
  }
139
139
  if (
140
140
  opt.format === 'yaml-rails' ||
141
141
  opt.format === 'yml-rails'
142
142
  ) {
143
- const d = data.toString();
144
- if (!d || d.trim() === '') return cb(null, {});
145
- const jsObj = yaml.parse(d);
143
+ const d = data.toString()
144
+ if (!d || d.trim() === '') return cb(null, {})
145
+ const jsObj = yaml.parse(d)
146
146
  cb(
147
147
  null,
148
148
  flatten(
149
149
  jsObj[Object.keys(jsObj)[0]]
150
150
  )
151
- );
152
- return;
151
+ )
152
+ return
153
153
  }
154
154
  if (
155
155
  opt.format === 'yaml-rails-ns' ||
156
156
  opt.format === 'yml-rails-ns'
157
157
  ) {
158
- const dn = data.toString();
159
- if (!dn || dn.trim() === '') return cb(null, {});
160
- const jsObjn = yaml.parse(dn);
158
+ const dn = data.toString()
159
+ if (!dn || dn.trim() === '') return cb(null, {})
160
+ const jsObjn = yaml.parse(dn)
161
161
  cb(
162
162
  null,
163
163
  flatten(
@@ -165,12 +165,12 @@ const convertToFlatFormat = (opt, data, lng, cb) => {
165
165
  Object.keys(jsObjn[Object.keys(jsObjn)[0]])[0]
166
166
  ]
167
167
  )
168
- );
169
- return;
168
+ )
169
+ return
170
170
  }
171
171
  if (opt.format === 'android') {
172
172
  asr2js(data.toString(), { comment: 'right' }, (err, res) => {
173
- if (err) return cb(err);
173
+ if (err) return cb(err)
174
174
  Object.keys(res).forEach((k) => {
175
175
  if (res[k] !== 'string' && typeof res[k].comment === 'string') {
176
176
  res[k] = {
@@ -178,20 +178,20 @@ const convertToFlatFormat = (opt, data, lng, cb) => {
178
178
  context: {
179
179
  text: res[k].comment,
180
180
  },
181
- };
181
+ }
182
182
  } else {
183
- res[k] = { value: res[k].value || res[k] };
183
+ res[k] = { value: res[k].value || res[k] }
184
184
  }
185
- });
186
- cb(null, res);
187
- });
188
- return;
185
+ })
186
+ cb(null, res)
187
+ })
188
+ return
189
189
  }
190
190
  if (opt.format === 'strings') {
191
191
  // CRLF => LF
192
- data = stringsFile.parse(data.toString().replace(/\r\n/g, '\n'), false);
193
- cb(null, data);
194
- return;
192
+ data = stringsFile.parse(data.toString().replace(/\r\n/g, '\n'), false)
193
+ cb(null, data)
194
+ return
195
195
  }
196
196
  if (
197
197
  opt.format === 'xliff2' ||
@@ -202,13 +202,13 @@ const convertToFlatFormat = (opt, data, lng, cb) => {
202
202
  const fn =
203
203
  opt.format === 'xliff12' || opt.format === 'xlf12'
204
204
  ? xliff12ToJs
205
- : xliff2js;
205
+ : xliff2js
206
206
  fn(data.toString(), (err, res) => {
207
- if (err) return cb(err);
208
- res.resources = res.resources || {};
209
- const ns = Object.keys(res.resources)[0];
210
- const orgRes = res.resources[ns] || res.resources;
211
- function checkForPostProcessing(nsRes) {
207
+ if (err) return cb(err)
208
+ res.resources = res.resources || {}
209
+ const ns = Object.keys(res.resources)[0]
210
+ const orgRes = res.resources[ns] || res.resources
211
+ function checkForPostProcessing (nsRes) {
212
212
  Object.keys(nsRes).forEach((k) => {
213
213
  if (orgRes[k].note && (typeof nsRes[k] === 'string' || !nsRes[k])) {
214
214
  nsRes[k] = {
@@ -216,48 +216,48 @@ const convertToFlatFormat = (opt, data, lng, cb) => {
216
216
  context: {
217
217
  text: orgRes[k].note,
218
218
  }
219
- };
219
+ }
220
220
  }
221
- });
222
- return prepareCombinedImport(nsRes);
221
+ })
222
+ return prepareCombinedImport(nsRes)
223
223
  }
224
224
  if (!res.targetLanguage) {
225
225
  sourceOfjs(res, (err, ret) => {
226
- if (err) return cb(err);
227
- cb(null, checkForPostProcessing(ret));
228
- });
226
+ if (err) return cb(err)
227
+ cb(null, checkForPostProcessing(ret))
228
+ })
229
229
  } else {
230
- let ret = targetOfjs(res);
231
- if (lng !== opt.referenceLanguage) return cb(null, checkForPostProcessing(ret));
232
- ret = ret || {};
233
- const keys = Object.keys(ret);
234
- if (keys.length === 0) return cb(null, checkForPostProcessing(ret));
235
- const allEmpty = keys.filter((k) => ret[k] !== '').length === 0;
236
- if (!allEmpty) return cb(null, checkForPostProcessing(ret));
237
- ret = sourceOfjs(res);
238
- cb(null, checkForPostProcessing(ret));
230
+ let ret = targetOfjs(res)
231
+ if (lng !== opt.referenceLanguage) return cb(null, checkForPostProcessing(ret))
232
+ ret = ret || {}
233
+ const keys = Object.keys(ret)
234
+ if (keys.length === 0) return cb(null, checkForPostProcessing(ret))
235
+ const allEmpty = keys.filter((k) => ret[k] !== '').length === 0
236
+ if (!allEmpty) return cb(null, checkForPostProcessing(ret))
237
+ ret = sourceOfjs(res)
238
+ cb(null, checkForPostProcessing(ret))
239
239
  }
240
- });
241
- return;
240
+ })
241
+ return
242
242
  }
243
243
  if (opt.format === 'resx') {
244
244
  resx2js(data.toString(), (err, res) => {
245
- if (err) return cb(err);
245
+ if (err) return cb(err)
246
246
  res = Object.keys(res).reduce((mem, k) => {
247
- const value = res[k];
247
+ const value = res[k]
248
248
  if (typeof value === 'string') {
249
- mem[k] = value;
249
+ mem[k] = value
250
250
  } else if (value.value) {
251
251
  mem[k] = {
252
252
  value: value.value,
253
253
  context: value.comment ? { text: value.comment } : null,
254
- };
254
+ }
255
255
  }
256
- return mem;
257
- }, {});
258
- cb(null, res);
259
- });
260
- return;
256
+ return mem
257
+ }, {})
258
+ cb(null, res)
259
+ })
260
+ return
261
261
  }
262
262
  if (opt.format === 'fluent') {
263
263
  const fluentJS = ftl2js(
@@ -267,56 +267,56 @@ const convertToFlatFormat = (opt, data, lng, cb) => {
267
267
  new RegExp(String.fromCharCode(160), 'g'),
268
268
  String.fromCharCode(32)
269
269
  )
270
- );
271
- const comments = {};
270
+ )
271
+ const comments = {}
272
272
  Object.keys(fluentJS).forEach((prop) => {
273
273
  if (fluentJS[prop] && fluentJS[prop].comment) {
274
- comments[prop] = fluentJS[prop].comment;
275
- delete fluentJS[prop].comment;
274
+ comments[prop] = fluentJS[prop].comment
275
+ delete fluentJS[prop].comment
276
276
  }
277
- });
278
- const res = flatten(fluentJS);
277
+ })
278
+ const res = flatten(fluentJS)
279
279
  if (res && comments) {
280
280
  Object.keys(comments).forEach((prop) => {
281
281
  res[`${prop}.val`] = {
282
282
  value: res[`${prop}.val`],
283
283
  context: comments[prop] ? { text: comments[prop] } : null,
284
- };
285
- });
284
+ }
285
+ })
286
286
  }
287
- cb(null, res);
288
- return;
287
+ cb(null, res)
288
+ return
289
289
  }
290
290
  if (opt.format === 'tmx') {
291
291
  tmx2js(data.toString(), (err, jsonData) => {
292
- if (err) return cb(err);
293
- const tmxJsRes = jsonData.resources[Object.keys(jsonData.resources)[0]];
294
- const res = {};
292
+ if (err) return cb(err)
293
+ const tmxJsRes = jsonData.resources[Object.keys(jsonData.resources)[0]]
294
+ const res = {}
295
295
  if (tmxJsRes) {
296
296
  Object.keys(tmxJsRes).forEach((k) => {
297
- res[k] = tmxJsRes[k][opt.referenceLanguage];
298
- });
297
+ res[k] = tmxJsRes[k][opt.referenceLanguage]
298
+ })
299
299
  }
300
- cb(null, res);
301
- });
302
- return;
300
+ cb(null, res)
301
+ })
302
+ return
303
303
  }
304
304
  if (opt.format === 'laravel') {
305
- laravel2js(data.toString(), (err, res) => cb(err, flatten(res)));
306
- return;
305
+ laravel2js(data.toString(), (err, res) => cb(err, flatten(res)))
306
+ return
307
307
  }
308
308
  if (opt.format === 'properties') {
309
- cb(null, javaProperties.parseToProperties(data.toString()));
310
- return;
309
+ cb(null, javaProperties.parseToProperties(data.toString()))
310
+ return
311
311
  }
312
312
  if (opt.format === 'xcstrings') {
313
- cb(null, xcstrings2locize(data.toString()));
314
- return;
313
+ cb(null, xcstrings2locize(data.toString()))
314
+ return
315
315
  }
316
- cb(new Error(`${opt.format} is not a valid format!`));
316
+ cb(new Error(`${opt.format} is not a valid format!`))
317
317
  } catch (err) {
318
- cb(err);
318
+ cb(err)
319
319
  }
320
- };
320
+ }
321
321
 
322
- module.exports = convertToFlatFormat;
322
+ module.exports = convertToFlatFormat
package/copyVersion.js CHANGED
@@ -1,69 +1,69 @@
1
- const colors = require('colors');
2
- const request = require('./request');
3
- const getJob = require('./getJob');
1
+ const colors = require('colors')
2
+ const request = require('./request')
3
+ const getJob = require('./getJob')
4
4
 
5
5
  const copyVersion = (opt, cb) => {
6
- const queryParams = new URLSearchParams();
6
+ const queryParams = new URLSearchParams()
7
7
  if (opt.ignoreIfVersionExists) {
8
- queryParams.append('ignoreIfVersionExists', 'true');
8
+ queryParams.append('ignoreIfVersionExists', 'true')
9
9
  }
10
- const queryString = queryParams.size > 0 ? '?' + queryParams.toString() : '';
11
- request(opt.apiPath + '/copy/' + opt.projectId + '/version/' + opt.fromVersion + '/' + opt.toVersion + queryString, {
10
+ const queryString = queryParams.size > 0 ? '?' + queryParams.toString() : ''
11
+ request(opt.apiEndpoint + '/copy/' + opt.projectId + '/version/' + opt.fromVersion + '/' + opt.toVersion + queryString, {
12
12
  method: 'post',
13
13
  headers: {
14
- 'Authorization': opt.apiKey
14
+ Authorization: opt.apiKey
15
15
  }
16
16
  }, (err, res, obj) => {
17
17
  if (err || (obj && (obj.errorMessage || obj.message))) {
18
- if (!cb) console.log(colors.red(`copy failed from ${opt.fromVersion} to ${opt.toVersion}...`));
18
+ if (!cb) console.log(colors.red(`copy failed from ${opt.fromVersion} to ${opt.toVersion}...`))
19
19
 
20
20
  if (err) {
21
- if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
22
- if (cb) cb(err);
23
- return;
21
+ if (!cb) { console.error(colors.red(err.message)); process.exit(1) }
22
+ if (cb) cb(err)
23
+ return
24
24
  }
25
25
  if (obj && (obj.errorMessage || obj.message)) {
26
- if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
27
- if (cb) cb(new Error((obj.errorMessage || obj.message)));
28
- return;
26
+ if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1) }
27
+ if (cb) cb(new Error((obj.errorMessage || obj.message)))
28
+ return
29
29
  }
30
30
  }
31
31
  if (res.status >= 300) {
32
- if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
33
- if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
34
- return;
32
+ if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1) }
33
+ if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'))
34
+ return
35
35
  }
36
36
 
37
37
  if (!obj || !obj.jobId) {
38
- if (!cb) { console.error(colors.red('No jobId! Something went wrong!')); process.exit(1); }
39
- if (cb) cb(new Error('No jobId! Something went wrong!'));
40
- return;
38
+ if (!cb) { console.error(colors.red('No jobId! Something went wrong!')); process.exit(1) }
39
+ if (cb) cb(new Error('No jobId! Something went wrong!'))
40
+ return
41
41
  }
42
42
 
43
- (function waitForJob() {
43
+ (function waitForJob () {
44
44
  getJob(opt, obj.jobId, (err, job) => {
45
45
  if (err) {
46
- if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
47
- if (cb) cb(err);
48
- return;
46
+ if (!cb) { console.error(colors.red(err.message)); process.exit(1) }
47
+ if (cb) cb(err)
48
+ return
49
49
  }
50
50
 
51
51
  if (job && !job.timeouted) {
52
- setTimeout(waitForJob, 2000);
53
- return;
52
+ setTimeout(waitForJob, 2000)
53
+ return
54
54
  }
55
55
 
56
56
  if (job && job.timeouted) {
57
- if (!cb) { console.error(colors.red('Job timeouted!')); process.exit(1); }
58
- if (cb) cb(new Error('Job timeouted!'));
59
- return;
57
+ if (!cb) { console.error(colors.red('Job timeouted!')); process.exit(1) }
58
+ if (cb) cb(new Error('Job timeouted!'))
59
+ return
60
60
  }
61
61
 
62
- if (!cb) console.log(colors.green(`copy from ${opt.fromVersion} to ${opt.toVersion} succesfully requested`));
63
- if (cb) cb(null);
64
- });
65
- })();
66
- });
67
- };
62
+ if (!cb) console.log(colors.green(`copy from ${opt.fromVersion} to ${opt.toVersion} succesfully requested`))
63
+ if (cb) cb(null)
64
+ })
65
+ })()
66
+ })
67
+ }
68
68
 
69
- module.exports = copyVersion;
69
+ module.exports = copyVersion