@lingui/cli 5.3.2 → 5.4.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.
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.extractFromFiles = extractFromFiles;
7
- const chalk_1 = __importDefault(require("chalk"));
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const extractors_1 = __importDefault(require("../extractors"));
10
10
  const utils_1 = require("../utils");
@@ -23,7 +23,7 @@ function mergePlaceholders(prev, next) {
23
23
  async function extractFromFiles(paths, config) {
24
24
  const messages = {};
25
25
  let catalogSuccess = true;
26
- for (const filename of paths) {
26
+ await Promise.all(paths.map(async (filename) => {
27
27
  const fileSuccess = await (0, extractors_1.default)(filename, (next) => {
28
28
  var _a;
29
29
  if (!messages[next.id]) {
@@ -42,18 +42,18 @@ async function extractFromFiles(paths, config) {
42
42
  : "";
43
43
  const origin = [filename, next.origin[1]];
44
44
  if (prev.message && next.message && prev.message !== next.message) {
45
- throw new Error(`Encountered different default translations for message ${chalk_1.default.yellow(next.id)}` +
46
- `\n${chalk_1.default.yellow((0, utils_1.prettyOrigin)(prev.origin))} ${prev.message}` +
47
- `\n${chalk_1.default.yellow((0, utils_1.prettyOrigin)([origin]))} ${next.message}`);
45
+ throw new Error(`Encountered different default translations for message ${picocolors_1.default.yellow(next.id)}` +
46
+ `\n${picocolors_1.default.yellow((0, utils_1.prettyOrigin)(prev.origin))} ${prev.message}` +
47
+ `\n${picocolors_1.default.yellow((0, utils_1.prettyOrigin)([origin]))} ${next.message}`);
48
48
  }
49
49
  messages[next.id] = Object.assign(Object.assign({}, prev), { message: (_a = prev.message) !== null && _a !== void 0 ? _a : next.message, comments: next.comment
50
- ? [...prev.comments, next.comment]
51
- : prev.comments, origin: [...prev.origin, [filename, next.origin[1]]], placeholders: mergePlaceholders(prev.placeholders, next.placeholders) });
50
+ ? [...prev.comments, next.comment].sort()
51
+ : prev.comments, origin: [...prev.origin, [filename, next.origin[1]]].sort((a, b) => a[0].localeCompare(b[0])), placeholders: mergePlaceholders(prev.placeholders, next.placeholders) });
52
52
  }, config, {
53
53
  extractors: config.extractors,
54
54
  });
55
55
  catalogSuccess && (catalogSuccess = fileSuccess);
56
- }
56
+ }));
57
57
  if (!catalogSuccess)
58
58
  return undefined;
59
59
  return messages;
@@ -34,10 +34,12 @@ class Catalog {
34
34
  this.format.getCatalogExtension());
35
35
  }
36
36
  async make(options) {
37
- const nextCatalog = await this.collect({ files: options.files });
37
+ const [nextCatalog, prevCatalogs] = await Promise.all([
38
+ this.collect({ files: options.files }),
39
+ this.readAll(),
40
+ ]);
38
41
  if (!nextCatalog)
39
42
  return false;
40
- const prevCatalogs = await this.readAll();
41
43
  const catalogs = this.merge(prevCatalogs, nextCatalog, {
42
44
  overwrite: options.overwrite,
43
45
  files: options.files,
@@ -46,7 +46,9 @@ function createCompiledCatalog(locale, messages, options) {
46
46
  const { strict = false, namespace = "cjs", pseudoLocale, compilerBabelOptions = {}, } = options;
47
47
  const shouldPseudolocalize = locale === pseudoLocale;
48
48
  const errors = [];
49
- const compiledMessages = Object.keys(messages).reduce((obj, key) => {
49
+ const compiledMessages = Object.keys(messages)
50
+ .sort()
51
+ .reduce((obj, key) => {
50
52
  // Don't use `key` as a fallback translation in strict mode.
51
53
  const translation = (messages[key] || (!strict ? key : ""));
52
54
  try {
@@ -5,9 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createMissingErrorMessage = createMissingErrorMessage;
7
7
  exports.createCompilationErrorMessage = createCompilationErrorMessage;
8
- const chalk_1 = __importDefault(require("chalk"));
8
+ const picocolors_1 = __importDefault(require("picocolors"));
9
9
  function createMissingErrorMessage(locale, missingMessages, configurationMsg) {
10
- let message = `Failed to compile catalog for locale ${chalk_1.default.bold(locale)}!
10
+ let message = `Failed to compile catalog for locale ${picocolors_1.default.bold(locale)}!
11
11
 
12
12
  Missing ${missingMessages.length} translation(s):
13
13
  \n`;
@@ -20,7 +20,7 @@ Missing ${missingMessages.length} translation(s):
20
20
  return message;
21
21
  }
22
22
  function createCompilationErrorMessage(locale, errors) {
23
- let message = `Failed to compile catalog for locale ${chalk_1.default.bold(locale)}!
23
+ let message = `Failed to compile catalog for locale ${picocolors_1.default.bold(locale)}!
24
24
 
25
25
  Compilation error for ${errors.length} translation(s):
26
26
  \n`;
package/dist/api/stats.js CHANGED
@@ -8,7 +8,7 @@ exports.printStats = printStats;
8
8
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
9
9
  // @ts-ignore
10
10
  const cli_table_1 = __importDefault(require("cli-table"));
11
- const chalk_1 = __importDefault(require("chalk"));
11
+ const picocolors_1 = __importDefault(require("picocolors"));
12
12
  function getStats(catalog) {
13
13
  return [
14
14
  Object.keys(catalog).length,
@@ -33,7 +33,7 @@ function printStats(config, catalogs) {
33
33
  // was not extracted due to a `--locale` filter
34
34
  const [all, translated] = catalog ? getStats(catalog) : ["-", "-"];
35
35
  if (config.sourceLocale === locale) {
36
- table.push({ [`${chalk_1.default.bold(locale)} (source)`]: [all, "-"] });
36
+ table.push({ [`${picocolors_1.default.bold(locale)} (source)`]: [all, "-"] });
37
37
  }
38
38
  else {
39
39
  table.push({ [locale]: [all, translated] });
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.writeCatalogs = writeCatalogs;
7
7
  exports.writeTemplate = writeTemplate;
8
8
  const resolveTemplatePath_1 = require("./resolveTemplatePath");
9
- const chalk_1 = __importDefault(require("chalk"));
9
+ const picocolors_1 = __importDefault(require("picocolors"));
10
10
  const resolveCatalogPath_1 = require("./resolveCatalogPath");
11
11
  const mergeCatalog_1 = require("../api/catalog/mergeCatalog");
12
12
  const stats_1 = require("../api/stats");
@@ -35,6 +35,6 @@ async function writeTemplate(params) {
35
35
  const catalogOutput = (0, resolveTemplatePath_1.resolveTemplatePath)(entryPoint, outputPattern, linguiConfig.rootDir, format.getTemplateExtension());
36
36
  await format.write(catalogOutput, cleanAndSort(messages, clean, linguiConfig.orderBy), undefined);
37
37
  return {
38
- statMessage: `${chalk_1.default.bold(Object.keys(messages).length)} message(s) extracted`,
38
+ statMessage: `${picocolors_1.default.bold(Object.keys(messages).length)} message(s) extracted`,
39
39
  };
40
40
  }
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.command = command;
7
- const chalk_1 = __importDefault(require("chalk"));
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
8
  const chokidar_1 = __importDefault(require("chokidar"));
9
9
  const commander_1 = require("commander");
10
10
  const conf_1 = require("@lingui/conf");
@@ -14,54 +14,70 @@ const api_1 = require("./api");
14
14
  const getCatalogs_1 = require("./api/catalog/getCatalogs");
15
15
  const normalize_path_1 = __importDefault(require("normalize-path"));
16
16
  const path_1 = __importDefault(require("path"));
17
+ class ProgramExit extends Error {
18
+ }
17
19
  async function command(config, options) {
18
20
  const catalogs = await (0, api_1.getCatalogs)(config);
19
21
  // Check config.compile.merge if catalogs for current locale are to be merged into a single compiled file
20
22
  const doMerge = !!config.catalogsMergePath;
21
- let mergedCatalogs = {};
22
23
  console.log("Compiling message catalogs…");
23
- for (const locale of config.locales) {
24
- for (const catalog of catalogs) {
25
- const { messages, missing: missingMessages } = await catalog.getTranslations(locale, {
26
- fallbackLocales: config.fallbackLocales,
27
- sourceLocale: config.sourceLocale,
28
- });
29
- if (!options.allowEmpty &&
30
- locale !== config.pseudoLocale &&
31
- missingMessages.length > 0) {
32
- console.error(chalk_1.default.red(`Error: Failed to compile catalog for locale ${chalk_1.default.bold(locale)}!`));
33
- if (options.verbose) {
34
- console.error(chalk_1.default.red("Missing translations:"));
35
- missingMessages.forEach((missing) => {
36
- const source = missing.source || missing.source === missing.id
37
- ? `: (${missing.source})`
38
- : "";
39
- console.error(`${missing.id}${source}`);
40
- });
41
- }
42
- else {
43
- console.error(chalk_1.default.red(`Missing ${missingMessages.length} translation(s)`));
44
- }
45
- console.error();
46
- return false;
24
+ let errored = false;
25
+ await Promise.all(config.locales.map(async (locale) => {
26
+ try {
27
+ await compileLocale(locale, catalogs, options, config, doMerge);
28
+ }
29
+ catch (err) {
30
+ if (err instanceof ProgramExit) {
31
+ errored = true;
47
32
  }
48
- if (doMerge) {
49
- mergedCatalogs = Object.assign(Object.assign({}, mergedCatalogs), messages);
33
+ else {
34
+ throw err;
35
+ }
36
+ }
37
+ }));
38
+ return !errored;
39
+ }
40
+ async function compileLocale(locale, catalogs, options, config, doMerge) {
41
+ let mergedCatalogs = {};
42
+ await Promise.all(catalogs.map(async (catalog) => {
43
+ const { messages, missing: missingMessages } = await catalog.getTranslations(locale, {
44
+ fallbackLocales: config.fallbackLocales,
45
+ sourceLocale: config.sourceLocale,
46
+ });
47
+ if (!options.allowEmpty &&
48
+ locale !== config.pseudoLocale &&
49
+ missingMessages.length > 0) {
50
+ console.error(picocolors_1.default.red(`Error: Failed to compile catalog for locale ${picocolors_1.default.bold(locale)}!`));
51
+ if (options.verbose) {
52
+ console.error(picocolors_1.default.red("Missing translations:"));
53
+ missingMessages.forEach((missing) => {
54
+ const source = missing.source || missing.source === missing.id
55
+ ? `: (${missing.source})`
56
+ : "";
57
+ console.error(`${missing.id}${source}`);
58
+ });
50
59
  }
51
60
  else {
52
- if (!(await compileAndWrite(locale, config, options, catalog, messages))) {
53
- return false;
54
- }
61
+ console.error(picocolors_1.default.red(`Missing ${missingMessages.length} translation(s)`));
55
62
  }
63
+ console.error();
64
+ throw new ProgramExit();
56
65
  }
57
66
  if (doMerge) {
58
- const result = await compileAndWrite(locale, config, options, await (0, getCatalogs_1.getCatalogForMerge)(config), mergedCatalogs);
59
- if (!result) {
60
- return false;
67
+ mergedCatalogs = Object.assign(Object.assign({}, mergedCatalogs), messages);
68
+ }
69
+ else {
70
+ if (!(await compileAndWrite(locale, config, options, catalog, messages))) {
71
+ throw new ProgramExit();
61
72
  }
62
73
  }
74
+ }));
75
+ if (doMerge) {
76
+ const result = await compileAndWrite(locale, config, options, await (0, getCatalogs_1.getCatalogForMerge)(config), mergedCatalogs);
77
+ if (!result) {
78
+ throw new ProgramExit();
79
+ }
63
80
  }
64
- return true;
65
81
  }
66
82
  async function compileAndWrite(locale, config, options, catalogToWrite, messages) {
67
83
  const namespace = options.typescript
@@ -77,17 +93,17 @@ async function compileAndWrite(locale, config, options, catalogToWrite, messages
77
93
  let message = (0, api_1.createCompilationErrorMessage)(locale, errors);
78
94
  if (options.failOnCompileError) {
79
95
  message += `These errors fail command execution because \`--strict\` option passed`;
80
- console.error(chalk_1.default.red(message));
96
+ console.error(picocolors_1.default.red(message));
81
97
  return false;
82
98
  }
83
99
  else {
84
100
  message += `You can fail command execution on these errors by passing \`--strict\` option`;
85
- console.error(chalk_1.default.red(message));
101
+ console.error(picocolors_1.default.red(message));
86
102
  }
87
103
  }
88
104
  let compiledPath = await catalogToWrite.writeCompiled(locale, compiledCatalog, namespace);
89
105
  compiledPath = (0, normalize_path_1.default)(path_1.default.relative(config.rootDir, compiledPath));
90
- options.verbose && console.error(chalk_1.default.green(`${locale} ⇒ ${compiledPath}`));
106
+ options.verbose && console.error(picocolors_1.default.green(`${locale} ⇒ ${compiledPath}`));
91
107
  return true;
92
108
  }
93
109
  if (require.main === module) {
@@ -135,7 +151,7 @@ if (require.main === module) {
135
151
  };
136
152
  // Check if Watch Mode is enabled
137
153
  if (options.watch) {
138
- console.info(chalk_1.default.bold("Initializing Watch Mode..."));
154
+ console.info(picocolors_1.default.bold("Initializing Watch Mode..."));
139
155
  (async function initWatch() {
140
156
  const format = await (0, api_1.getFormat)(config.format, config.formatOptions, config.sourceLocale);
141
157
  const catalogs = await (0, api_1.getCatalogs)(config);
@@ -151,7 +167,7 @@ if (require.main === module) {
151
167
  persistent: true,
152
168
  });
153
169
  const onReady = () => {
154
- console.info(chalk_1.default.green.bold("Watcher is ready!"));
170
+ console.info(picocolors_1.default.green(picocolors_1.default.bold("Watcher is ready!")));
155
171
  watcher
156
172
  .on("add", () => dispatchCompile())
157
173
  .on("change", () => dispatchCompile());
@@ -15,7 +15,7 @@ const normalize_path_1 = __importDefault(require("normalize-path"));
15
15
  const bundleSource_1 = require("./extract-experimental/bundleSource");
16
16
  const writeCatalogs_1 = require("./extract-experimental/writeCatalogs");
17
17
  const getEntryPoints_1 = require("./extract-experimental/getEntryPoints");
18
- const chalk_1 = __importDefault(require("chalk"));
18
+ const picocolors_1 = __importDefault(require("picocolors"));
19
19
  const babel_1 = require("./api/extractors/babel");
20
20
  async function command(linguiConfig, options) {
21
21
  var _a;
@@ -24,7 +24,7 @@ async function command(linguiConfig, options) {
24
24
  if (!config) {
25
25
  throw new Error("The configuration for experimental extractor is empty. Please read the docs.");
26
26
  }
27
- console.log(chalk_1.default.yellow([
27
+ console.log(picocolors_1.default.yellow([
28
28
  "You have using an experimental feature",
29
29
  "Experimental features are not covered by semver, and may cause unexpected or broken application behavior." +
30
30
  " Use at your own risk.",
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = command;
7
- const chalk_1 = __importDefault(require("chalk"));
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
8
  const commander_1 = require("commander");
9
9
  const conf_1 = require("@lingui/conf");
10
10
  const api_1 = require("./api");
@@ -23,7 +23,7 @@ async function command(config, options) {
23
23
  commandSuccess && (commandSuccess = Boolean(result));
24
24
  }));
25
25
  Object.entries(catalogStats).forEach(([key, value]) => {
26
- console.log(`Catalog statistics for ${chalk_1.default.bold(key)}: ${chalk_1.default.green(value)} messages`);
26
+ console.log(`Catalog statistics for ${picocolors_1.default.bold(key)}: ${picocolors_1.default.green(value)} messages`);
27
27
  console.log();
28
28
  });
29
29
  return commandSuccess;
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = command;
7
- const chalk_1 = __importDefault(require("chalk"));
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
8
  const chokidar_1 = __importDefault(require("chokidar"));
9
9
  const commander_1 = require("commander");
10
10
  const path_1 = __importDefault(require("path"));
@@ -20,11 +20,11 @@ async function command(config, options) {
20
20
  const catalogStats = {};
21
21
  let commandSuccess = true;
22
22
  const spinner = (0, ora_1.default)().start();
23
- for (const catalog of catalogs) {
23
+ await Promise.all(catalogs.map(async (catalog) => {
24
24
  const result = await catalog.make(Object.assign(Object.assign({}, options), { orderBy: config.orderBy }));
25
25
  catalogStats[(0, normalize_path_1.default)(path_1.default.relative(config.rootDir, catalog.path))] = result || {};
26
26
  commandSuccess && (commandSuccess = Boolean(result));
27
- }
27
+ }));
28
28
  if (commandSuccess) {
29
29
  spinner.succeed();
30
30
  }
@@ -37,8 +37,8 @@ async function command(config, options) {
37
37
  console.log();
38
38
  });
39
39
  if (!options.watch) {
40
- console.log(`(Use "${chalk_1.default.yellow((0, help_1.helpRun)("extract"))}" to update catalogs with new messages.)`);
41
- console.log(`(Use "${chalk_1.default.yellow((0, help_1.helpRun)("compile"))}" to compile catalogs for production. Alternatively, use bundler plugins: https://lingui.dev/ref/cli#compiling-catalogs-in-ci)`);
40
+ console.log(`(Use "${picocolors_1.default.yellow((0, help_1.helpRun)("extract"))}" to update catalogs with new messages.)`);
41
+ console.log(`(Use "${picocolors_1.default.yellow((0, help_1.helpRun)("compile"))}" to compile catalogs for production. Alternatively, use bundler plugins: https://lingui.dev/ref/cli#compiling-catalogs-in-ci)`);
42
42
  }
43
43
  // If service key is present in configuration, synchronize with cloud translation platform
44
44
  if (typeof config.service === "object" &&
@@ -83,18 +83,18 @@ if (require.main === module) {
83
83
  if (prevFormat && config.format === prevFormat) {
84
84
  hasErrors = true;
85
85
  console.error("Trying to migrate message catalog to the same format");
86
- console.error(`Set ${chalk_1.default.bold("new")} format in LinguiJS configuration\n` +
87
- ` and ${chalk_1.default.bold("previous")} format using --convert-from option.`);
86
+ console.error(`Set ${picocolors_1.default.bold("new")} format in LinguiJS configuration\n` +
87
+ ` and ${picocolors_1.default.bold("previous")} format using --convert-from option.`);
88
88
  console.log();
89
89
  console.log(`Example: Convert from lingui format to minimal`);
90
- console.log(chalk_1.default.yellow((0, help_1.helpRun)(`extract --convert-from lingui`)));
90
+ console.log(picocolors_1.default.yellow((0, help_1.helpRun)(`extract --convert-from lingui`)));
91
91
  process.exit(1);
92
92
  }
93
93
  if (options.locale) {
94
94
  const missingLocale = options.locale.find((l) => !config.locales.includes(l));
95
95
  if (missingLocale) {
96
96
  hasErrors = true;
97
- console.error(`Locale ${chalk_1.default.bold(missingLocale)} does not exist.`);
97
+ console.error(`Locale ${picocolors_1.default.bold(missingLocale)} does not exist.`);
98
98
  console.error();
99
99
  }
100
100
  }
@@ -132,7 +132,7 @@ if (require.main === module) {
132
132
  };
133
133
  // Check if Watch Mode is enabled
134
134
  if (options.watch) {
135
- console.info(chalk_1.default.bold("Initializing Watch Mode..."));
135
+ console.info(picocolors_1.default.bold("Initializing Watch Mode..."));
136
136
  (async function initWatch() {
137
137
  const catalogs = await (0, api_1.getCatalogs)(config);
138
138
  const paths = [];
@@ -146,7 +146,7 @@ if (require.main === module) {
146
146
  persistent: true,
147
147
  });
148
148
  const onReady = () => {
149
- console.info(chalk_1.default.green.bold("Watcher is ready!"));
149
+ console.info(picocolors_1.default.green(picocolors_1.default.bold("Watcher is ready!")));
150
150
  watcher
151
151
  .on("add", (path) => dispatchExtract([path]))
152
152
  .on("change", (path) => dispatchExtract([path]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingui/cli",
3
- "version": "5.3.2",
3
+ "version": "5.4.0",
4
4
  "description": "CLI for working wit message catalogs",
5
5
  "keywords": [
6
6
  "cli",
@@ -12,7 +12,12 @@
12
12
  "translation",
13
13
  "multilingual"
14
14
  ],
15
- "repository": "lingui/js-lingui",
15
+ "homepage": "https://lingui.dev",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/lingui/js-lingui.git",
19
+ "directory": "packages/cli"
20
+ },
16
21
  "bugs": "https://github.com/lingui/js-lingui/issues",
17
22
  "license": "MIT",
18
23
  "author": {
@@ -57,14 +62,12 @@
57
62
  "@babel/parser": "^7.22.0",
58
63
  "@babel/runtime": "^7.21.0",
59
64
  "@babel/types": "^7.21.2",
60
- "@lingui/babel-plugin-extract-messages": "5.3.2",
61
- "@lingui/babel-plugin-lingui-macro": "5.3.2",
62
- "@lingui/conf": "5.3.2",
63
- "@lingui/core": "5.3.2",
64
- "@lingui/format-po": "5.3.2",
65
- "@lingui/message-utils": "5.3.2",
66
- "babel-plugin-macros": "^3.0.1",
67
- "chalk": "^4.1.0",
65
+ "@lingui/babel-plugin-extract-messages": "5.4.0",
66
+ "@lingui/babel-plugin-lingui-macro": "5.4.0",
67
+ "@lingui/conf": "5.4.0",
68
+ "@lingui/core": "5.4.0",
69
+ "@lingui/format-po": "5.4.0",
70
+ "@lingui/message-utils": "5.4.0",
68
71
  "chokidar": "3.5.1",
69
72
  "cli-table": "^0.3.11",
70
73
  "commander": "^10.0.0",
@@ -72,12 +75,10 @@
72
75
  "date-fns": "^3.6.0",
73
76
  "esbuild": "^0.25.1",
74
77
  "glob": "^11.0.0",
75
- "inquirer": "^7.3.3",
76
78
  "micromatch": "^4.0.7",
77
79
  "normalize-path": "^3.0.0",
78
80
  "ora": "^5.1.0",
79
- "pathe": "^1.1.0",
80
- "pkg-up": "^3.1.0",
81
+ "picocolors": "^1.1.1",
81
82
  "pofile": "^1.1.4",
82
83
  "pseudolocale": "^2.0.0",
83
84
  "source-map": "^0.8.0-beta.0"
@@ -90,5 +91,5 @@
90
91
  "mock-fs": "^5.2.0",
91
92
  "mockdate": "^3.0.5"
92
93
  },
93
- "gitHead": "37f40ec18928b357c07a228947b2bf071e92449e"
94
+ "gitHead": "ce0d17bd0874f5f4f01fd073749f29087835a315"
94
95
  }