@esgettext/tools 1.1.0 → 1.3.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.
Files changed (91) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/dist/command.js +0 -1
  4. package/dist/commands/add-language.js +100 -0
  5. package/dist/commands/convert.js +17 -15
  6. package/dist/commands/init.js +743 -0
  7. package/dist/commands/install.js +21 -6
  8. package/dist/commands/msgfmt-all.js +72 -50
  9. package/dist/commands/msgmerge-all.js +71 -49
  10. package/dist/commands/potfiles.js +165 -0
  11. package/dist/commands/xgettext/file-resolver.js +0 -1
  12. package/dist/commands/xgettext/files-collector.js +1 -1
  13. package/dist/commands/xgettext.js +37 -17
  14. package/dist/configuration.js +174 -115
  15. package/dist/esgettext-package-json.js +0 -1
  16. package/dist/index.js +97 -29
  17. package/dist/optspec.js +28 -0
  18. package/dist/package.js +4 -2
  19. package/dist/parser/javascript.js +2 -1
  20. package/dist/parser/parser.js +17 -2
  21. package/dist/parser/po.js +34 -1
  22. package/dist/parser/typescript.js +2 -1
  23. package/dist/pot/catalog.js +36 -1
  24. package/dist/pot/entry.js +71 -1
  25. package/dist/pot/keyword.js +10 -5
  26. package/package.json +11 -6
  27. package/dist/command.d.ts +0 -11
  28. package/dist/command.js.map +0 -1
  29. package/dist/commands/convert.d.ts +0 -24
  30. package/dist/commands/convert.js.map +0 -1
  31. package/dist/commands/install.d.ts +0 -22
  32. package/dist/commands/install.js.map +0 -1
  33. package/dist/commands/msgfmt-all.d.ts +0 -20
  34. package/dist/commands/msgfmt-all.js.map +0 -1
  35. package/dist/commands/msgmerge-all.d.ts +0 -21
  36. package/dist/commands/msgmerge-all.js.map +0 -1
  37. package/dist/commands/xgettext/file-resolver.d.ts +0 -5
  38. package/dist/commands/xgettext/file-resolver.js.map +0 -1
  39. package/dist/commands/xgettext/file-resolver.spec.d.ts +0 -1
  40. package/dist/commands/xgettext/file-resolver.spec.js +0 -22
  41. package/dist/commands/xgettext/file-resolver.spec.js.map +0 -1
  42. package/dist/commands/xgettext/files-collector.d.ts +0 -5
  43. package/dist/commands/xgettext/files-collector.js.map +0 -1
  44. package/dist/commands/xgettext/files-collector.spec.d.ts +0 -1
  45. package/dist/commands/xgettext/files-collector.spec.js +0 -96
  46. package/dist/commands/xgettext/files-collector.spec.js.map +0 -1
  47. package/dist/commands/xgettext.d.ts +0 -29
  48. package/dist/commands/xgettext.js.map +0 -1
  49. package/dist/commands/xgettext.spec.d.ts +0 -1
  50. package/dist/commands/xgettext.spec.js +0 -897
  51. package/dist/commands/xgettext.spec.js.map +0 -1
  52. package/dist/configuration.d.ts +0 -36
  53. package/dist/configuration.js.map +0 -1
  54. package/dist/esgettext-package-json.d.ts +0 -15
  55. package/dist/esgettext-package-json.js.map +0 -1
  56. package/dist/index.d.ts +0 -2
  57. package/dist/index.js.map +0 -1
  58. package/dist/package.d.ts +0 -5
  59. package/dist/package.js.map +0 -1
  60. package/dist/parser/javascript.d.ts +0 -4
  61. package/dist/parser/javascript.js.map +0 -1
  62. package/dist/parser/javascript.spec.d.ts +0 -1
  63. package/dist/parser/javascript.spec.js +0 -535
  64. package/dist/parser/javascript.spec.js.map +0 -1
  65. package/dist/parser/parser.d.ts +0 -45
  66. package/dist/parser/parser.js.map +0 -1
  67. package/dist/parser/po.d.ts +0 -22
  68. package/dist/parser/po.js.map +0 -1
  69. package/dist/parser/po.spec.d.ts +0 -1
  70. package/dist/parser/po.spec.js +0 -486
  71. package/dist/parser/po.spec.js.map +0 -1
  72. package/dist/parser/typescript.d.ts +0 -4
  73. package/dist/parser/typescript.js.map +0 -1
  74. package/dist/parser/typescript.spec.d.ts +0 -1
  75. package/dist/parser/typescript.spec.js +0 -121
  76. package/dist/parser/typescript.spec.js.map +0 -1
  77. package/dist/pot/catalog.d.ts +0 -26
  78. package/dist/pot/catalog.js.map +0 -1
  79. package/dist/pot/catalog.spec.d.ts +0 -1
  80. package/dist/pot/catalog.spec.js +0 -244
  81. package/dist/pot/catalog.spec.js.map +0 -1
  82. package/dist/pot/entry.d.ts +0 -35
  83. package/dist/pot/entry.js.map +0 -1
  84. package/dist/pot/entry.spec.d.ts +0 -1
  85. package/dist/pot/entry.spec.js +0 -433
  86. package/dist/pot/entry.spec.js.map +0 -1
  87. package/dist/pot/keyword.d.ts +0 -17
  88. package/dist/pot/keyword.js.map +0 -1
  89. package/dist/pot/keyword.spec.d.ts +0 -1
  90. package/dist/pot/keyword.spec.js +0 -54
  91. package/dist/pot/keyword.spec.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,56 +1,91 @@
1
1
  #! /usr/bin/env node
2
2
  "use strict";
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
3
12
  var __importDefault = (this && this.__importDefault) || function (mod) {
4
13
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
14
  };
6
15
  Object.defineProperty(exports, "__esModule", { value: true });
7
16
  const yargs_1 = __importDefault(require("yargs"));
8
- const package_1 = require("./package");
17
+ const package_js_1 = require("./package.js");
9
18
  const runtime_1 = require("@esgettext/runtime");
10
- const configuration_1 = require("./configuration");
11
- const xgettext_1 = require("./commands/xgettext");
12
- const msgmerge_all_1 = require("./commands/msgmerge-all");
13
- const install_1 = require("./commands/install");
14
- const convert_1 = require("./commands/convert");
15
- const msgfmt_all_1 = require("./commands/msgfmt-all");
19
+ const configuration_js_1 = require("./configuration.js");
20
+ const xgettext_js_1 = require("./commands/xgettext.js");
21
+ const msgmerge_all_js_1 = require("./commands/msgmerge-all.js");
22
+ const install_js_1 = require("./commands/install.js");
23
+ const convert_js_1 = require("./commands/convert.js");
24
+ const msgfmt_all_js_1 = require("./commands/msgfmt-all.js");
25
+ const init_js_1 = require("./commands/init.js");
26
+ const potfiles_js_1 = require("./commands/potfiles.js");
27
+ const add_language_js_1 = require("./commands/add-language.js");
16
28
  const commandNames = [
17
- 'xgettext',
18
- 'msgmerge-all',
19
- 'msgfmt-all',
20
- 'install',
29
+ 'add-language',
21
30
  'convert',
31
+ 'install',
32
+ 'init',
33
+ 'msgfmt-all',
34
+ 'msgmerge-all',
35
+ 'potfiles',
36
+ 'xgettext',
22
37
  ];
38
+ const configFiles = locateConfigFiles();
39
+ const pkgJsonFile = locatePkgJsonFile();
23
40
  const gtx = runtime_1.Textdomain.getInstance('com.cantanea.esgettext-tools');
24
41
  gtx
25
42
  .resolve()
26
- .then(async () => {
43
+ .then(() => __awaiter(void 0, void 0, void 0, function* () {
44
+ var _a;
27
45
  const locale = runtime_1.Textdomain.selectLocale(['en-US', 'en-GB', 'de']);
28
46
  const ulocale = locale.replace('-', '_');
29
- const configuration = await configuration_1.ConfigurationFactory.create(locale);
47
+ const configuration = yield configuration_js_1.ConfigurationFactory.create(configFiles, pkgJsonFile, locale);
30
48
  if (!configuration)
31
49
  process.exit(1);
32
50
  const commands = {
33
- xgettext: new xgettext_1.XGettext(configuration),
34
- 'msgmerge-all': new msgmerge_all_1.MsgmergeAll(configuration),
35
- 'msgfmt-all': new msgfmt_all_1.MsgfmtAll(configuration),
36
- install: new install_1.Install(configuration),
37
- convert: new convert_1.Convert(configuration),
51
+ xgettext: new xgettext_js_1.XGettext(configuration),
52
+ 'msgmerge-all': new msgmerge_all_js_1.MsgmergeAll(configuration),
53
+ 'msgfmt-all': new msgfmt_all_js_1.MsgfmtAll(configuration),
54
+ install: new install_js_1.Install(configuration),
55
+ convert: new convert_js_1.Convert(configuration),
56
+ init: new init_js_1.Init(configuration),
57
+ potfiles: new potfiles_js_1.Potfiles(configuration),
58
+ 'add-language': new add_language_js_1.AddLanguage(configuration),
38
59
  };
39
60
  const program = (0, yargs_1.default)(process.argv.slice(2))
40
61
  .locale(ulocale)
41
62
  .strict()
63
+ .options({
64
+ configuration: {
65
+ alias: ['config-file'],
66
+ type: 'string',
67
+ describe: gtx._('Path to configuration file'),
68
+ default: 'esgettext.config.{mjs,cjs,js,json}',
69
+ },
70
+ package: {
71
+ alias: ['package-json'],
72
+ type: 'string',
73
+ describe: gtx._("Path to 'package.json'"),
74
+ default: 'package.json',
75
+ },
76
+ })
42
77
  .showHelpOnFail(false, gtx._x("Try {programName} '--help' for more information!", {
43
- programName: package_1.Package.getName(),
78
+ programName: package_js_1.Package.getName(),
44
79
  }))
45
80
  .demandCommand(1, gtx._('Error: No command given.'))
46
- .scriptName(package_1.Package.getName());
47
- let epilogue = configuration.files.length
81
+ .scriptName(package_js_1.Package.getName());
82
+ let epilogue = ((_a = configuration.files) === null || _a === void 0 ? void 0 : _a.length)
48
83
  ? gtx._x('Additional defaults read from: {files}.', {
49
84
  files: configuration.files.join(', '),
50
85
  }) + '\n\n'
51
86
  : '';
52
87
  epilogue += gtx._x('Report bugs in the bugtracker at {url}!', {
53
- url: package_1.Package.getBugTrackerUrl(),
88
+ url: package_js_1.Package.getBugTrackerUrl(),
54
89
  });
55
90
  for (const name of commandNames) {
56
91
  const command = commands[name];
@@ -66,19 +101,52 @@ gtx
66
101
  command.additional(argv);
67
102
  return argv.options(command.args());
68
103
  },
69
- handler: async (argv) => {
70
- argv._.shift();
71
- const exitCode = await command.run(argv);
104
+ handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
105
+ argv._.shift(); // Remove the command name.
106
+ const exitCode = yield command.run(argv);
72
107
  process.exit(exitCode);
73
- },
108
+ }),
74
109
  });
75
110
  }
76
111
  program.help().epilogue(epilogue).parse();
77
- })
112
+ }))
78
113
  .catch((exception) => {
79
114
  console.error(gtx._x('{programName}: unhandled exception: {exception}'), {
80
- programName: package_1.Package.getName(),
115
+ programName: package_js_1.Package.getName(),
81
116
  exception,
82
117
  });
83
118
  });
84
- //# sourceMappingURL=index.js.map
119
+ function getArgument(option) {
120
+ const longOption = '--' + option;
121
+ const longOptionRe = new RegExp(`^${longOption}=.+`);
122
+ const args = process.argv.slice(2);
123
+ for (const [index, arg] of args.entries()) {
124
+ if (arg == longOption && index < args.length) {
125
+ return args[index + 1];
126
+ }
127
+ else if (arg.match(longOptionRe)) {
128
+ return arg.substring(longOption.length + 1);
129
+ }
130
+ else if (arg[0] !== '-') {
131
+ break;
132
+ }
133
+ }
134
+ return null;
135
+ }
136
+ function locateConfigFiles() {
137
+ var _a;
138
+ const configFile = (_a = getArgument('config-file')) !== null && _a !== void 0 ? _a : getArgument('configuration');
139
+ return configFile !== null
140
+ ? [configFile]
141
+ : [
142
+ 'esgettext.config.mjs',
143
+ 'esgettext.config.cjs',
144
+ 'esgettext.config.js',
145
+ 'esgettext.config.json',
146
+ ];
147
+ }
148
+ function locatePkgJsonFile() {
149
+ var _a;
150
+ const configFile = (_a = getArgument('package')) !== null && _a !== void 0 ? _a : getArgument('package-json');
151
+ return configFile !== null ? configFile : 'package.json';
152
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.coerceOptions = void 0;
4
+ const runtime_1 = require("@esgettext/runtime");
5
+ const package_1 = require("./package");
6
+ const gtx = runtime_1.Textdomain.getInstance('com.cantanea.esgettext-tools');
7
+ function coerceOptions(args, optspecs) {
8
+ for (const optname in optspecs) {
9
+ const optspec = optspecs[optname];
10
+ const optkey = optname.replace(/-(.)/g, (_, group1) => group1.toUpperCase());
11
+ const arg = args[optkey];
12
+ const isArray = typeof arg === 'object' && Array.isArray(arg);
13
+ if (optspec.multi) {
14
+ if (typeof arg !== 'undefined' && !isArray) {
15
+ args[optkey] = [args[optkey]];
16
+ }
17
+ }
18
+ else {
19
+ if (isArray) {
20
+ console.error(gtx._x('{programName}: Error: The option' +
21
+ ' {optname} cannot be specified more than once!', { programName: package_1.Package.getName(), optname }));
22
+ return false;
23
+ }
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+ exports.coerceOptions = coerceOptions;
package/dist/package.js CHANGED
@@ -9,8 +9,10 @@ class Package {
9
9
  return 'https://github.com/gflohr/esgettext/issues';
10
10
  }
11
11
  static getVersion() {
12
- return '1.1.0';
12
+ return '1.3.0';
13
+ }
14
+ static getNpmRunAllVersion() {
15
+ return '^4.1.5';
13
16
  }
14
17
  }
15
18
  exports.Package = Package;
16
- //# sourceMappingURL=package.js.map
@@ -11,6 +11,8 @@ class JavaScriptParser extends parser_2.Parser {
11
11
  allowReturnOutsideFunction: true,
12
12
  allowSuperOutsideMethod: true,
13
13
  allowUndeclaredExports: true,
14
+ // Documented but not supported. FIXME! Maybe only missing in types.
15
+ // errorRecovery: true,
14
16
  sourceFilename: filename,
15
17
  plugins: [
16
18
  'flow',
@@ -24,4 +26,3 @@ class JavaScriptParser extends parser_2.Parser {
24
26
  }
25
27
  }
26
28
  exports.JavaScriptParser = JavaScriptParser;
27
- //# sourceMappingURL=javascript.js.map
@@ -38,6 +38,9 @@ class Parser {
38
38
  constructor(catalog, options = {}) {
39
39
  this.catalog = catalog;
40
40
  this.options = options;
41
+ this.filename = '';
42
+ this.errors = 0;
43
+ this.comments = [];
41
44
  this.keywords = {};
42
45
  (options.keyword || Parser.cookedDefaultKeywords()).forEach(keyword => {
43
46
  this.keywords[keyword.method] = keyword;
@@ -81,6 +84,7 @@ class Parser {
81
84
  filename,
82
85
  identifierName: null,
83
86
  };
87
+ // Find the offending character.
84
88
  for (let i = 0; i < pos; ++i) {
85
89
  if (buf[i] === 10) {
86
90
  ++loc.start.line;
@@ -105,6 +109,7 @@ class Parser {
105
109
  input = buf.toString();
106
110
  }
107
111
  else {
112
+ // Convert.
108
113
  try {
109
114
  input = (0, iconv_lite_1.decode)(buf, this.options.fromCode);
110
115
  }
@@ -136,11 +141,15 @@ class Parser {
136
141
  });
137
142
  }
138
143
  extractAllStrings(ast) {
144
+ // Step 1: Transform string concatenations into one string.
139
145
  (0, traverse_1.default)(ast, {
140
146
  StringLiteral: path => {
141
147
  this.concatStrings(path);
142
148
  },
143
149
  });
150
+ // Step 2: Extract the remaining strings. Those that are part of a
151
+ // binary expression have not been recognized in step 1 and must be
152
+ // ignored.
144
153
  (0, traverse_1.default)(ast, {
145
154
  StringLiteral: path => {
146
155
  if (!t.isBinaryExpression(path.parentPath.node)) {
@@ -165,7 +174,7 @@ class Parser {
165
174
  return true;
166
175
  }
167
176
  checkInstance(instance) {
168
- if (!this.options.instance) {
177
+ if (!this.instances) {
169
178
  return true;
170
179
  }
171
180
  for (let i = 0; i < this.instances.length; ++i) {
@@ -197,6 +206,7 @@ class Parser {
197
206
  if (!Object.prototype.hasOwnProperty.call(this.keywords, method)) {
198
207
  return;
199
208
  }
209
+ // Enough arguments?
200
210
  const keywordSpec = this.keywords[method];
201
211
  if (keywordSpec.totalArgs &&
202
212
  path.node.arguments.length !== keywordSpec.totalArgs) {
@@ -347,12 +357,14 @@ class Parser {
347
357
  else if (t.isMemberExpression(me.object) &&
348
358
  t.isIdentifier(me.property) &&
349
359
  !me.computed) {
360
+ // Recurse.
350
361
  instance.push(me.property.name);
351
362
  return this.methodFromMemberExpression(me.object, instance);
352
363
  }
353
364
  else if (t.isMemberExpression(me.object) &&
354
365
  t.isLiteral(me.property) &&
355
366
  me.computed) {
367
+ // Recurse.
356
368
  instance.push(this.literalValue(me.property));
357
369
  return this.methodFromMemberExpression(me.object, instance);
358
370
  }
@@ -376,6 +388,8 @@ class Parser {
376
388
  }
377
389
  findPrecedingComments(loc) {
378
390
  let last;
391
+ // Find the last relevant comment, which is the first one that
392
+ // immediately precedes the location.
379
393
  for (last = 0; last < this.comments.length; ++last) {
380
394
  const commentLocation = this.comments[last].loc;
381
395
  if (commentLocation.end.line === loc.start.line ||
@@ -391,6 +405,7 @@ class Parser {
391
405
  this.comments.splice(0, this.comments.length);
392
406
  return [];
393
407
  }
408
+ // Now go back and find all adjacent comments.
394
409
  let ptr = this.comments[last].loc;
395
410
  const preceding = this.comments.splice(0, last + 1);
396
411
  if (!last) {
@@ -476,6 +491,7 @@ class Parser {
476
491
  console.error(gtx._x('{location}: Error: {msg}', { location, msg }));
477
492
  }
478
493
  canonicalizeEncoding(encoding) {
494
+ // This is taken from iconv-lite.
479
495
  const canonical = ('' + encoding)
480
496
  .toLowerCase()
481
497
  .replace(/:[0-9]{4}$|[^0-9a-z]/g, '');
@@ -592,4 +608,3 @@ class Parser {
592
608
  }
593
609
  }
594
610
  exports.Parser = Parser;
595
- //# sourceMappingURL=parser.js.map
package/dist/parser/po.js CHANGED
@@ -7,6 +7,26 @@ const entry_1 = require("../pot/entry");
7
7
  const parser_1 = require("./parser");
8
8
  const gtx = runtime_1.Textdomain.getInstance('tools');
9
9
  class PoParser extends parser_1.Parser {
10
+ constructor() {
11
+ super(...arguments);
12
+ // All those get reset on each call to parse().
13
+ this.entry = undefined;
14
+ this.loc = undefined;
15
+ this.entryLoc = undefined;
16
+ this.msgType = undefined;
17
+ this.seen = {};
18
+ }
19
+ /**
20
+ * Parse a po file into a catalog. This parser is very forgiving and
21
+ * accepts input that actually does not follow the standard in certain
22
+ * areas.
23
+ *
24
+ * The encoding will always be read from the PO header if present.
25
+ *
26
+ * @param input - the content of the po file
27
+ * @param filename - the filename
28
+ * @param encoding - an optional encoding
29
+ */
10
30
  parse(buf, filename, encoding) {
11
31
  if (typeof encoding !== 'undefined') {
12
32
  if (!(0, iconv_lite_1.encodingExists)(encoding)) {
@@ -15,6 +35,7 @@ class PoParser extends parser_1.Parser {
15
35
  }
16
36
  }
17
37
  const input = typeof encoding === 'undefined' ? buf.toString() : (0, iconv_lite_1.decode)(buf, encoding);
38
+ // Reset parser.
18
39
  this.entry = undefined;
19
40
  this.filename = filename;
20
41
  this.loc = {
@@ -34,6 +55,8 @@ class PoParser extends parser_1.Parser {
34
55
  this.msgType = undefined;
35
56
  this.seen = {};
36
57
  this.errors = 0;
58
+ // We cannot use forEach here because we may have to return from
59
+ // inside the loop.
37
60
  const lines = input.split('\n');
38
61
  for (let i = 0; i < lines.length; ++i) {
39
62
  const line = lines[i];
@@ -48,6 +71,9 @@ class PoParser extends parser_1.Parser {
48
71
  if (charset &&
49
72
  (typeof encoding === 'undefined' ||
50
73
  charset.toLowerCase() !== encoding.toLowerCase())) {
74
+ // FIXME! This must only happen, if the header is the first
75
+ // entry that has been added. Otherwise, we'll add the entries
76
+ // before this, twice.
51
77
  return this.parse(buf, filename, charset);
52
78
  }
53
79
  }
@@ -99,6 +125,9 @@ class PoParser extends parser_1.Parser {
99
125
  if (charset &&
100
126
  (typeof encoding === 'undefined' ||
101
127
  charset.toLowerCase() !== encoding.toLowerCase())) {
128
+ // FIXME! This must only happen, if the header is the first
129
+ // entry that has been added. Otherwise, we'll add the entries
130
+ // before this, twice.
102
131
  return this.parse(buf, filename, charset);
103
132
  }
104
133
  }
@@ -106,9 +135,11 @@ class PoParser extends parser_1.Parser {
106
135
  if (this.errors) {
107
136
  return false;
108
137
  }
138
+ // FIXME! This must go into the caller!
109
139
  this.catalog.makePOT();
110
140
  return true;
111
141
  }
142
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
112
143
  doParse(_input, _filename) {
113
144
  throw new Error('not implemented');
114
145
  }
@@ -150,6 +181,7 @@ class PoParser extends parser_1.Parser {
150
181
  const msgctxt = this.entry.properties.msgctxt;
151
182
  const msgid = this.entry.properties.msgid;
152
183
  if (typeof msgid === 'undefined') {
184
+ // TRANSLATORS: Do not translate "msgid".
153
185
  this.error(gtx._('missing "msgid" section'), this.loc);
154
186
  return;
155
187
  }
@@ -275,6 +307,7 @@ class PoParser extends parser_1.Parser {
275
307
  retval = '\r';
276
308
  break;
277
309
  default:
310
+ // We have to take the leading quote into account.
278
311
  this.loc.start.column += offset + 1;
279
312
  this.error(gtx._('invalid control sequence'), this.loc);
280
313
  retval = '';
@@ -298,6 +331,7 @@ class PoParser extends parser_1.Parser {
298
331
  this.entry.addToMsgctxt(msg);
299
332
  break;
300
333
  default:
334
+ // Ignore plural translations.
301
335
  break;
302
336
  }
303
337
  }
@@ -374,4 +408,3 @@ class PoParser extends parser_1.Parser {
374
408
  }
375
409
  }
376
410
  exports.PoParser = PoParser;
377
- //# sourceMappingURL=po.js.map
@@ -11,6 +11,8 @@ class TypeScriptParser extends parser_2.Parser {
11
11
  allowReturnOutsideFunction: true,
12
12
  allowSuperOutsideMethod: true,
13
13
  allowUndeclaredExports: true,
14
+ // Documented but not supported. FIXME! Maybe only missing in types.
15
+ // errorRecovery: true,
14
16
  sourceFilename: filename,
15
17
  plugins: [
16
18
  'typescript',
@@ -25,4 +27,3 @@ class TypeScriptParser extends parser_2.Parser {
25
27
  }
26
28
  }
27
29
  exports.TypeScriptParser = TypeScriptParser;
28
- //# sourceMappingURL=typescript.js.map
@@ -2,6 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Catalog = void 0;
4
4
  const entry_1 = require("./entry");
5
+ /**
6
+ * An entire message catalog that is subsequently filled.
7
+ */
5
8
  class Catalog {
6
9
  constructor(properties = {}) {
7
10
  this.properties = properties;
@@ -26,6 +29,7 @@ class Catalog {
26
29
  }
27
30
  if (typeof properties.date === 'undefined') {
28
31
  const now = new Date();
32
+ // Avoid if/else, so we do not spoil our test coverage. :)
29
33
  let year = now.getFullYear().toString();
30
34
  year = '0'.repeat(4 - year.length) + year;
31
35
  let month = (1 + now.getMonth()).toString();
@@ -36,6 +40,7 @@ class Catalog {
36
40
  hour = '0'.repeat(2 - hour.length) + hour;
37
41
  let minutes = now.getMinutes().toString();
38
42
  minutes = '0'.repeat(2 - minutes.length) + minutes;
43
+ // Do not depend on the timezone for test coverage.
39
44
  let offset = now.getTimezoneOffset();
40
45
  const sign = ['+', '-'][Math.sign(offset) + 1];
41
46
  offset = Math.abs(offset);
@@ -85,6 +90,17 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
85
90
  });
86
91
  this.addEntry(headerEntry);
87
92
  }
93
+ /**
94
+ * Render the entire catalog.
95
+ *
96
+ * @param renderOptions - options for rendering
97
+ *
98
+ * The following options are supported:
99
+ *
100
+ * width: wrap lines to that page width (default: 76)
101
+ *
102
+ * @returns the catalog rendered as a po(t) file
103
+ */
88
104
  toString(options = {}) {
89
105
  const width = options && typeof options.width !== 'undefined' ? options.width : 76;
90
106
  const isNotHeader = (entry) => {
@@ -111,6 +127,9 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
111
127
  }
112
128
  const actx = a.properties.msgctxt;
113
129
  const bctx = b.properties.msgctxt;
130
+ // It is impossible that both msgctxts are undefined
131
+ // because that would mean that the msgids are identical
132
+ // which is prevented.
114
133
  if (typeof bctx === 'undefined') {
115
134
  return +1;
116
135
  }
@@ -130,6 +149,7 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
130
149
  const filename = parts.join(':');
131
150
  return { filename, lineno };
132
151
  };
152
+ // First order all references
133
153
  copy.entries.forEach(entry => {
134
154
  if (entry.properties.references) {
135
155
  entry.properties.references = entry.properties.references
@@ -183,6 +203,13 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
183
203
  return header || body || '';
184
204
  }
185
205
  }
206
+ /**
207
+ * Add an entry to the catalog. If an entry with the same msgid
208
+ * and msgctxt already exists, the entry is merged into
209
+ * the existing one instead.
210
+ *
211
+ * @param entry - the `POTEntry` to add
212
+ */
186
213
  addEntry(entry) {
187
214
  const msgid = entry.properties.msgid;
188
215
  const msgctxt = entry.properties.msgctxt;
@@ -208,11 +235,20 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
208
235
  delete this.cache[msgid][msgctxt];
209
236
  this.entries = this.entries.filter(other => other !== entry);
210
237
  }
238
+ /**
239
+ * Copy a catalog with other options. This is for testing only.
240
+ *
241
+ * @returns a deep copy of the catalog.
242
+ */
211
243
  copy(properties) {
212
244
  const other = new Catalog(properties);
213
245
  this.entries.forEach(entry => other.addEntry(entry));
214
246
  return other;
215
247
  }
248
+ /**
249
+ * Removes all translations from a catalog, so that it can be used as
250
+ * a .pot file.
251
+ */
216
252
  makePOT() {
217
253
  this.entries.forEach(entry => {
218
254
  if (!(entry.properties.msgid === '' &&
@@ -223,4 +259,3 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
223
259
  }
224
260
  }
225
261
  exports.Catalog = Catalog;
226
- //# sourceMappingURL=catalog.js.map