From c102ad8944eb7c66c8d2318d0a278916fcb36810 Mon Sep 17 00:00:00 2001 From: Zachary Dovel Date: Tue, 29 Jan 2019 21:53:52 -0800 Subject: [PATCH] Update versions. Add cli interface --- .editorconfig | 2 +- .gitignore | 2 + .travis.yml | 4 +- README.md | 72 +- example/src/README.md | 8 + example/src/index.js | 9 + package.json | 42 +- src/.babelrc.js | 5 +- src/.eslintrc.js | 45 +- src/README.md | 72 +- src/hasTranslation.js | 22 +- src/hasTranslation.test.js | 100 +- src/index.js | 924 +++---- src/isEscapeCharacter.js | 12 +- src/isLocalizationFunctionStart.js | 22 +- src/isLocalizationFunctionStart.test.js | 88 +- src/isQuoteCharacter.js | 8 +- src/isSubPath.js | 12 +- src/isSubPath.test.js | 24 +- src/isWhiteSpaceCharacter.js | 6 +- src/parseLocalizationFunction.js | 106 +- src/readCharacter.js | 322 +-- src/readCharacter.test.js | 1834 +++++++------- src/readString.error.test.js | 18 +- src/readString.js | 80 +- src/readString.test.js | 232 +- src/scrubLocalization.js | 14 +- src/scrubLocalization.test.js | 18 +- src/startsWith.js | 2 +- src/startsWith.test.js | 18 +- src/test.js | 1927 ++++++++------- src/update-translations.js | 87 + yarn.lock | 2920 ++++++++++------------- 33 files changed, 4437 insertions(+), 4620 deletions(-) create mode 100644 example/src/README.md create mode 100644 example/src/index.js create mode 100644 src/update-translations.js diff --git a/.editorconfig b/.editorconfig index 3ded83a..dcd0779 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,7 @@ insert_final_newline = true # Matches multiple files with brace expansion notation # Set default charset -[*.{js}] +[*.js] charset = utf-8 indent_style = space indent_size = 2 diff --git a/.gitignore b/.gitignore index e7ab49d..e471aee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ node_modules +locales +.locales build yarn-error.log documentation diff --git a/.travis.yml b/.travis.yml index 2281cfd..7890864 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,9 @@ language: node_js cache: yarn node_js: - - "6" -# - "7" NOT SUPPORTED BY fs-extra - "8" - - "9" - "10" + - "11" install: - yarn add --dev codecov snyk coveralls script: diff --git a/README.md b/README.md index 05bcdbe..d354fb3 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,10 @@ A library for scanning javscript files to build translation mappings in json aut ## Why use this? +- Automated code splittiing - You no longer have to manage hierarchies of translations -- Designed for architectures leveraging dynamic imports, allowing splitting of the translations based off of file structure +- Includes a handy commandline program called `update-translations` +- Designed for architectures leveraging dynamic imports - Templates are automatically generated for the translators where they only need to fill in the blanks - The translations are annoted if they are new or unused as well as the file names and line numbers of usages - Easy auditing for missing or non-updated translation strings with never running your application or enlisting QA @@ -39,7 +41,26 @@ yarn add @zakkudo/translation-static-analyzer ## Setup 1. Wrap strings you want to be translated in `__('text')` or `__n('singlular', 'plural', number)` or `__p('context', 'text')` or `__np('context', 'singular', 'plural', number)` using a library like `@zakkudo/translator` -2. Initialize the analyzer in your build scripts similar to below. +2. Initialize the analyzer in your build scripts similar to below: +``` console +$ npm install -g @zakkudo/translation-static-analyzer +$ update-translations --help +usage: update-translations [--help] [--version] [--watch] [--templates=path] [--target=glob] [--debug] [--locales=es,fr] ...source-files-glob + +A console application for updating gettext style translations in a javscript application. + + -h/--help Show this help information. + -V/--version Show the program version. + -w/--watch Update the translations as the files change. ctrl-c to quit. + --templates=path The output target of the developer centric translations. A 'locale' directory will be created in this localition. + --target=glob The output target of the developer centric translations. A '.locale' directory will be created in this location. + --debug Show debugging messages. + -l/--locales=es,fr The locales to generate translation templates for, comma separated. +$ update-translations --target src --locales fr --templates . --debug 'src/**/*.js' +``` + +or you can use the api directly, which is used to make `@zakkudo/translate-webpack-plugin` and other handy wrappers: + ``` javascript const TranslationStaticAnalyzer = require('@zakkudo/translation-static-analyzer'); const analyzer = new TransalationStaticAnalyzer({ @@ -137,14 +158,37 @@ document.body.innerHTML = __n('There is one user', 'There are %d users', 2); ## Examples +### Use the command-line program, using the git repository of this project +```console +# Install the command globally +$ npm install -g @zakkudo/translation-static-analyzer +# Copy the project +$ git clone https://github.com/zakkudo/translation-static-analyzer.git +$ cd translation-static-analyzer/example/src +# Check out the help for the fun of it +$ update-translations --help +usage: update-translations [--help] [--version] [--watch] [--templates=path] [--target=glob] [--debug] [--locales=es,fr] ...source-files-glob + +A console application for updating gettext style translations in a javscript application. + + -h/--help Show this help information. + -V/--version Show the program version. + -w/--watch Update the translations as the files change. ctrl-c to quit. + --templates=path The output target of the developer centric translations. A 'locale' directory will be created in this localition. + --target=glob The output target of the developer centric translations. A '.locale' directory will be created in this location. + --debug Show debugging messages. + -l/--locales=es,fr The locales to generate translation templates for, comma separated. +# Generate some translations +$ update-translations --locales=es,fr +# View what was created +$ ls .locales # For the developers +$ ls ../locales # For the translators +``` + ### Configure the analyzer to build a single `.locales` directory -``` javascript -const TranslationStaticAnalyzer = require('@zakkudo/translation-static-analyzer'); -const analyzer = new TransalationStaticAnalyzer({ - files: 'src/**/*.js', - locales: ['es', 'fr'], - target: 'src' -}); +``` console +$ npm install -g @zakkudo/translation-static-analyzer +$ update-translations --templates . --target src --locales es,fr 'src/**/*.js' ``` ``` @@ -165,13 +209,9 @@ File Structure ``` ### Configure the analyzer for a split `.locales` directory -``` javascript -const TranslationStaticAnalyzer = require('@zakkudo/translation-static-analyzer'); -const analyzer = new TransalationStaticAnalyzer({ - files: 'src/**/*.js', - locales: ['es', 'fr'], - target: 'src/pages/*' -}); +``` console +$ npm install -g @zakkudo/translation-static-analyzer +$ update-translations --templates . --target 'src/pages/*' --locales es,fr 'src/**/*.js' ``` ``` diff --git a/example/src/README.md b/example/src/README.md new file mode 100644 index 0000000..c3d201a --- /dev/null +++ b/example/src/README.md @@ -0,0 +1,8 @@ +Run + +```console +npm install -g @zakkudo/translation-static-analyzer +update-translations --locales fr,es +``` + +To see how translations are generated! There will be a `locales` directory generated in the parent directory and a `.locales` generated in the `src` directory. diff --git a/example/src/index.js b/example/src/index.js new file mode 100644 index 0000000..7ff9519 --- /dev/null +++ b/example/src/index.js @@ -0,0 +1,9 @@ + +import Translator from '@zakkudo/translator'; + +const translator = new Translator(); +const { __, __n } = translator; + +console.log(__('Lets see how this works!')); +console.log(__n("I'm going to eat %d apple!", "I'm going to eat %d apples!", 3)); + diff --git a/package.json b/package.json index ca34ad6..6cf1897 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@zakkudo/translation-static-analyzer", - "version": "0.2.2", - "description": "A library for generating localization files using static analysis of source files similar to gettext", + "version": "0.3.0", + "description": "A library for generating localization files using static analysis of source files similar to gettext with code splitting", "keywords": [ "gettext", "i18n", @@ -10,40 +10,48 @@ "localization", "localize", "translate", - "translation" + "translation", + "code splitting" ], "main": "index.js", "files": [ "*" ], + "bin": { + "update-translations": "update-translations.js" + }, "engines": { - "node": ">=6.0.0 <7.0.0 || >=8.0.0" + "node": ">=8.0.0" }, "repository": "github:zakkudo/translation-static-analyzer", "license": "BSD-3-Clause", "devDependencies": { - "@babel/cli": "^7.0.0-beta.56", - "@babel/core": "^7.0.0-beta.56", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/preset-env": "^7.0.0-beta.56", + "@babel/cli": "^7.2.3", + "@babel/core": "^7.2.2", + "@babel/plugin-transform-classes": "^7.2.2", + "@babel/plugin-transform-runtime": "^7.2.0", + "@babel/preset-env": "^7.0.0", "babel-core": "^7.0.0-0", - "babel-jest": "^23.4.2", + "babel-jest": "^24.0.0", + "babel-plugin-transform-define": "^1.3.1", "babel-plugin-transform-undefined-to-void": "^6.9.4", - "eslint": "^4.19.1", + "eslint": "^5.12.1", "eslint-plugin-jasmine": "^2.10.1", - "eslint-plugin-jest": "^21.21.0", - "eslint-plugin-node": "^7.0.1", - "jest": "^23.4.2", - "jest-cli": "^23.4.2", + "eslint-plugin-jest": "^22.1.3", + "eslint-plugin-node": "^8.0.1", + "jest": "^24.0.0", + "jest-cli": "^24.0.0", "jsdoc": "^3.5.5", "jsdoc-to-markdown": "^4.0.1" }, "dependencies": { - "@babel/runtime-corejs2": "^7.0.0", + "@babel/runtime-corejs2": "^7.3.1", + "@zakkudo/argument-parser": "0.0.1", + "chokidar": "^2.0.4", "deep-equal": "^1.0.1", - "fs-extra": "^7.0.0", + "fs-extra": "^7.0.1", "glob": "^7.1.2", - "json5": "^1.0.1", + "json5": "^2.1.0", "safe-eval": "^0.4.1" }, "scripts": { diff --git a/src/.babelrc.js b/src/.babelrc.js index 2391b07..a14c410 100644 --- a/src/.babelrc.js +++ b/src/.babelrc.js @@ -1,3 +1,5 @@ +const packageConfig = require('../package.json'); + module.exports = { "presets": [ [ @@ -13,7 +15,8 @@ module.exports = { ], "plugins": [ ["@babel/transform-runtime", {"corejs": 2}], - "transform-undefined-to-void" + "transform-undefined-to-void", + ["transform-define", {"__VERSION__": packageConfig.version}] ], minified: false, // When enabled, makes debuggers confused even with source maps comments: false diff --git a/src/.eslintrc.js b/src/.eslintrc.js index c942eb8..4d370e3 100644 --- a/src/.eslintrc.js +++ b/src/.eslintrc.js @@ -1,24 +1,27 @@ module.exports = { - "extends": [ - "eslint:recommended", - "plugin:node/recommended" - ], - "env": { - "jasmine": true, - "jest/globals": true - }, - "plugins": [ - "jasmine", - "jest" - ], - "parserOptions": { - "ecmaVersion": 6, - "ecmaFeatures": { - "experimentalObjectRestSpread": true - } - }, - "rules": { - 'max-len': ["error", { "code": 100, "comments": 120 }], - "no-console": "off" + "extends": [ + "eslint:recommended", + "plugin:node/recommended" + ], + "env": { + "jasmine": true, + "jest/globals": true + }, + "globals": { + "__VERSION__": true + }, + "plugins": [ + "jasmine", + "jest" + ], + "parserOptions": { + "ecmaVersion": 6, + "ecmaFeatures": { + "experimentalObjectRestSpread": true } + }, + "rules": { + 'max-len': ["error", { "code": 100, "comments": 120 }], + "no-console": "off" + } }; diff --git a/src/README.md b/src/README.md index d5cf17b..5319286 100644 --- a/src/README.md +++ b/src/README.md @@ -10,8 +10,10 @@ A library for scanning javscript files to build translation mappings in json aut ## Why use this? +- Automated code splittiing - You no longer have to manage hierarchies of translations -- Designed for architectures leveraging dynamic imports, allowing splitting of the translations based off of file structure +- Includes a handy commandline program called `update-translations` +- Designed for architectures leveraging dynamic imports - Templates are automatically generated for the translators where they only need to fill in the blanks - The translations are annoted if they are new or unused as well as the file names and line numbers of usages - Easy auditing for missing or non-updated translation strings with never running your application or enlisting QA @@ -39,7 +41,26 @@ yarn add @zakkudo/translation-static-analyzer ## Setup 1. Wrap strings you want to be translated in `__('text')` or `__n('singlular', 'plural', number)` or `__p('context', 'text')` or `__np('context', 'singular', 'plural', number)` using a library like `@zakkudo/translator` -2. Initialize the analyzer in your build scripts similar to below. +2. Initialize the analyzer in your build scripts similar to below: +``` console +$ npm install -g @zakkudo/translation-static-analyzer +$ update-translations --help +usage: update-translations [--help] [--version] [--watch] [--templates=path] [--target=glob] [--debug] [--locales=es,fr] ...source-files-glob + +A console application for updating gettext style translations in a javscript application. + + -h/--help Show this help information. + -V/--version Show the program version. + -w/--watch Update the translations as the files change. ctrl-c to quit. + --templates=path The output target of the developer centric translations. A 'locale' directory will be created in this localition. + --target=glob The output target of the developer centric translations. A '.locale' directory will be created in this location. + --debug Show debugging messages. + -l/--locales=es,fr The locales to generate translation templates for, comma separated. +$ update-translations --target src --locales fr --templates . --debug 'src/**/*.js' +``` + +or you can use the api directly, which is used to make `@zakkudo/translate-webpack-plugin` and other handy wrappers: + ``` javascript const TranslationStaticAnalyzer = require('@zakkudo/translation-static-analyzer'); const analyzer = new TransalationStaticAnalyzer({ @@ -137,14 +158,37 @@ document.body.innerHTML = __n('There is one user', 'There are %d users', 2); ## Examples +### Use the command-line program, using the git repository of this project +```console +# Install the command globally +$ npm install -g @zakkudo/translation-static-analyzer +# Copy the project +$ git clone https://github.com/zakkudo/translation-static-analyzer.git +$ cd translation-static-analyzer/example/src +# Check out the help for the fun of it +$ update-translations --help +usage: update-translations [--help] [--version] [--watch] [--templates=path] [--target=glob] [--debug] [--locales=es,fr] ...source-files-glob + +A console application for updating gettext style translations in a javscript application. + + -h/--help Show this help information. + -V/--version Show the program version. + -w/--watch Update the translations as the files change. ctrl-c to quit. + --templates=path The output target of the developer centric translations. A 'locale' directory will be created in this localition. + --target=glob The output target of the developer centric translations. A '.locale' directory will be created in this location. + --debug Show debugging messages. + -l/--locales=es,fr The locales to generate translation templates for, comma separated. +# Generate some translations +$ update-translations --locales=es,fr +# View what was created +$ ls .locales # For the developers +$ ls ../locales # For the translators +``` + ### Configure the analyzer to build a single `.locales` directory -``` javascript -const TranslationStaticAnalyzer = require('@zakkudo/translation-static-analyzer'); -const analyzer = new TransalationStaticAnalyzer({ - files: 'src/**/*.js', - locales: ['es', 'fr'], - target: 'src' -}); +``` console +$ npm install -g @zakkudo/translation-static-analyzer +$ update-translations --templates . --target src --locales es,fr 'src/**/*.js' ``` ``` @@ -166,13 +210,9 @@ File Structure ### Configure the analyzer for a split `.locales` directory -``` javascript -const TranslationStaticAnalyzer = require('@zakkudo/translation-static-analyzer'); -const analyzer = new TransalationStaticAnalyzer({ - files: 'src/**/*.js', - locales: ['es', 'fr'], - target: 'src/pages/*' -}); +``` console +$ npm install -g @zakkudo/translation-static-analyzer +$ update-translations --templates . --target 'src/pages/*' --locales es,fr 'src/**/*.js' ``` ``` diff --git a/src/hasTranslation.js b/src/hasTranslation.js index a52007b..803c80b 100644 --- a/src/hasTranslation.js +++ b/src/hasTranslation.js @@ -2,20 +2,20 @@ * @private */ function singularHasTranslation(data) { - return Boolean(data.length); + return Boolean(data.length); } /** * @private */ function pluralHasTranslation(data) { - return Object.values(data || {}).some((v) => { - if (Object(v) === v) { - return pluralHasTranslation(v); - } + return Object.values(data || {}).some((v) => { + if (Object(v) === v) { + return pluralHasTranslation(v); + } - return singularHasTranslation(v); - }); + return singularHasTranslation(v); + }); } /** @@ -26,9 +26,9 @@ function pluralHasTranslation(data) { * @private */ module.exports = function hasTranslation(data) { - if (typeof data === 'string') { - return singularHasTranslation(data); - } + if (typeof data === 'string') { + return singularHasTranslation(data); + } - return pluralHasTranslation(data); + return pluralHasTranslation(data); } diff --git a/src/hasTranslation.test.js b/src/hasTranslation.test.js index 8c94755..1ca699d 100644 --- a/src/hasTranslation.test.js +++ b/src/hasTranslation.test.js @@ -1,54 +1,54 @@ const hasTranslation = require('./hasTranslation'); describe('hasTranslation', () => { - it('returns true for empty object', () => { - expect(hasTranslation({})).toBe(false); - }); - - it('returns false for empty value', () => { - expect(hasTranslation({a: ''})).toBe(false); - }); - - it('returns true for value', () => { - expect(hasTranslation({a: 'b'})).toBe(true); - }); - - it('returns true for deep value', () => { - expect(hasTranslation({a: {b: 'c'}})).toBe(true); - }); - - it('returns false for emtpy deep value', () => { - expect(hasTranslation({a: {b: ''}})).toBe(false); - }); - - it('returns false for string', () => { - expect(hasTranslation('test text')).toBe(true); - }); - - it('returns true for plural form', () => { - expect(hasTranslation({ - "%d %s cat": { - "one": "%d %s cat", - "other": "%d %s cats" - }, - })).toEqual(true); - }); - - it('returns false for plural form when empty strings', () => { - expect(hasTranslation({ - "%d %s cat": { - "one": "", - "other": "" - }, - })).toEqual(false); - }); - - it('returns true for plural form even when one empty string', () => { - expect(hasTranslation({ - "%d %s cat": { - "one": "", - "other": "%d %s cats" - }, - })).toEqual(true); - }); + it('returns true for empty object', () => { + expect(hasTranslation({})).toBe(false); + }); + + it('returns false for empty value', () => { + expect(hasTranslation({a: ''})).toBe(false); + }); + + it('returns true for value', () => { + expect(hasTranslation({a: 'b'})).toBe(true); + }); + + it('returns true for deep value', () => { + expect(hasTranslation({a: {b: 'c'}})).toBe(true); + }); + + it('returns false for emtpy deep value', () => { + expect(hasTranslation({a: {b: ''}})).toBe(false); + }); + + it('returns false for string', () => { + expect(hasTranslation('test text')).toBe(true); + }); + + it('returns true for plural form', () => { + expect(hasTranslation({ + "%d %s cat": { + "one": "%d %s cat", + "other": "%d %s cats" + }, + })).toEqual(true); + }); + + it('returns false for plural form when empty strings', () => { + expect(hasTranslation({ + "%d %s cat": { + "one": "", + "other": "" + }, + })).toEqual(false); + }); + + it('returns true for plural form even when one empty string', () => { + expect(hasTranslation({ + "%d %s cat": { + "one": "", + "other": "%d %s cats" + }, + })).toEqual(true); + }); }); diff --git a/src/index.js b/src/index.js index 3b5da40..86a0114 100644 --- a/src/index.js +++ b/src/index.js @@ -13,7 +13,6 @@ const console = require('console'); const hasTranslation = require('./hasTranslation'); const readString = require('./readString'); const isSubPath = require('./isSubPath'); - const name = 'translation-static-analyzer'; @@ -21,207 +20,207 @@ const name = 'translation-static-analyzer'; * @private */ function toKeyWithContext(key, context = 'default') { - return `${querystring.escape(key)}:${querystring.escape(context)}`; + return `${querystring.escape(key)}:${querystring.escape(context)}`; } /** * @private */ function fromKeyWithContext(keyWithContext) { - const [key, value] = String(keyWithContext).split(':'); + const [key, value] = String(keyWithContext).split(':'); - return [ - querystring.unescape(key), - querystring.unescape(value), - ]; + return [ + querystring.unescape(key), + querystring.unescape(value), + ]; } /** * @private */ function __(key) { - return [toKeyWithContext(key), ""]; + return [toKeyWithContext(key), ""]; } /** * @private */ function __p(context, key) { - return [toKeyWithContext(key, context), ""]; + return [toKeyWithContext(key, context), ""]; } /** * @private */ function __n(singular) { - return [toKeyWithContext(singular), { - // Singular form placeholder - "1": "", - // Plural form placeholder - "2": "" - }]; + return [toKeyWithContext(singular), { + // Singular form placeholder + "1": "", + // Plural form placeholder + "2": "" + }]; } /** * @private */ function __np(context, singular) { - return [toKeyWithContext(singular, context), { - // Singular form placeholder - "1": "", - // Plural form placeholder - "2": "" - }]; + return [toKeyWithContext(singular, context), { + // Singular form placeholder + "1": "", + // Plural form placeholder + "2": "" + }]; } /** * @private */ function print(message, ...leftover) { - console.log(`${name}: ${message}`, ...leftover); + console.log(`${name}: ${message}`, ...leftover); } /** * @private */ function calculateTargetFiles(targetDirectories, all) { - const target = all.reduce((accumulator, a) => { - let unused = true; - - targetDirectories.forEach((t) => { - if (isSubPath(t, a)) { - if (!accumulator[t]) { - accumulator[t] = new Set([a]); - } else { - accumulator[t].add(a) - } - - unused = false; - } - }); + const target = all.reduce((accumulator, a) => { + let unused = true; - if (unused) { - targetDirectories.forEach((t) => { - if (!accumulator[t]) { - accumulator[t] = new Set([a]); - } else { - accumulator[t].add(a); - } - }); + targetDirectories.forEach((t) => { + if (isSubPath(t, a)) { + if (!accumulator[t]) { + accumulator[t] = new Set([a]); + } else { + accumulator[t].add(a) } - return accumulator; - }, {}); + unused = false; + } + }); - return Object.keys(target).reduce((accumulator, k) => { - return Object.assign({}, accumulator, { - [k]: [...target[k]].sort() - }); - }, {}); + if (unused) { + targetDirectories.forEach((t) => { + if (!accumulator[t]) { + accumulator[t] = new Set([a]); + } else { + accumulator[t].add(a); + } + }); + } + + return accumulator; + }, {}); + + return Object.keys(target).reduce((accumulator, k) => { + return Object.assign({}, accumulator, { + [k]: [...target[k]].sort() + }); + }, {}); } /** * @private */ function calculateFiles(requestFiles) { - const options = this.options; - const {files, target} = options; - const all = glob.sync(files).map((a) => path.resolve(a)); - const hasModifiedFiles = Boolean(requestFiles.length); - const allAsSet = new Set(all); - const modified = hasModifiedFiles ? requestFiles.filter((f) => allAsSet.has(f)) : all; - const removed = requestFiles.filter((f) => !allAsSet.has(f)); - const targetDirectories = glob.sync(target).filter((t) => fs.statSync(t).isDirectory()); - const filesByTargetDirectory = calculateTargetFiles(targetDirectories, all); - - return { - all, - modified: new Set([...this.files.modified, ...modified]), - removed: new Set([...this.files.removed, ...removed]), - target: { - targetDirectories, - filesByTargetDirectory, - }, - }; + const options = this.options; + const {files, target} = options; + const all = glob.sync(files).map((a) => path.resolve(a)); + const hasModifiedFiles = Boolean(requestFiles.length); + const allAsSet = new Set(all); + const modified = hasModifiedFiles ? requestFiles.filter((f) => allAsSet.has(f)) : all; + const removed = requestFiles.filter((f) => !allAsSet.has(f)); + const targetDirectories = glob.sync(target).filter((t) => fs.statSync(t).isDirectory()); + const filesByTargetDirectory = calculateTargetFiles(targetDirectories, all); + + return { + all, + modified: new Set([...this.files.modified, ...modified]), + removed: new Set([...this.files.removed, ...removed]), + target: { + targetDirectories, + filesByTargetDirectory, + }, + }; } /** * @private */ function serializeLocalizationWithMetaData(localizationWithMetadata) { - const templateDirectory = path.resolve(this.templateDirectory, '..'); - const translations = Object.values(localizationWithMetadata).map((t) => { - const usages = t.usages.map((u) => { - return `${path.relative(templateDirectory, u.filename)}:${u.lineNumber}`; - }).sort(); - - return Object.assign({}, t, {usages}); - }).sort((a, b) => { - return a.key.localeCompare(b.key) || a.context.localeCompare(b.context); - }); - const indent = ' '; - const lines = ['{']; - let previousKey = translations[0].key; - - /* - * EXAMPLE - * { - * "English": { - * // filename:number - * "default": "French" - * } - * } - * - */ - return translations.reduce((lines, t, i) => { - const {key, context, data, usages, note} = t; - const newLines = []; - - if (i === 0) { - newLines.push(`${indent}"${key}": {`); - } + const templateDirectory = path.resolve(this.templateDirectory, '..'); + const translations = Object.values(localizationWithMetadata).map((t) => { + const usages = t.usages.map((u) => { + return `${path.relative(templateDirectory, u.filename)}:${u.lineNumber}`; + }).sort(); + + return Object.assign({}, t, {usages}); + }).sort((a, b) => { + return a.key.localeCompare(b.key) || a.context.localeCompare(b.context); + }); + const indent = ' '; + const lines = ['{']; + let previousKey = translations[0].key; + + /* + * EXAMPLE + * { + * "English": { + * // filename:number + * "default": "French" + * } + * } + * + */ + return translations.reduce((lines, t, i) => { + const {key, context, data, usages, note} = t; + const newLines = []; + + if (i === 0) { + newLines.push(`${indent}"${key}": {`); + } - if (previousKey !== key) { - newLines.push(`${indent}},`); - newLines.push(`${indent}"${key}": {`); - } else if (i > 0) { - const length = lines.length; - const last = length - 1; + if (previousKey !== key) { + newLines.push(`${indent}},`); + newLines.push(`${indent}"${key}": {`); + } else if (i > 0) { + const length = lines.length; + const last = length - 1; - lines[last] = lines[last] + ','; - } + lines[last] = lines[last] + ','; + } - if (note) { - newLines.push(`${indent}${indent}// ${note.toUpperCase()}`); - } + if (note) { + newLines.push(`${indent}${indent}// ${note.toUpperCase()}`); + } - usages.forEach((u) => { - newLines.push(`${indent}${indent}// ${u}`); - }); + usages.forEach((u) => { + newLines.push(`${indent}${indent}// ${u}`); + }); - newLines.push(`${indent}${indent}"${context}": ${JSON.stringify(data)}`); + newLines.push(`${indent}${indent}"${context}": ${JSON.stringify(data)}`); - previousKey = key; + previousKey = key; - return lines.concat(newLines); - }, lines).concat([`${indent}}`, '}']).join('\n'); + return lines.concat(newLines); + }, lines).concat([`${indent}}`, '}']).join('\n'); } /** * @private */ function readJSON5FileWithFallback(filename, fallback = {}) { - let data = fallback; + let data = fallback; - try { - data = JSON5.parse(fs.readFileSync(filename)); - } catch (e) { - if (e.code !== 'ENOENT') { - throw e; - } + try { + data = JSON5.parse(fs.readFileSync(filename)); + } catch (e) { + if (e.code !== 'ENOENT') { + throw e; } + } - return data; + return data; } /** @@ -230,33 +229,33 @@ function readJSON5FileWithFallback(filename, fallback = {}) { * @private */ function flattenLocalization(localization) { - return Object.entries(localization).reduce((accumulator, [k, v]) => { - if (Object(v) === v) { - const translations = {}; + return Object.entries(localization).reduce((accumulator, [k, v]) => { + if (Object(v) === v) { + const translations = {}; - Object.entries(v).forEach(([context, translation]) => { - translations[toKeyWithContext(k, context)] = translation; - }); + Object.entries(v).forEach(([context, translation]) => { + translations[toKeyWithContext(k, context)] = translation; + }); - return Object.assign(accumulator, translations); - } + return Object.assign(accumulator, translations); + } - return accumulator; - }, {}); + return accumulator; + }, {}); } /** * @private */ function unflattenLocalization(localization) { - return Object.entries(localization).reduce((accumulator, [keyWithContext, translation]) => { - const [key, context] = fromKeyWithContext(keyWithContext); - const contexts = accumulator[key] || {}; + return Object.entries(localization).reduce((accumulator, [keyWithContext, translation]) => { + const [key, context] = fromKeyWithContext(keyWithContext); + const contexts = accumulator[key] || {}; - return Object.assign({}, accumulator, { - [key]: Object.assign({}, contexts, {[context]: translation}) - }); - }, {}); + return Object.assign({}, accumulator, { + [key]: Object.assign({}, contexts, {[context]: translation}) + }); + }, {}); } /** @@ -266,294 +265,296 @@ function unflattenLocalization(localization) { * @private */ function collapseLocalization(localization) { - return Object.entries(localization).reduce((accumulator, [key, contexts]) => { - const keys = new Set(Object.keys(contexts)); + return Object.entries(localization).reduce((accumulator, [key, contexts]) => { + const keys = new Set(Object.keys(contexts)); - if (keys.size === 1 && keys.has('default')) { - return Object.assign({}, accumulator, {[key]: contexts.default}); - } + if (keys.size === 1 && keys.has('default')) { + return Object.assign({}, accumulator, {[key]: contexts.default}); + } - return Object.assign({}, accumulator, {[key]: contexts}); - }, {}); + return Object.assign({}, accumulator, {[key]: contexts}); + }, {}); } /** * @private */ function readLocalization(locale) { - const directory = this.templateDirectory; - const filename = `${directory}/${locale}.json`; - const data = readJSON5FileWithFallback.call(this, filename); + const directory = this.templateDirectory; + const filename = `${directory}/${locale}.json`; + const data = readJSON5FileWithFallback.call(this, filename); - return flattenLocalization(data); + return flattenLocalization(data); } /** * @private */ function writeLocalizationWithMetadata(locale, localization) { - const directory = this.templateDirectory; - const filename = `${directory}/${locale}.json`; - const serialized = serializeLocalizationWithMetaData.call(this, localization); - const options = this.options; + const directory = this.templateDirectory; + const filename = `${directory}/${locale}.json`; + const serialized = serializeLocalizationWithMetaData.call(this, localization); + const options = this.options; - if (options.debug) { - print('Writing localization for', filename, localization); - } + if (options.debug) { + print('Writing localization for', filename, localization); + } - fs.writeFileSync(filename, serialized); + fs.writeFileSync(filename, serialized); } /** * @private */ function updateLocalization(localization) { - const template = this.referenceTemplate; - const usagesByKey = this.usagesByKey; - const keys = [ - ...new Set(Object.keys(localization).concat(Object.keys(template))) - ].sort(); - const fallbackFiles = new Set(); - - return keys.reduce((accumulator, k) => { - const usages = [...(usagesByKey.get(k) || fallbackFiles)].sort(); - - const localizationHasTranslation = hasTranslation(localization[k]); - const templateHasProperty = template.hasOwnProperty(k); - const [key, context] = fromKeyWithContext(k); - - if (!templateHasProperty && localizationHasTranslation) { - return Object.assign({}, accumulator, { - [k]: { - note: 'unused', - usages, - key, - context, - data: localization[k] - } - }); - } else if (templateHasProperty && !localizationHasTranslation) { - return Object.assign({}, accumulator, { - [k]: { - note: 'new', - usages, - key, - context, - data: template[k] - } - }); - } else if (templateHasProperty && localizationHasTranslation) { - return Object.assign({}, accumulator, { - [k]: { - usages, - key, - context, - data: localization[k] - } - }); + const template = this.referenceTemplate; + const usagesByKey = this.usagesByKey; + const keys = [ + ...new Set(Object.keys(localization).concat(Object.keys(template))) + ].sort(); + const fallbackFiles = new Set(); + + return keys.reduce((accumulator, k) => { + const usages = [...(usagesByKey.get(k) || fallbackFiles)].sort(); + + const localizationHasTranslation = hasTranslation(localization[k]); + const templateHasProperty = template.hasOwnProperty(k); + const [key, context] = fromKeyWithContext(k); + + if (!templateHasProperty && localizationHasTranslation) { + return Object.assign({}, accumulator, { + [k]: { + note: 'unused', + usages, + key, + context, + data: localization[k] } + }); + } else if (templateHasProperty && !localizationHasTranslation) { + return Object.assign({}, accumulator, { + [k]: { + note: 'new', + usages, + key, + context, + data: template[k] + } + }); + } else if (templateHasProperty && localizationHasTranslation) { + return Object.assign({}, accumulator, { + [k]: { + usages, + key, + context, + data: localization[k] + } + }); + } - return accumulator; - }, {}); + return accumulator; + }, {}); } /** * @private */ function stripMetadata(localizationWithMetadata) { - const pairs = Object.entries(localizationWithMetadata); + const pairs = Object.entries(localizationWithMetadata); - return pairs.reduce((accumulator, [keyWithContext, m]) => { - return Object.assign(accumulator, { - [keyWithContext]: m.data - }); - }, {}); + return pairs.reduce((accumulator, [keyWithContext, m]) => { + return Object.assign(accumulator, { + [keyWithContext]: m.data + }); + }, {}); } /** * @private */ function generateLocaleFiles() { - const options = this.options; - const locales = options.locales; - const previousLocalizationWithMetadataByLanguage = this.localizationWithMetadataByLanguage; - const localizationWithMetadataByLanguage = this.localizationWithMetadataByLanguage = new Map(); - const localizationByLanguage = this.localizationByLanguage = new Map(); - let changed = false; - - fs.ensureDirSync(this.templateDirectory); + const options = this.options; + const locales = options.locales; + const previousLocalizationWithMetadataByLanguage = this.localizationWithMetadataByLanguage; + const localizationWithMetadataByLanguage = this.localizationWithMetadataByLanguage = new Map(); + const localizationByLanguage = this.localizationByLanguage = new Map(); + let changed = false; + + fs.ensureDirSync(this.templateDirectory); + + locales.forEach((l) => { + const localizationWithMetadata = previousLocalizationWithMetadataByLanguage.get(l); + const localization = readLocalization.call(this, l); + const nextLocalizationWithMetadata = updateLocalization.call(this, localization); + const nextLocalization = stripMetadata(nextLocalizationWithMetadata) + const sourceCodeChangeUpdatedLocalization = !equal( + localizationWithMetadata, + nextLocalizationWithMetadata + ); + const translationChangeUpdatedLocalization = !equal( + localization, + nextLocalization + ); + + localizationByLanguage.set(l, nextLocalization); + localizationWithMetadataByLanguage.set(l, nextLocalizationWithMetadata); + + if (sourceCodeChangeUpdatedLocalization || translationChangeUpdatedLocalization || this.firstRun) { + writeLocalizationWithMetadata.call(this, l, nextLocalizationWithMetadata); + changed = true; + } + }); - locales.forEach((l) => { - const localizationWithMetadata = previousLocalizationWithMetadataByLanguage.get(l); - const localization = readLocalization.call(this, l); - const nextLocalizationWithMetadata = updateLocalization.call(this, localization); - const nextLocalization = stripMetadata(nextLocalizationWithMetadata) - const sourceCodeChangeUpdatedLocalization = !equal( - localizationWithMetadata, - nextLocalizationWithMetadata - ); - const translationChangeUpdatedLocalization = !equal( - localization, - nextLocalization - ); - - localizationByLanguage.set(l, nextLocalization); - localizationWithMetadataByLanguage.set(l, nextLocalizationWithMetadata); - - if (sourceCodeChangeUpdatedLocalization || translationChangeUpdatedLocalization) { - writeLocalizationWithMetadata.call(this, l, nextLocalizationWithMetadata); - changed = true; - } - }); + this.firstRun = false; - return changed; + return changed; } /** * @private */ function rebuildCache() { - const usagesByKey = this.usagesByKey = new Map(); - const keysByFilename = this.keysByFilename = new Map(); - const referenceTemplate = this.referenceTemplate = {}; - const options = this.options; - const sourceByFilename = this.sourceByFilename; - - this.files.all.forEach((m) => { - const contents = sourceByFilename.get(m); - const addedKeysWithContext = new Set(); - - if (contents && typeof contents === 'string') { - const metadata = readString(contents); - - Object.values(metadata).forEach((translations) => { - translations.forEach((t) => { - try { - const {lineNumber, fn} = t; - const [ - keyWithContext, - placeholderTranslation, - ] = safeEval(fn, {__, __n, __p, __np}); - - referenceTemplate[keyWithContext] = placeholderTranslation; - - addedKeysWithContext.add(keyWithContext); - - if (!usagesByKey.has(keyWithContext)) { - usagesByKey.set(keyWithContext, new Set()); - } - - usagesByKey.get(keyWithContext).add({ - filename: m, - lineNumber, - }); - } catch(e) { - console.warn(e); - } - }); + const usagesByKey = this.usagesByKey = new Map(); + const keysByFilename = this.keysByFilename = new Map(); + const referenceTemplate = this.referenceTemplate = {}; + const options = this.options; + const sourceByFilename = this.sourceByFilename; + + this.files.all.forEach((m) => { + const contents = sourceByFilename.get(m); + const addedKeysWithContext = new Set(); + + if (contents && typeof contents === 'string') { + const metadata = readString(contents); + + Object.values(metadata).forEach((translations) => { + translations.forEach((t) => { + try { + const {lineNumber, fn} = t; + const [ + keyWithContext, + placeholderTranslation, + ] = safeEval(fn, {__, __n, __p, __np}); + + referenceTemplate[keyWithContext] = placeholderTranslation; + + addedKeysWithContext.add(keyWithContext); + + if (!usagesByKey.has(keyWithContext)) { + usagesByKey.set(keyWithContext, new Set()); + } + + usagesByKey.get(keyWithContext).add({ + filename: m, + lineNumber, }); + } catch(e) { + console.warn(e); + } + }); + }); - } + } - keysByFilename.set(m, addedKeysWithContext); - }); + keysByFilename.set(m, addedKeysWithContext); + }); - if (options.debug) { - print('Parsed keys', JSON.stringify(Array.from(usagesByKey.keys()), null, 4)); - } + if (options.debug) { + print('Parsed keys', JSON.stringify(Array.from(usagesByKey.keys()), null, 4)); + } } /** * @private */ function loadSourceFiles() { - const {modified, removed} = this.files; - const sourceByFilename = this.sourceByFilename; - const keysByFilename = this.keysByFilename; - - modified.forEach((m) => { - try { - const contents = String(fs.readFileSync(m)); - sourceByFilename.set(m, contents); - } catch (e) { - sourceByFilename.delete(m); - keysByFilename.delete(m); - removed.add(m); - } - }); + const {modified, removed} = this.files; + const sourceByFilename = this.sourceByFilename; + const keysByFilename = this.keysByFilename; + + modified.forEach((m) => { + try { + const contents = String(fs.readFileSync(m)); + sourceByFilename.set(m, contents); + } catch (e) { + sourceByFilename.delete(m); + keysByFilename.delete(m); + removed.add(m); + } + }); } /** * @private */ function writeIndexTarget(targetDirectory, subLocalization) { - const directory = path.resolve(targetDirectory, '.locales'); - const filename = path.resolve(directory, `index.json`); + const directory = path.resolve(targetDirectory, '.locales'); + const filename = path.resolve(directory, `index.json`); - fs.writeFileSync(filename, JSON.stringify(subLocalization, null, 4)); + fs.writeFileSync(filename, JSON.stringify(subLocalization, null, 4)); } /** * @private */ function buildTargetLocalization(localization, filenames) { - const subLocalization = {}; - const keysByFilename = this.keysByFilename; + const subLocalization = {}; + const keysByFilename = this.keysByFilename; - filenames.forEach((f) => { - const keys = keysByFilename.get(f); + filenames.forEach((f) => { + const keys = keysByFilename.get(f); - keys.forEach((k) => { - if (localization.hasOwnProperty(k) && hasTranslation(localization[k])) { - subLocalization[k] = localization[k] - } - }); + keys.forEach((k) => { + if (localization.hasOwnProperty(k) && hasTranslation(localization[k])) { + subLocalization[k] = localization[k] + } }); + }); - return collapseLocalization(unflattenLocalization(subLocalization)); + return collapseLocalization(unflattenLocalization(subLocalization)); } /** * @private */ function writeToTargets() { - const options = this.options; - const locales = options.locales; - const filesByTargetDirectory = this.files.target.filesByTargetDirectory; - const targetDirectories = Object.keys(filesByTargetDirectory); - const localizationByLanguage = this.localizationByLanguage; - const aggregate = {}; - let localizationChanged = false; + const options = this.options; + const locales = options.locales; + const filesByTargetDirectory = this.files.target.filesByTargetDirectory; + const targetDirectories = Object.keys(filesByTargetDirectory); + const localizationByLanguage = this.localizationByLanguage; + const aggregate = {}; + let localizationChanged = false; - targetDirectories.forEach((t) => { - // This is intentionally a hidden directory. It should generally not be included - // with git. - const directory = path.resolve(t, '.locales'); - - fs.ensureDirSync(directory) - - locales.forEach((l) => { - const filenames = filesByTargetDirectory[t]; - const localization = localizationByLanguage.get(l); - const subLocalization = buildTargetLocalization.call(this, localization, filenames); - const filename = path.resolve(directory, `${l}.json`); - const previousSubLocalization = readJSON5FileWithFallback.call(this, filename); - - aggregate[l] = subLocalization; - - if (!equal(subLocalization, previousSubLocalization)) { - if (options.debug) { - print('Writing final target to ', filename); - } - localizationChanged = true; - fs.writeFileSync(filename, JSON.stringify(subLocalization, null, 4)); - } - }); + targetDirectories.forEach((t) => { + // This is intentionally a hidden directory. It should generally not be included + // with git. + const directory = path.resolve(t, '.locales'); - if (localizationChanged) { - writeIndexTarget(t, aggregate); + fs.ensureDirSync(directory) + + locales.forEach((l) => { + const filenames = filesByTargetDirectory[t]; + const localization = localizationByLanguage.get(l); + const subLocalization = buildTargetLocalization.call(this, localization, filenames); + const filename = path.resolve(directory, `${l}.json`); + const previousSubLocalization = readJSON5FileWithFallback.call(this, filename, null); + + aggregate[l] = subLocalization; + + if (!equal(subLocalization, previousSubLocalization)) { + if (options.debug) { + print('Writing final target to ', filename); } + localizationChanged = true; + fs.writeFileSync(filename, JSON.stringify(subLocalization, null, 4)); + } }); + + if (localizationChanged) { + writeIndexTarget(t, aggregate); + } + }); } /** @@ -561,133 +562,134 @@ function writeToTargets() { * localization templates. */ class TranslationStaticAnalyzer { - /** - * @param {Object} options - The modifiers for how the analyzer is run - * @param {String} options.files - A - * [glob pattern]{@link https://www.npmjs.com/package/glob} of the files to pull translations from - * @param {Boolean} [options.debug = false] - Show debugging information in the console - * @param {Array} [options.locales = []] - The locales to generate (eg fr, ja_JP, en) - * @param {String} [options.templates] - The location to store - * the translator translatable templates for each language. Defaults to - * making a `locales` directory in the current working directory - * @param {String} [options.target] - Where to write the final translations, which can be split between - * multiple directories for modularity. If there are no targets, no `.locales` directory will be generated anywhere. - */ - constructor(options) { - this.options = options || {}; - this.sourceByFilename = new Map(); - this.keysByFilename = new Map(); - this.usagesByKey = new Map(); - this.localizationByLanguage = new Map(); - this.localizationWithMetadataByLanguage = new Map(); - this.files = { - modified: new Set(), - removed: new Set(), - }; - this.files = calculateFiles.call(this, []); - this.files.modified = new Set(); - this.files.removed = new Set(); + /** + * @param {Object} options - The modifiers for how the analyzer is run + * @param {String} options.files - A + * [glob pattern]{@link https://www.npmjs.com/package/glob} of the files to pull translations from + * @param {Boolean} [options.debug = false] - Show debugging information in the console + * @param {Array} [options.locales = []] - The locales to generate (eg fr, ja_JP, en) + * @param {String} [options.templates] - The location to store + * the translator translatable templates for each language. Defaults to + * making a `locales` directory in the current working directory + * @param {String} [options.target] - Where to write the final translations, which can be split between + * multiple directories for modularity. If there are no targets, no `.locales` directory will be generated anywhere. + */ + constructor(options) { + this.options = options || {}; + this.sourceByFilename = new Map(); + this.keysByFilename = new Map(); + this.usagesByKey = new Map(); + this.localizationByLanguage = new Map(); + this.firstRun = true; + this.localizationWithMetadataByLanguage = new Map(); + this.files = { + modified: new Set(), + removed: new Set(), + }; + this.files = calculateFiles.call(this, []); + this.files.modified = new Set(); + this.files.removed = new Set(); + } + + /** + * Read changes from the source files and update the database stored in the current + * analyzer instance. No changes will be written to the templates and all reads are + * accumulative for the next write. Use the `requestFiles` option if you want to hook + * this method up to a file watcher which can supply a list of files that have changed. + * @param {Array} [requestFiles = []] - A subset of files from the + * `options.files` glob to read or non to reread all files. Any files that are supplied to this + * method that are not part of the `options.files` glob are simply ignored. + * @return {Boolean} True if some some of the modified files matches the + * file option passed on initialization + */ + read(requestFiles = []) { + const options = this.options; + const locales = options.locales || []; + const files = this.files = calculateFiles.call( + this, + requestFiles.map((m) => path.resolve(m)) + ) + + if (!locales.length) { + console.warn( + "This library isn't particularly useful " + + "if you don't request any locales to be generated." + ); + return; } - /** - * Read changes from the source files and update the database stored in the current - * analyzer instance. No changes will be written to the templates and all reads are - * accumulative for the next write. Use the `requestFiles` option if you want to hook - * this method up to a file watcher which can supply a list of files that have changed. - * @param {Array} [requestFiles = []] - A subset of files from the - * `options.files` glob to read or non to reread all files. Any files that are supplied to this - * method that are not part of the `options.files` glob are simply ignored. - * @return {Boolean} True if some some of the modified files matches the - * file option passed on initialization - */ - read(requestFiles = []) { - const options = this.options; - const locales = options.locales || []; - const files = this.files = calculateFiles.call( - this, - requestFiles.map((m) => path.resolve(m)) - ) - - if (!locales.length) { - console.warn( - "This library isn't particularly useful " + - "if you don't request any locales to be generated." - ); - return; - } - - if (options.debug) { - print('Updating localization keys for', files.modified); - } + if (options.debug) { + print('Updating localization keys for', files.modified); + } - if (files.removed.size) { - files.removed.forEach((f) => { - this.sourceByFilename.delete(f); - this.keysByFilename.delete(f); - }); - } + if (files.removed.size) { + files.removed.forEach((f) => { + this.sourceByFilename.delete(f); + this.keysByFilename.delete(f); + }); + } - if (files.modified.size) { - loadSourceFiles.call(this); - } + if (files.modified.size) { + loadSourceFiles.call(this); + } - rebuildCache.call(this); + rebuildCache.call(this); - return Boolean(files.modified.size || files.removed.size); - } + return Boolean(files.modified.size || files.removed.size); + } - /** - * Write the current database to the templates and targets. This method is - * useful to force an update of the targets if a - * language file template in `templateDirectory` is updated without - * updating a source file. - */ - write() { - const referenceTemplate = this.referenceTemplate; - - if (referenceTemplate && generateLocaleFiles.call(this)) { - writeToTargets.call(this); - } + /** + * Write the current database to the templates and targets. This method is + * useful to force an update of the targets if a + * language file template in `templateDirectory` is updated without + * updating a source file. + */ + write() { + const referenceTemplate = this.referenceTemplate; - this.files.modified = new Set(); - this.files.removed = new Set(); + if (referenceTemplate && generateLocaleFiles.call(this)) { + writeToTargets.call(this); } - /** - * Updates the translations to match the source files, using logic to try to reduce disk writes - * if no source files changed. This method was designed to be hooked up to a file watcher for the source - * code. *There will be no changes if this method is called after there is a manual change to the translation - * templates. It only cares about source files.* - * @param {Array} [requestFiles = []] - The files or none to - * update everything in the options.files glob pattern. - */ - update(requestFiles = []) { - const options = this.options; - - if (this.read(requestFiles)) { - this.write(); - } + this.files.modified = new Set(); + this.files.removed = new Set(); + } + + /** + * Updates the translations to match the source files, using logic to try to reduce disk writes + * if no source files changed. This method was designed to be hooked up to a file watcher for the source + * code. *There will be no changes if this method is called after there is a manual change to the translation + * templates. It only cares about source files.* + * @param {Array} [requestFiles = []] - The files or none to + * update everything in the options.files glob pattern. + */ + update(requestFiles = []) { + const options = this.options; - if (options.debug) { - print('DONE'); - } + if (this.read(requestFiles)) { + this.write(); } - /** - * @return {String} The path to the directory which holds - * the translation templates that are dynamically updated - * by code changes and should be used by translators - * to add the localizations. - */ - get templateDirectory() { - const options = this.options; - - if (options.templates) { - return path.resolve(options.templates, 'locales'); - } + if (options.debug) { + print('DONE'); + } + } + + /** + * @return {String} The path to the directory which holds + * the translation templates that are dynamically updated + * by code changes and should be used by translators + * to add the localizations. + */ + get templateDirectory() { + const options = this.options; - return './locales'; + if (options.templates) { + return path.resolve(options.templates, 'locales'); } + + return './locales'; + } } module.exports = TranslationStaticAnalyzer; diff --git a/src/isEscapeCharacter.js b/src/isEscapeCharacter.js index ecd52f5..b998455 100644 --- a/src/isEscapeCharacter.js +++ b/src/isEscapeCharacter.js @@ -1,9 +1,9 @@ const escapeCharacters = new Set([ - `'`, - '"', - "`", - "/*", - "//" + `'`, + '"', + "`", + "/*", + "//" ]); /** @@ -14,5 +14,5 @@ const escapeCharacters = new Set([ * @private */ module.exports = function isEscapeCharacter(character) { - return escapeCharacters.has(character); + return escapeCharacters.has(character); } diff --git a/src/isLocalizationFunctionStart.js b/src/isLocalizationFunctionStart.js index 3ef2e73..37ee680 100644 --- a/src/isLocalizationFunctionStart.js +++ b/src/isLocalizationFunctionStart.js @@ -1,16 +1,16 @@ const translationStartPatterns = [ - '__(', - '__`', - `__n(`, - '__n`', - '__p(', - '__p`', - `__np(`, - '__np`', + '__(', + '__`', + `__n(`, + '__n`', + '__p(', + '__p`', + `__np(`, + '__np`', ]; const length = translationStartPatterns - .reduce((accumulator, p) => Math.max(p.length, accumulator), 0); + .reduce((accumulator, p) => Math.max(p.length, accumulator), 0); /** * @param {String} text - A blob of text to act as a haystack @@ -21,7 +21,7 @@ const length = translationStartPatterns * @private */ module.exports = function isLocalizationStart(text, {index}) { - const testString = text.substring(index, index + length); + const testString = text.substring(index, index + length); - return translationStartPatterns.some((p) => testString.startsWith(p)); + return translationStartPatterns.some((p) => testString.startsWith(p)); } diff --git a/src/isLocalizationFunctionStart.test.js b/src/isLocalizationFunctionStart.test.js index cd22051..a4e0865 100644 --- a/src/isLocalizationFunctionStart.test.js +++ b/src/isLocalizationFunctionStart.test.js @@ -1,63 +1,63 @@ const isLocalizationFunctionStart = require('./isLocalizationFunctionStart'); describe('isLocalizationFunctionStart', () => { - describe('Singular', () => { - it('returns false for before with single quote', () => { - expect(isLocalizationFunctionStart(`a __('a')`, {index: 0})).toBe(false); - }); + describe('Singular', () => { + it('returns false for before with single quote', () => { + expect(isLocalizationFunctionStart(`a __('a')`, {index: 0})).toBe(false); + }); - it('returns true when index is start with single quote', () => { - expect(isLocalizationFunctionStart(`a __('a')`, {index: 2})).toBe(true); - }); + it('returns true when index is start with single quote', () => { + expect(isLocalizationFunctionStart(`a __('a')`, {index: 2})).toBe(true); + }); - it('returns false when afterw ith single quote', () => { - expect(isLocalizationFunctionStart(`a __('a')`, {index: 4})).toBe(false); - }); + it('returns false when afterw ith single quote', () => { + expect(isLocalizationFunctionStart(`a __('a')`, {index: 4})).toBe(false); + }); - it('returns false for before with double quote', () => { - expect(isLocalizationFunctionStart(`a __("a")`, {index: 0})).toBe(false); - }); + it('returns false for before with double quote', () => { + expect(isLocalizationFunctionStart(`a __("a")`, {index: 0})).toBe(false); + }); - it('returns true when index is start with double quote', () => { - expect(isLocalizationFunctionStart(`a __("a")`, {index: 2})).toBe(true); - }); + it('returns true when index is start with double quote', () => { + expect(isLocalizationFunctionStart(`a __("a")`, {index: 2})).toBe(true); + }); - it('returns false when afterw ith double quote', () => { - expect(isLocalizationFunctionStart(`a __("a")`, {index: 4})).toBe(false); - }); + it('returns false when afterw ith double quote', () => { + expect(isLocalizationFunctionStart(`a __("a")`, {index: 4})).toBe(false); + }); - it('returns false for before with backtick quote', () => { - expect(isLocalizationFunctionStart('a __(`a`)', {index: 0})).toBe(false); - }); + it('returns false for before with backtick quote', () => { + expect(isLocalizationFunctionStart('a __(`a`)', {index: 0})).toBe(false); + }); - it('returns true when index is start with backtick quote', () => { - expect(isLocalizationFunctionStart('a __(`a`)', {index: 2})).toBe(true); - }); + it('returns true when index is start with backtick quote', () => { + expect(isLocalizationFunctionStart('a __(`a`)', {index: 2})).toBe(true); + }); - it('returns false when afterw ith backtick quote', () => { - expect(isLocalizationFunctionStart('a __(`a`)', {index: 4})).toBe(false); - }); + it('returns false when afterw ith backtick quote', () => { + expect(isLocalizationFunctionStart('a __(`a`)', {index: 4})).toBe(false); + }); - it('returns false for before with short', () => { - expect(isLocalizationFunctionStart('a __`a`', {index: 0})).toBe(false); - }); + it('returns false for before with short', () => { + expect(isLocalizationFunctionStart('a __`a`', {index: 0})).toBe(false); + }); - it('returns true when index is start with short', () => { - expect(isLocalizationFunctionStart('a __`a`', {index: 2})).toBe(true); - }); + it('returns true when index is start with short', () => { + expect(isLocalizationFunctionStart('a __`a`', {index: 2})).toBe(true); + }); - it('returns false when afterw with short', () => { - expect(isLocalizationFunctionStart('a __`a`', {index: 4})).toBe(false); - }); + it('returns false when afterw with short', () => { + expect(isLocalizationFunctionStart('a __`a`', {index: 4})).toBe(false); }); + }); - describe('Plural', () => { - it('returns false for before with single quote', () => { - expect(isLocalizationFunctionStart(`a __n('a')`, {index: 0})).toBe(false); - }); + describe('Plural', () => { + it('returns false for before with single quote', () => { + expect(isLocalizationFunctionStart(`a __n('a')`, {index: 0})).toBe(false); + }); - it('returns true when index is start with single quote', () => { - expect(isLocalizationFunctionStart(`a __n('a')`, {index: 2})).toBe(true); - }); + it('returns true when index is start with single quote', () => { + expect(isLocalizationFunctionStart(`a __n('a')`, {index: 2})).toBe(true); }); + }); }); diff --git a/src/isQuoteCharacter.js b/src/isQuoteCharacter.js index 7cd9ec5..923fd7d 100644 --- a/src/isQuoteCharacter.js +++ b/src/isQuoteCharacter.js @@ -1,7 +1,7 @@ const quoteCharacters = new Set([ - "'", - '"', - "`" + "'", + '"', + "`" ]); /** @@ -11,5 +11,5 @@ const quoteCharacters = new Set([ * @private */ module.exports = function isQuoteCharacter(character) { - return quoteCharacters.has(character); + return quoteCharacters.has(character); } diff --git a/src/isSubPath.js b/src/isSubPath.js index 98e6974..60953ee 100644 --- a/src/isSubPath.js +++ b/src/isSubPath.js @@ -6,10 +6,10 @@ * @private */ module.exports = function isSubPath(path, subPath) { - return subPath.startsWith(path) && - ( - path.length === subPath.length || // /one/two === /one/two - path.slice(-1) === '/' || // /one/ === /one/two - subPath.charAt(path.length) === '/' // /one === /one/two - ); + return subPath.startsWith(path) && + ( + path.length === subPath.length || // /one/two === /one/two + path.slice(-1) === '/' || // /one/ === /one/two + subPath.charAt(path.length) === '/' // /one === /one/two + ); } diff --git a/src/isSubPath.test.js b/src/isSubPath.test.js index e162da9..198520a 100644 --- a/src/isSubPath.test.js +++ b/src/isSubPath.test.js @@ -1,19 +1,19 @@ const isSubPath = require('./isSubPath'); describe('isSubPath', () => { - it('returns true when matches cleanly with no final slash', () => { - expect(isSubPath('/path', '/path/child')).toBe(true); - }); + it('returns true when matches cleanly with no final slash', () => { + expect(isSubPath('/path', '/path/child')).toBe(true); + }); - it('returns true when matches cleanly and includes final slash', () => { - expect(isSubPath('/path/', '/path/child')).toBe(true); - }); + it('returns true when matches cleanly and includes final slash', () => { + expect(isSubPath('/path/', '/path/child')).toBe(true); + }); - it('returns true when exactly equal', () => { - expect(isSubPath('/path/child', '/path/child')).toBe(true); - }); + it('returns true when exactly equal', () => { + expect(isSubPath('/path/child', '/path/child')).toBe(true); + }); - it('returns flash when extra characters', () => { - expect(isSubPath('/path/child', '/path/childextra')).toBe(false); - }); + it('returns flash when extra characters', () => { + expect(isSubPath('/path/child', '/path/childextra')).toBe(false); + }); }); diff --git a/src/isWhiteSpaceCharacter.js b/src/isWhiteSpaceCharacter.js index 15af7d8..479e6aa 100644 --- a/src/isWhiteSpaceCharacter.js +++ b/src/isWhiteSpaceCharacter.js @@ -1,6 +1,6 @@ const whiteSpaceCharacters = new Set([ - ' ', - ' ', + ' ', + ' ', ]); /** @@ -11,5 +11,5 @@ const whiteSpaceCharacters = new Set([ * @private */ module.exports = function isWhiteSpaceCharacter(character) { - return whiteSpaceCharacters.has(character); + return whiteSpaceCharacters.has(character); } diff --git a/src/parseLocalizationFunction.js b/src/parseLocalizationFunction.js index 6324e6d..38d0b51 100644 --- a/src/parseLocalizationFunction.js +++ b/src/parseLocalizationFunction.js @@ -5,48 +5,48 @@ const isWhiteSpaceCharacter = require('./isWhiteSpaceCharacter'); * @private */ function continueToQuoteStart(text, state) { - const readCharacter = require('./readCharacter'); + const readCharacter = require('./readCharacter'); - while ((state = readCharacter(text, state)) !== null) { - const character = text.charAt(state.index); + while ((state = readCharacter(text, state)) !== null) { + const character = text.charAt(state.index); - if (isQuoteCharacter(state.stack[0])) { - break; - } + if (isQuoteCharacter(state.stack[0])) { + break; + } - if (!isQuoteCharacter(character) && !isWhiteSpaceCharacter(character)) { - throw new SyntaxError('localization key must be a literal'); - } + if (!isQuoteCharacter(character) && !isWhiteSpaceCharacter(character)) { + throw new SyntaxError('localization key must be a literal'); } + } - return state; + return state; } /** * @private */ function continueUntilStackLengthIs(text, state, length) { - const readCharacter = require('./readCharacter'); + const readCharacter = require('./readCharacter'); - while ((state = readCharacter(text, state)) !== null) { - if (state.stack.length <= length) { - break; - } + while ((state = readCharacter(text, state)) !== null) { + if (state.stack.length <= length) { + break; } + } - return state; + return state; } function readStringArgument(text, {index, stack, lineNumber}, name) { - const start = continueToQuoteStart(text, {index, stack, lineNumber}); - const end = continueUntilStackLengthIs(text, {...start}, start.stack.length - 1); - const stringArgument = text.substring(start.index, end.index - 1); + const start = continueToQuoteStart(text, {index, stack, lineNumber}); + const end = continueUntilStackLengthIs(text, {...start}, start.stack.length - 1); + const stringArgument = text.substring(start.index, end.index - 1); - if (start.index === end.index - 1) { - throw new SyntaxError(`${name} string argument is empty`); - } + if (start.index === end.index - 1) { + throw new SyntaxError(`${name} string argument is empty`); + } - return [end, stringArgument]; + return [end, stringArgument]; } /** @@ -61,43 +61,43 @@ function readStringArgument(text, {index, stack, lineNumber}, name) { * @private */ module.exports = function parseLocalizationFunction(text, {index, stack, lineNumber}) { - const functionStart = {index, stack, lineNumber}; - let plural = false; - let particular = false; + const functionStart = {index, stack, lineNumber}; + let plural = false; + let particular = false; - index += 1; + index += 1; - if (text.charAt(index + 1) === 'n') { - plural = true; - index += 1; - } + if (text.charAt(index + 1) === 'n') { + plural = true; + index += 1; + } - if (text.charAt(index + 1) === 'p') { - particular = true; - index += 1; - } + if (text.charAt(index + 1) === 'p') { + particular = true; + index += 1; + } - if (text.charAt(index + 1) === '(') { - index += 1; - } + if (text.charAt(index + 1) === '(') { + index += 1; + } - const metadata = {plural, particular}; - let state = {index, stack, lineNumber}; + const metadata = {plural, particular}; + let state = {index, stack, lineNumber}; - if (particular) { - let context; - [state, context] = readStringArgument(text, state, 'context'); - metadata.context = context; - } + if (particular) { + let context; + [state, context] = readStringArgument(text, state, 'context'); + metadata.context = context; + } - let key; - [state, key] = readStringArgument(text, state, 'key'); - metadata.key = key; + let key; + [state, key] = readStringArgument(text, state, 'key'); + metadata.key = key; - const functionEnd = (state.stack[0] === '(') ? - continueUntilStackLengthIs(text, {...state}, state.stack.length - 1) : state; - const fn = text.substring(functionStart.index, functionEnd.index); - metadata.fn = fn; + const functionEnd = (state.stack[0] === '(') ? + continueUntilStackLengthIs(text, {...state}, state.stack.length - 1) : state; + const fn = text.substring(functionStart.index, functionEnd.index); + metadata.fn = fn; - return Object.assign({}, functionEnd, metadata); + return Object.assign({}, functionEnd, metadata); } diff --git a/src/readCharacter.js b/src/readCharacter.js index 89dcc7e..c25a69a 100644 --- a/src/readCharacter.js +++ b/src/readCharacter.js @@ -6,15 +6,15 @@ const parseLocalizationFunction = require('./parseLocalizationFunction'); function push(stack, value) { - const copy = [value].concat(stack); + const copy = [value].concat(stack); - return {stack: copy, head: copy[0]}; + return {stack: copy, head: copy[0]}; } function pop(stack) { - const copy = stack.slice(1); + const copy = stack.slice(1); - return {stack: copy, head: copy[0]}; + return {stack: copy, head: copy[0]}; } /** @@ -28,171 +28,171 @@ function pop(stack) { * @private */ function readCharacter(text, {index, stack, lineNumber}) { - const character = text.charAt(index); - let head = stack[0]; - const escaped = isEscapeCharacter(head); - let localization; - let testString; + const character = text.charAt(index); + let head = stack[0]; + const escaped = isEscapeCharacter(head); + let localization; + let testString; - if (character === '') { - while (head === '//') { - ({head, stack} = pop(stack)); - } - - if (stack.length) { - throw new SyntaxError( - 'text ended with unclosed stack items', - JSON.stringify(stack, null, 4) - ); - } + if (character === '') { + while (head === '//') { + ({head, stack} = pop(stack)); + } - return null; + if (stack.length) { + throw new SyntaxError( + 'text ended with unclosed stack items', + JSON.stringify(stack, null, 4) + ); } - switch (character) { - case '_': - if (!escaped) { - if (isLocalizationFunctionStart(text, {index})) { - ({ - index, - stack, - lineNumber, - ...localization - } = parseLocalizationFunction(text, {index, stack, lineNumber})); - } else { - index += 1; - } - } else { - index += 1; - } - break; - case '<': //EJS style template strings - if (isQuoteCharacter(head) && startsWith(text, index, '<%')) { - ({head, stack} = push(stack, '<%')); - index += 2; - } else { - index += 1; - } - break; - case '%': - if (head === '<%' && startsWith(text, index, '%>')) { - ({head, stack} = pop(stack)); - index += 2; - } else { - index += 1; - } - break; - case '[': //Polymer style template strings - if (isQuoteCharacter(head) && startsWith(text, index, '[[')) { - ({head, stack} = push(stack, '[[')); - index += 2; - } else { - index += 1; - } - break; - case ']': - if (head === '[[' && startsWith(text, index, ']]')) { - ({head, stack} = pop(stack)); - index += 2; - } else { - index += 1; - } - break; - case '$': //Native javscript template strings - if (head === '`' && startsWith(text, index, '${')) { - ({head, stack} = push(stack, '${')); - index += 2; - } else { - index += 1; - } - break; - case '{': //Angular style template strings - if (isQuoteCharacter(head) && startsWith(text, index, '{{')) { - ({head, stack} = push(stack, '{{')); - index += 2; - } else { - index += 1; - } - break; - case '}': - if (head === '{{' && startsWith(text, index, '}}')) { - ({head, stack} = pop(stack)); - index += 2; - } else if (head === '${' && startsWith(text, index, '}')) { - ({head, stack} = pop(stack)); - index += 1; - } else { - index += 1; - } - break; - case '*': - if (head === '/*' && startsWith(text, index, '*/')) { - ({head, stack} = pop(stack)); - index += 2; - } else { - index += 1; - } - break; - case '/': - testString = text.substring(index, index + 2); + return null; + } - if (!escaped && testString === '//') { - ({head, stack} = push(stack, testString)); - index += 2; - } else if (!escaped && testString === '/*') { - ({head, stack} = push(stack, testString)); - index += 2; - } else { - index += 1; - } + switch (character) { + case '_': + if (!escaped) { + if (isLocalizationFunctionStart(text, {index})) { + ({ + index, + stack, + lineNumber, + ...localization + } = parseLocalizationFunction(text, {index, stack, lineNumber})); + } else { + index += 1; + } + } else { + index += 1; + } + break; + case '<': //EJS style template strings + if (isQuoteCharacter(head) && startsWith(text, index, '<%')) { + ({head, stack} = push(stack, '<%')); + index += 2; + } else { + index += 1; + } + break; + case '%': + if (head === '<%' && startsWith(text, index, '%>')) { + ({head, stack} = pop(stack)); + index += 2; + } else { + index += 1; + } + break; + case '[': //Polymer style template strings + if (isQuoteCharacter(head) && startsWith(text, index, '[[')) { + ({head, stack} = push(stack, '[[')); + index += 2; + } else { + index += 1; + } + break; + case ']': + if (head === '[[' && startsWith(text, index, ']]')) { + ({head, stack} = pop(stack)); + index += 2; + } else { + index += 1; + } + break; + case '$': //Native javscript template strings + if (head === '`' && startsWith(text, index, '${')) { + ({head, stack} = push(stack, '${')); + index += 2; + } else { + index += 1; + } + break; + case '{': //Angular style template strings + if (isQuoteCharacter(head) && startsWith(text, index, '{{')) { + ({head, stack} = push(stack, '{{')); + index += 2; + } else { + index += 1; + } + break; + case '}': + if (head === '{{' && startsWith(text, index, '}}')) { + ({head, stack} = pop(stack)); + index += 2; + } else if (head === '${' && startsWith(text, index, '}')) { + ({head, stack} = pop(stack)); + index += 1; + } else { + index += 1; + } + break; + case '*': + if (head === '/*' && startsWith(text, index, '*/')) { + ({head, stack} = pop(stack)); + index += 2; + } else { + index += 1; + } + break; + case '/': + testString = text.substring(index, index + 2); - break; - case '`': - case '"': - case `'`: - if (head === character) { - ({head, stack} = pop(stack)); - index += 1; - } else if (!escaped) { - ({head, stack} = push(stack, character)); - index += 1; - } else { - index += 1; - } - break; - case '(': - if (!escaped) { - ({head, stack} = push(stack, character)); - } - index += 1; - break; - case ')': - if (!escaped) { - if (head === '(') { - ({head, stack} = pop(stack)); - } else { - throw new SyntaxError('missing matching opening brace'); - } - } - index += 1; - break; - case '\n': - if (head === '//') { - ({head, stack} = pop(stack)); - } - index += 1; - lineNumber += 1; - break; - default: - index += 1; - break; - } + if (!escaped && testString === '//') { + ({head, stack} = push(stack, testString)); + index += 2; + } else if (!escaped && testString === '/*') { + ({head, stack} = push(stack, testString)); + index += 2; + } else { + index += 1; + } - if (localization) { - return {index, stack, lineNumber, localization}; - } + break; + case '`': + case '"': + case `'`: + if (head === character) { + ({head, stack} = pop(stack)); + index += 1; + } else if (!escaped) { + ({head, stack} = push(stack, character)); + index += 1; + } else { + index += 1; + } + break; + case '(': + if (!escaped) { + ({head, stack} = push(stack, character)); + } + index += 1; + break; + case ')': + if (!escaped) { + if (head === '(') { + ({head, stack} = pop(stack)); + } else { + throw new SyntaxError('missing matching opening brace'); + } + } + index += 1; + break; + case '\n': + if (head === '//') { + ({head, stack} = pop(stack)); + } + index += 1; + lineNumber += 1; + break; + default: + index += 1; + break; + } + + if (localization) { + return {index, stack, lineNumber, localization}; + } - return {index, stack, lineNumber}; + return {index, stack, lineNumber}; } module.exports = readCharacter; diff --git a/src/readCharacter.test.js b/src/readCharacter.test.js index dc9dd0d..0a16254 100644 --- a/src/readCharacter.test.js +++ b/src/readCharacter.test.js @@ -1,943 +1,943 @@ const readCharacter = require('./readCharacter'); describe('plugins/readCharacter', () => { - it('reads letters with no special meaning', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'abc'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); + it('reads letters with no special meaning', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'abc'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + lineNumber: 0 + }, { + index: 3, + stack: [], + lineNumber: 0 + }]); + }); + + it('reads a string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a"b"c'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: ['"'], + lineNumber: 0 + }, { + index: 3, + stack: ['"'], + lineNumber: 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }, { + index: 5, + stack: [], + lineNumber: 0 + }]); + }); + + it('reads a string surrounded in parenthesis', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a("b")c'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: ['('], + lineNumber: 0 + }, { + index: 3, + stack: ['"', '('], + lineNumber: 0 + }, { + index: 4, + stack: ['"', '('], + lineNumber: 0 + }, { + index: 5, + stack: ['('], + lineNumber: 0 + }, { + index: 6, + stack: [], + lineNumber: 0 + }, { + index: 7, + stack: [], + lineNumber: 0 + }]); + }); + + it('doesn\'t add quoted parenthesis to the stack', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a"(b)"c'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: ['"'], + lineNumber: 0 + }, { + index: 3, + stack: ['"'], + lineNumber: 0 + }, { + index: 4, + stack: ['"'], + lineNumber: 0 + }, { + index: 5, + stack: ['"'], + lineNumber: 0 + }, { + index: 6, + stack: [], + lineNumber: 0 + }, { + index: 7, + stack: [], + lineNumber: 0 + }]); + }); + + it('doesn\'t add commented quotes', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '//"\n""'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 2, + stack: ['//'], + lineNumber: 0 + }, { + index: 3, + stack: ['//'], + lineNumber: 0 + }, { + index: 4, + stack: [], + lineNumber: 1 + }, { + index: 5, + stack: ['"'], + lineNumber: 1 + }, { + index: 6, + stack: [], + lineNumber: 1 + }]); + }); + + it('multiline comments comment quotes', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '/*"\n*/""'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 2, + stack: ['/*'], + lineNumber: 0 + }, { + index: 3, + stack: ['/*'], + lineNumber: 0 + }, { + index: 4, + stack: ['/*'], + lineNumber: 1 + }, { + index: 6, + stack: [], + lineNumber: 1 + }, { + index: 7, + stack: ['"'], + lineNumber: 1 + }, { + index: 8, + stack: [], + lineNumber: 1 + }]); + }); + + it('parses basic translation function', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__("a")b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 7, + stack: [], + lineNumber: 0, + localization: { + key: 'a', + fn: '__("a")', + plural: false, + particular: false, + } + }, { + index: 8, + stack: [], + lineNumber: 0, + }]); + }); + + it('parses basic translation function with context', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__p("a", "b")c'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 13, + stack: [], + lineNumber: 0, + localization: { + context: 'a', + key: 'b', + fn: '__p("a", "b")', + plural: false, + particular: true, + } + }, { + index: 14, + stack: [], + lineNumber: 0, + }]); + }); + + it('parses basic plural translation function', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__n("%d cat", "%d cats", 1)b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 27, + stack: [], + lineNumber: 0, + localization: { + key: '%d cat', + fn: '__n("%d cat", "%d cats", 1)', + plural: true, + particular: false, + } + }, { + index: 28, + stack: [], + lineNumber: 0, + }]); + }); + + it('parses basic plural translation function with context', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__np("a", "%d cat", "%d cats", 1)b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 33, + stack: [], + lineNumber: 0, + localization: { + key: '%d cat', + context: 'a', + fn: '__np("a", "%d cat", "%d cats", 1)', + plural: true, + particular: true, + } + }, { + index: 34, + stack: [], + lineNumber: 0, + }]); + }); + + describe('polymer-style template strings', () => { + it('parses basic translation function in [[]] interpolation string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '`[[__("a")]]`'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 3, + stack: [ + "[[", + "`" + ], + lineNumber: 0 + }, { + index: 10, + stack: [ + "[[", + "`" + ], + lineNumber: 0, + localization: { + "key": "a", + "fn": "__(\"a\")", + particular: false, + plural: false, } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - lineNumber: 0 - }, { - index: 3, - stack: [], - lineNumber: 0 - }]); + }, { + index: 12, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 13, + stack: [ + ], + lineNumber: 0 + }]); }); - it('reads a string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a"b"c'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: ['"'], - lineNumber: 0 - }, { - index: 3, - stack: ['"'], - lineNumber: 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }, { - index: 5, - stack: [], - lineNumber: 0 - }]); + it('skips [ interpolation when not part of a string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a[[b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + "lineNumber": 0 + }, { + index: 3, + stack: [], + "lineNumber": 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }]); }); - it('reads a string surrounded in parenthesis', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a("b")c'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: ['('], - lineNumber: 0 - }, { - index: 3, - stack: ['"', '('], - lineNumber: 0 - }, { - index: 4, - stack: ['"', '('], - lineNumber: 0 - }, { - index: 5, - stack: ['('], - lineNumber: 0 - }, { - index: 6, - stack: [], - lineNumber: 0 - }, { - index: 7, - stack: [], - lineNumber: 0 - }]); + it('skips ]] interpolation when not started', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a]]b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + "lineNumber": 0 + }, { + index: 3, + stack: [], + "lineNumber": 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }]); }); - - it('doesn\'t add quoted parenthesis to the stack', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a"(b)"c'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); + }); + + describe('Angular style template strings', () => { + it('parses basic translation function in {{}} interpolation string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '`{{__("a")}}`'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 3, + stack: [ + "{{", + "`" + ], + lineNumber: 0 + }, { + index: 10, + stack: [ + "{{", + "`" + ], + lineNumber: 0, + localization: { + "key": "a", + "fn": "__(\"a\")", + particular: false, + plural: false, } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: ['"'], - lineNumber: 0 - }, { - index: 3, - stack: ['"'], - lineNumber: 0 - }, { - index: 4, - stack: ['"'], - lineNumber: 0 - }, { - index: 5, - stack: ['"'], - lineNumber: 0 - }, { - index: 6, - stack: [], - lineNumber: 0 - }, { - index: 7, - stack: [], - lineNumber: 0 - }]); + }, { + index: 12, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 13, + stack: [ + ], + lineNumber: 0 + }]); }); - it('doesn\'t add commented quotes', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '//"\n""'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 2, - stack: ['//'], - lineNumber: 0 - }, { - index: 3, - stack: ['//'], - lineNumber: 0 - }, { - index: 4, - stack: [], - lineNumber: 1 - }, { - index: 5, - stack: ['"'], - lineNumber: 1 - }, { - index: 6, - stack: [], - lineNumber: 1 - }]); + it('skips {{ interpolation when not part of a string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a{{b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + "lineNumber": 0 + }, { + index: 3, + stack: [], + "lineNumber": 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }]); }); - it('multiline comments comment quotes', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '/*"\n*/""'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 2, - stack: ['/*'], - lineNumber: 0 - }, { - index: 3, - stack: ['/*'], - lineNumber: 0 - }, { - index: 4, - stack: ['/*'], - lineNumber: 1 - }, { - index: 6, - stack: [], - lineNumber: 1 - }, { - index: 7, - stack: ['"'], - lineNumber: 1 - }, { - index: 8, - stack: [], - lineNumber: 1 - }]); + it('skips {{ interpolation when not on stack', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a}}b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + "lineNumber": 0 + }, { + index: 3, + stack: [], + "lineNumber": 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }]); }); - - it('parses basic translation function', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__("a")b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); + }); + + describe('Javscript style template strings', () => { + it('parses basic translation function in `${}` interpolation string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '`${__("a")}`'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 3, + stack: [ + "${", + "`" + ], + lineNumber: 0 + }, { + index: 10, + stack: [ + "${", + "`" + ], + lineNumber: 0, + localization: { + "key": "a", + "fn": "__(\"a\")", + particular: false, + plural: false } - - expect(actual).toEqual([{ - index: 7, - stack: [], - lineNumber: 0, - localization: { - key: 'a', - fn: '__("a")', - plural: false, - particular: false, - } - }, { - index: 8, - stack: [], - lineNumber: 0, - }]); + }, { + index: 11, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 12, + stack: [ + ], + lineNumber: 0 + }]); }); - it('parses basic translation function with context', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__p("a", "b")c'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 13, - stack: [], - lineNumber: 0, - localization: { - context: 'a', - key: 'b', - fn: '__p("a", "b")', - plural: false, - particular: true, - } - }, { - index: 14, - stack: [], - lineNumber: 0, - }]); + it('skips $ interpolation when not part of a string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a${b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + "lineNumber": 0 + }, { + index: 3, + stack: [], + "lineNumber": 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }]); }); - - it('parses basic plural translation function', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__n("%d cat", "%d cats", 1)b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 27, - stack: [], - lineNumber: 0, - localization: { - key: '%d cat', - fn: '__n("%d cat", "%d cats", 1)', - plural: true, - particular: false, - } - }, { - index: 28, - stack: [], - lineNumber: 0, - }]); - }); - - it('parses basic plural translation function with context', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__np("a", "%d cat", "%d cats", 1)b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); + }); + + describe('EJS style template strings', () => { + it('parses basic translation function in <% %> interpolation string', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '`<%:__("a")%>`'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 3, + stack: [ + "<%", + "`" + ], + lineNumber: 0 + }, { + index: 4, + stack: [ + "<%", + "`" + ], + lineNumber: 0 + }, { + index: 11, + stack: [ + "<%", + "`" + ], + lineNumber: 0, + localization: { + "key": "a", + "fn": "__(\"a\")", + plural: false, + particular: false, } - - expect(actual).toEqual([{ - index: 33, - stack: [], - lineNumber: 0, - localization: { - key: '%d cat', - context: 'a', - fn: '__np("a", "%d cat", "%d cats", 1)', - plural: true, - particular: true, - } - }, { - index: 34, - stack: [], - lineNumber: 0, - }]); - }); - - describe('polymer-style template strings', () => { - it('parses basic translation function in [[]] interpolation string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '`[[__("a")]]`'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 3, - stack: [ - "[[", - "`" - ], - lineNumber: 0 - }, { - index: 10, - stack: [ - "[[", - "`" - ], - lineNumber: 0, - localization: { - "key": "a", - "fn": "__(\"a\")", - particular: false, - plural: false, - } - }, { - index: 12, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 13, - stack: [ - ], - lineNumber: 0 - }]); - }); - - it('skips [ interpolation when not part of a string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a[[b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - "lineNumber": 0 - }, { - index: 3, - stack: [], - "lineNumber": 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }]); - }); - - it('skips ]] interpolation when not started', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a]]b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - "lineNumber": 0 - }, { - index: 3, - stack: [], - "lineNumber": 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }]); - }); + }, { + index: 13, + stack: [ + "`" + ], + lineNumber: 0 + }, { + index: 14, + stack: [ + ], + lineNumber: 0 + }]); }); - describe('Angular style template strings', () => { - it('parses basic translation function in {{}} interpolation string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '`{{__("a")}}`'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 3, - stack: [ - "{{", - "`" - ], - lineNumber: 0 - }, { - index: 10, - stack: [ - "{{", - "`" - ], - lineNumber: 0, - localization: { - "key": "a", - "fn": "__(\"a\")", - particular: false, - plural: false, - } - }, { - index: 12, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 13, - stack: [ - ], - lineNumber: 0 - }]); - }); - - it('skips {{ interpolation when not part of a string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a{{b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - "lineNumber": 0 - }, { - index: 3, - stack: [], - "lineNumber": 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }]); - }); - - it('skips {{ interpolation when not on stack', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a}}b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - "lineNumber": 0 - }, { - index: 3, - stack: [], - "lineNumber": 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }]); - }); - }); - - describe('Javscript style template strings', () => { - it('parses basic translation function in `${}` interpolation string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '`${__("a")}`'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 3, - stack: [ - "${", - "`" - ], - lineNumber: 0 - }, { - index: 10, - stack: [ - "${", - "`" - ], - lineNumber: 0, - localization: { - "key": "a", - "fn": "__(\"a\")", - particular: false, - plural: false - } - }, { - index: 11, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 12, - stack: [ - ], - lineNumber: 0 - }]); - }); - - it('skips $ interpolation when not part of a string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a${b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - "lineNumber": 0 - }, { - index: 3, - stack: [], - "lineNumber": 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }]); - }); - }); - - describe('EJS style template strings', () => { - it('parses basic translation function in <% %> interpolation string', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '`<%:__("a")%>`'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 3, - stack: [ - "<%", - "`" - ], - lineNumber: 0 - }, { - index: 4, - stack: [ - "<%", - "`" - ], - lineNumber: 0 - }, { - index: 11, - stack: [ - "<%", - "`" - ], - lineNumber: 0, - localization: { - "key": "a", - "fn": "__(\"a\")", - plural: false, - particular: false, - } - }, { - index: 13, - stack: [ - "`" - ], - lineNumber: 0 - }, { - index: 14, - stack: [ - ], - lineNumber: 0 - }]); - }); - - it('skips < interpolation when no %', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a interpolation when no %', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a%>b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 2, - stack: [], - "lineNumber": 0 - }, { - index: 3, - stack: [], - "lineNumber": 0 - }, { - index: 4, - stack: [], - lineNumber: 0 - }]); - }); - }); - - it('parses template translation function', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__`a`b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 5, - stack: [], - lineNumber: 0, - localization: { - key: 'a', - fn: '__`a`', - particular: false, - plural: false, - } - }, { - index: 6, - stack: [], - lineNumber: 0, - }]); - }); - - it('throws an exception when there is no closing quote', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '"'; - const actual = []; - - expect(() => { - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - }).toThrow(new SyntaxError('text ended with unclosed stack items')); - - expect(actual).toEqual([{ - index: 1, - stack: ['"'], - lineNumber: 0, - }]); - + it('skips < interpolation when no %', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '('; - const actual = []; - - expect(() => { - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - }).toThrow(new SyntaxError('text ended with unclosed stack items')); - - expect(actual).toEqual([{ - index: 1, - stack: ['('], - lineNumber: 0, - }]); - - }); - - it('throws an exception when a close parenthesis is used when there is no open', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = ')'; - const actual = []; - - expect(() => { - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - }).toThrow(new SyntaxError('missing matching opening brace')); - - expect(actual).toEqual([]); - - }); - - it('throws an error when there is no string literal for the translation', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__(fish)'; - const actual = []; - - expect(() => { - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - }).toThrow(new SyntaxError('localization key must be a literal')); - - expect(actual).toEqual([]); - - }); - - it('throws an error if quote is not the first character', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__(,"fish")'; - const actual = []; - - expect(() => { - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - }).toThrow(new SyntaxError('localization key must be a literal')); - - expect(actual).toEqual([]); - - }); - - it('throws an error if string is empty', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = '__("")'; - const actual = []; - - expect(() => { - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - }).toThrow(new SyntaxError('key string argument is empty')); - - expect(actual).toEqual([]); - - }); - - it('iterates * as a normal character', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a*b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0, - }, { - index: 2, - stack: [], - lineNumber: 0, - }, { - index: 3, - stack: [], - lineNumber: 0, - }]); - - }); - - it('iterates / as a normal character', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a/b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0, - }, { - index: 2, - stack: [], - lineNumber: 0, - }, { - index: 3, - stack: [], - lineNumber: 0, - }]); - - }); - - it('iterates _ as a normal character', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a_b'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0, - }, { - index: 2, - stack: [], - lineNumber: 0, - }, { - index: 3, - stack: [], - lineNumber: 0, - }]); - - }); - - it('escapes _', () => { - let state = {index: 0, stack: [], lineNumber: 0} - const text = 'a//_'; - const actual = []; - - while ((state = readCharacter(text, state)) !== null) { - actual.push(state); - } - - expect(actual).toEqual([{ - index: 1, - stack: [], - lineNumber: 0 - }, { - index: 3, - stack: [ - "//" - ], - "lineNumber": 0 - }, { - index: 4, - stack: [ - "//" - ], - lineNumber: 0 - }]); + it('skips > interpolation when no %', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a%>b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 2, + stack: [], + "lineNumber": 0 + }, { + index: 3, + stack: [], + "lineNumber": 0 + }, { + index: 4, + stack: [], + lineNumber: 0 + }]); }); + }); + + it('parses template translation function', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__`a`b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 5, + stack: [], + lineNumber: 0, + localization: { + key: 'a', + fn: '__`a`', + particular: false, + plural: false, + } + }, { + index: 6, + stack: [], + lineNumber: 0, + }]); + }); + + it('throws an exception when there is no closing quote', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '"'; + const actual = []; + + expect(() => { + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + }).toThrow(new SyntaxError('text ended with unclosed stack items')); + + expect(actual).toEqual([{ + index: 1, + stack: ['"'], + lineNumber: 0, + }]); + + }); + + it('throws an exception when parenthesis is not closed', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '('; + const actual = []; + + expect(() => { + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + }).toThrow(new SyntaxError('text ended with unclosed stack items')); + + expect(actual).toEqual([{ + index: 1, + stack: ['('], + lineNumber: 0, + }]); + + }); + + it('throws an exception when a close parenthesis is used when there is no open', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = ')'; + const actual = []; + + expect(() => { + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + }).toThrow(new SyntaxError('missing matching opening brace')); + + expect(actual).toEqual([]); + + }); + + it('throws an error when there is no string literal for the translation', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__(fish)'; + const actual = []; + + expect(() => { + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + }).toThrow(new SyntaxError('localization key must be a literal')); + + expect(actual).toEqual([]); + + }); + + it('throws an error if quote is not the first character', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__(,"fish")'; + const actual = []; + + expect(() => { + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + }).toThrow(new SyntaxError('localization key must be a literal')); + + expect(actual).toEqual([]); + + }); + + it('throws an error if string is empty', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = '__("")'; + const actual = []; + + expect(() => { + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + }).toThrow(new SyntaxError('key string argument is empty')); + + expect(actual).toEqual([]); + + }); + + it('iterates * as a normal character', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a*b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0, + }, { + index: 2, + stack: [], + lineNumber: 0, + }, { + index: 3, + stack: [], + lineNumber: 0, + }]); + + }); + + it('iterates / as a normal character', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a/b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0, + }, { + index: 2, + stack: [], + lineNumber: 0, + }, { + index: 3, + stack: [], + lineNumber: 0, + }]); + + }); + + it('iterates _ as a normal character', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a_b'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0, + }, { + index: 2, + stack: [], + lineNumber: 0, + }, { + index: 3, + stack: [], + lineNumber: 0, + }]); + + }); + + it('escapes _', () => { + let state = {index: 0, stack: [], lineNumber: 0} + const text = 'a//_'; + const actual = []; + + while ((state = readCharacter(text, state)) !== null) { + actual.push(state); + } + + expect(actual).toEqual([{ + index: 1, + stack: [], + lineNumber: 0 + }, { + index: 3, + stack: [ + "//" + ], + "lineNumber": 0 + }, { + index: 4, + stack: [ + "//" + ], + lineNumber: 0 + }]); + }); }); diff --git a/src/readString.error.test.js b/src/readString.error.test.js index 2aa611d..e9abc6a 100644 --- a/src/readString.error.test.js +++ b/src/readString.error.test.js @@ -4,15 +4,15 @@ const readCharacter = require('./readCharacter'); readCharacter.mockReturnValue({index: 0, stack: []}); describe('readString', () => { - it('escapes from infinite loop', () => { - const serializedState = JSON.stringify({ - index: 0, - stack: [], - }, null, 4); + it('escapes from infinite loop', () => { + const serializedState = JSON.stringify({ + index: 0, + stack: [], + }, null, 4); - expect(() => readString('a')).toThrow(new Error( + expect(() => readString('a')).toThrow(new Error( - `infinite loop detected\n\n${serializedState}\n\n Problem starts here -> a` - )); - }); + `infinite loop detected\n\n${serializedState}\n\n Problem starts here -> a` + )); + }); }); diff --git a/src/readString.js b/src/readString.js index 0fc7ecb..56344aa 100644 --- a/src/readString.js +++ b/src/readString.js @@ -1,22 +1,22 @@ const readCharacter = require('./readCharacter'); function readCharacterWithErrorHandling(text, state) { - let currentState = Object.assign({}, state); - let nextState; + let currentState = Object.assign({}, state); + let nextState; - while (nextState === undefined) { - try { - nextState = readCharacter(text, currentState); - } catch (e) { - if (currentState.stack.length) { - currentState.stack = currentState.stack.slice(1); - } else { - currentState.index += 1; - } - } + while (nextState === undefined) { + try { + nextState = readCharacter(text, currentState); + } catch (e) { + if (currentState.stack.length) { + currentState.stack = currentState.stack.slice(1); + } else { + currentState.index += 1; + } } + } - return nextState; + return nextState; } /** @@ -28,38 +28,38 @@ function readCharacterWithErrorHandling(text, state) { * @private */ module.exports = function readString(text) { - const localization = {}; - let state = { - index: 0, - stack: [], - lineNumber: 0, - }; - let previousIndex = 0; + const localization = {}; + let state = { + index: 0, + stack: [], + lineNumber: 0, + }; + let previousIndex = 0; - while ((state = readCharacterWithErrorHandling(text, state)) !== null) { - if (state.index === previousIndex) { - const serializedState = JSON.stringify(state, null, 4); - const slice = text.slice(state.index); + while ((state = readCharacterWithErrorHandling(text, state)) !== null) { + if (state.index === previousIndex) { + const serializedState = JSON.stringify(state, null, 4); + const slice = text.slice(state.index); - throw new Error( - `infinite loop detected\n\n${serializedState}\n\n Problem starts here -> ${slice}` - ); - } - - if (state.localization) { - const {key, fn} = state.localization; - const {index, lineNumber} = state; + throw new Error( + `infinite loop detected\n\n${serializedState}\n\n Problem starts here -> ${slice}` + ); + } - if (!localization[key]) { - localization[key] = [{fn, lineNumber, index}]; - } else { - localization[key].push({fn, lineNumber, index}); - } - } + if (state.localization) { + const {key, fn} = state.localization; + const {index, lineNumber} = state; - previousIndex = state.index; + if (!localization[key]) { + localization[key] = [{fn, lineNumber, index}]; + } else { + localization[key].push({fn, lineNumber, index}); + } } - return localization; + previousIndex = state.index; + } + + return localization; } diff --git a/src/readString.test.js b/src/readString.test.js index d0451e7..9972e16 100644 --- a/src/readString.test.js +++ b/src/readString.test.js @@ -1,121 +1,121 @@ const readString = require('./readString'); describe('readString', () => { - describe('singular', () => { - it('create key and value when contains translation', () => { - expect(readString(`a __('b') c`)).toEqual({b: [ - {fn: `__('b')`, lineNumber: 0, index: 9}], - }); - }); - - it('adds nothing when no translation', () => { - expect(readString(`a c`)).toEqual({}); - }); - - it('create key and value when contains shorthand translation', () => { - expect(readString('a __`b` c')).toEqual({b: [ - {fn: '__`b`', lineNumber: 0, index: 7 }], - }); - }); - - it('handles unclosed parenthesis gracefully', () => { - expect(readString('a __(`b` c')).toEqual({}); - }); - - it('handles two duplicate translations on same line gracefully', () => { - expect(readString('a __(`b`) __(`b`) c')).toEqual({b: [ - {fn: '__(`b`)', lineNumber: 0, index: 9 }, - {fn: '__(`b`)', lineNumber: 0, index: 17 }, - ]}); - }); - - it('handles two duplicate translations on different line gracefully', () => { - expect(readString('a __(`b`)\n__(`b`) c')).toEqual({b: [ - {fn: '__(`b`)', lineNumber: 0, index: 9 }, - {fn: '__(`b`)', lineNumber: 1, index: 17 }, - ]}); - }); - }); - - describe('singular with context', () => { - it('create key and value when contains translation', () => { - expect(readString(`a __p('b', 'c') d`)).toEqual({c: [ - {fn: `__p('b', 'c')`, lineNumber: 0, index: 15}, - ]}); - }); - - it('adds nothing when no translation', () => { - expect(readString(`a c`)).toEqual({}); - }); - - it('handles two duplicate translations on same line gracefully', () => { - expect(readString('a __p(`b`, `c`) __p(`b`, `c`) c')).toEqual({c: [ - {fn: '__p(`b`, `c`)', lineNumber: 0, index: 15 }, - {fn: '__p(`b`, `c`)', lineNumber: 0, index: 29 }, - ]}); - }); - - it('handles two duplicate translations on different line gracefully', () => { - expect(readString('a __p(`b`, `c`)\n__p(`b`, `c`) c')).toEqual({c: [ - {fn: '__p(`b`, `c`)', lineNumber: 0, index: 15 }, - {fn: '__p(`b`, `c`)', lineNumber: 1, index: 29 }, - ]}); - }); - }); - - describe('plural', () => { - it('create key and value when contains plural translation', () => { - expect(readString("a __n('%d cat', '%d cats', 1) c")).toEqual({ - '%d cat': [ - {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 29}, - ] - }); - }); - - it('handles two duplicate translations on same line gracefully', () => { - expect(readString("a __n('%d cat', '%d cats', 1) __n('%d cat', '%d cats', 1) c")).toEqual({ - '%d cat': [ - {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 29 }, - {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 57 }, - ] - }); - }); - - it('handles two duplicate translations on different line gracefully', () => { - expect(readString("a __n('%d cat', '%d cats', 1)\n__n('%d cat', '%d cats', 1) c")).toEqual({ - '%d cat': [ - {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 29 }, - {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 1, index: 57 }, - ] - }); - }); - }); - - describe('plural with context', () => { - it('create key and value when contains plural translation', () => { - expect(readString("a __np('a', '%d cat', '%d cats', 1) c")).toEqual({ - '%d cat': [ - {fn: "__np('a', '%d cat', '%d cats', 1)", lineNumber: 0, index: 35}, - ] - }); - }); - - it('handles two duplicate translations on same line gracefully', () => { - expect(readString("a __np('b', '%d cat', '%d cats', 1) __np('b', '%d cat', '%d cats', 1) c")).toEqual({ - '%d cat': [ - {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 0, index: 35 }, - {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 0, index: 69 }, - ] - }); - }); - - it('handles two duplicate translations on different line gracefully', () => { - expect(readString("a __np('b', '%d cat', '%d cats', 1)\n__np('b', '%d cat', '%d cats', 1) c")).toEqual({ - '%d cat': [ - {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 0, index: 35 }, - {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 1, index: 69 }, - ] - }); - }); + describe('singular', () => { + it('create key and value when contains translation', () => { + expect(readString(`a __('b') c`)).toEqual({b: [ + {fn: `__('b')`, lineNumber: 0, index: 9}], + }); }); + + it('adds nothing when no translation', () => { + expect(readString(`a c`)).toEqual({}); + }); + + it('create key and value when contains shorthand translation', () => { + expect(readString('a __`b` c')).toEqual({b: [ + {fn: '__`b`', lineNumber: 0, index: 7 }], + }); + }); + + it('handles unclosed parenthesis gracefully', () => { + expect(readString('a __(`b` c')).toEqual({}); + }); + + it('handles two duplicate translations on same line gracefully', () => { + expect(readString('a __(`b`) __(`b`) c')).toEqual({b: [ + {fn: '__(`b`)', lineNumber: 0, index: 9 }, + {fn: '__(`b`)', lineNumber: 0, index: 17 }, + ]}); + }); + + it('handles two duplicate translations on different line gracefully', () => { + expect(readString('a __(`b`)\n__(`b`) c')).toEqual({b: [ + {fn: '__(`b`)', lineNumber: 0, index: 9 }, + {fn: '__(`b`)', lineNumber: 1, index: 17 }, + ]}); + }); + }); + + describe('singular with context', () => { + it('create key and value when contains translation', () => { + expect(readString(`a __p('b', 'c') d`)).toEqual({c: [ + {fn: `__p('b', 'c')`, lineNumber: 0, index: 15}, + ]}); + }); + + it('adds nothing when no translation', () => { + expect(readString(`a c`)).toEqual({}); + }); + + it('handles two duplicate translations on same line gracefully', () => { + expect(readString('a __p(`b`, `c`) __p(`b`, `c`) c')).toEqual({c: [ + {fn: '__p(`b`, `c`)', lineNumber: 0, index: 15 }, + {fn: '__p(`b`, `c`)', lineNumber: 0, index: 29 }, + ]}); + }); + + it('handles two duplicate translations on different line gracefully', () => { + expect(readString('a __p(`b`, `c`)\n__p(`b`, `c`) c')).toEqual({c: [ + {fn: '__p(`b`, `c`)', lineNumber: 0, index: 15 }, + {fn: '__p(`b`, `c`)', lineNumber: 1, index: 29 }, + ]}); + }); + }); + + describe('plural', () => { + it('create key and value when contains plural translation', () => { + expect(readString("a __n('%d cat', '%d cats', 1) c")).toEqual({ + '%d cat': [ + {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 29}, + ] + }); + }); + + it('handles two duplicate translations on same line gracefully', () => { + expect(readString("a __n('%d cat', '%d cats', 1) __n('%d cat', '%d cats', 1) c")).toEqual({ + '%d cat': [ + {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 29 }, + {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 57 }, + ] + }); + }); + + it('handles two duplicate translations on different line gracefully', () => { + expect(readString("a __n('%d cat', '%d cats', 1)\n__n('%d cat', '%d cats', 1) c")).toEqual({ + '%d cat': [ + {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 0, index: 29 }, + {fn: "__n('%d cat', '%d cats', 1)", lineNumber: 1, index: 57 }, + ] + }); + }); + }); + + describe('plural with context', () => { + it('create key and value when contains plural translation', () => { + expect(readString("a __np('a', '%d cat', '%d cats', 1) c")).toEqual({ + '%d cat': [ + {fn: "__np('a', '%d cat', '%d cats', 1)", lineNumber: 0, index: 35}, + ] + }); + }); + + it('handles two duplicate translations on same line gracefully', () => { + expect(readString("a __np('b', '%d cat', '%d cats', 1) __np('b', '%d cat', '%d cats', 1) c")).toEqual({ + '%d cat': [ + {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 0, index: 35 }, + {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 0, index: 69 }, + ] + }); + }); + + it('handles two duplicate translations on different line gracefully', () => { + expect(readString("a __np('b', '%d cat', '%d cats', 1)\n__np('b', '%d cat', '%d cats', 1) c")).toEqual({ + '%d cat': [ + {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 0, index: 35 }, + {fn: "__np('b', '%d cat', '%d cats', 1)", lineNumber: 1, index: 69 }, + ] + }); + }); + }); }); diff --git a/src/scrubLocalization.js b/src/scrubLocalization.js index 39863ea..aee6c7f 100644 --- a/src/scrubLocalization.js +++ b/src/scrubLocalization.js @@ -4,11 +4,11 @@ * @private */ module.exports = function scrubLocalization(data) { - return Object.keys(data).reduce((accumulator, k) => { - if (typeof data[k] === 'string') { - return Object.assign(accumulator, {[k]: ''}); - } else { - return Object.assign(accumulator, {[k]: scrubLocalization(data[k])}); - } - }, {}); + return Object.keys(data).reduce((accumulator, k) => { + if (typeof data[k] === 'string') { + return Object.assign(accumulator, {[k]: ''}); + } else { + return Object.assign(accumulator, {[k]: scrubLocalization(data[k])}); + } + }, {}); } diff --git a/src/scrubLocalization.test.js b/src/scrubLocalization.test.js index 67c0ddd..32b95eb 100644 --- a/src/scrubLocalization.test.js +++ b/src/scrubLocalization.test.js @@ -1,15 +1,15 @@ const scrubLocalization = require('./scrubLocalization'); describe('scrubLocalization', () => { - it('does nothing when already empty', () => { - expect(scrubLocalization({'a': ''})).toEqual({'a': ''}) - }); + it('does nothing when already empty', () => { + expect(scrubLocalization({'a': ''})).toEqual({'a': ''}) + }); - it('converts value to an empty string', () => { - expect(scrubLocalization({'a': 'b'})).toEqual({'a': ''}) - }); + it('converts value to an empty string', () => { + expect(scrubLocalization({'a': 'b'})).toEqual({'a': ''}) + }); - it('scrubs deep strings embedded in objects', () => { - expect(scrubLocalization({'a': {'b': 'c'}})).toEqual({'a': {'b': ''}}) - }); + it('scrubs deep strings embedded in objects', () => { + expect(scrubLocalization({'a': {'b': 'c'}})).toEqual({'a': {'b': ''}}) + }); }); diff --git a/src/startsWith.js b/src/startsWith.js index 4d912fe..865130e 100644 --- a/src/startsWith.js +++ b/src/startsWith.js @@ -6,5 +6,5 @@ * @private */ module.exports = function startsWith(haystack, index, needle) { - return haystack.substring(index, index + needle.length) === needle; + return haystack.substring(index, index + needle.length) === needle; } diff --git a/src/startsWith.test.js b/src/startsWith.test.js index 0c25329..adbda76 100644 --- a/src/startsWith.test.js +++ b/src/startsWith.test.js @@ -1,15 +1,15 @@ const startsWith = require('./startsWith'); describe('startsWith', () => { - it('matches', () => { - expect(startsWith('abc', 1, 'bc')).toBe(true); - }); + it('matches', () => { + expect(startsWith('abc', 1, 'bc')).toBe(true); + }); - it('doesn\'t match', () => { - expect(startsWith('abc', 0, 'bc')).toBe(false); - }); + it('doesn\'t match', () => { + expect(startsWith('abc', 0, 'bc')).toBe(false); + }); - it('matches blank', () => { - expect(startsWith('abc', 0, '')).toBe(true); - }); + it('matches blank', () => { + expect(startsWith('abc', 0, '')).toBe(true); + }); }); diff --git a/src/test.js b/src/test.js index 5e9ac39..e579483 100644 --- a/src/test.js +++ b/src/test.js @@ -13,486 +13,506 @@ const mocks = {}; const path = require('path'); describe('TranslationStaticAnalyzer', () => { - beforeEach(() => { - mocks.processOn = jest.spyOn(process, 'on'); - mocks.consoleLog = jest.spyOn(console, 'log'); - path.relative.mockImplementation((from, to) => { - return to; - }); - - path.resolve.mockImplementation((...parts) => { - return `${parts.join('/')}`; - }); + beforeEach(() => { + mocks.processOn = jest.spyOn(process, 'on'); + mocks.consoleLog = jest.spyOn(console, 'log'); + path.relative.mockImplementation((from, to) => { + return to; }); - afterEach(() => { - Object.keys(mocks).forEach((k) => { - mocks[k].mockRestore(); - delete mocks[k]; - }); + path.resolve.mockImplementation((...parts) => { + return `${parts.join('/')}`; + }); + }); - fs.mockReset(); + afterEach(() => { + Object.keys(mocks).forEach((k) => { + mocks[k].mockRestore(); + delete mocks[k]; }); - it('handles empty key gracefully', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test empty keys', - locales: ['existing'], - target: 'test directory targets', - }); + fs.mockReset(); + }); - fs.actions.length = 0; + it('handles empty key gracefully', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test empty keys', + locales: ['existing'], + target: 'test directory targets', + }); - analyzer.read(); + fs.actions.length = 0; - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/EmptyKeys/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('') + __n('') + __np('') + __p('');\n }\n};" - } - ]); + analyzer.read(); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/EmptyKeys/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('') + __n('') + __np('') + __p('');\n }\n};" + } + ]); + }); + + it('does nothing when write is called and there is no template', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', }); - it('does nothing when write is called and there is no template', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); + delete analyzer.referenceTemplate; + fs.actions.length = 0; - delete analyzer.referenceTemplate; - fs.actions.length = 0; + analyzer.write(); - analyzer.write(); + expect(fs.actions).toEqual([]); + }); - expect(fs.actions).toEqual([]); + it('filters out traslation strings accidentally placed where contexts should exist', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', }); - it('filters out traslation strings accidentally placed where contexts should exist', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.read(); - - fs.writeFileSync('./locales/existing.json', JSON.stringify({ - 'test key': 'test invalid localization' - })); - - fs.actions.length = 0; - - analyzer.write(); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\"test key\":\"test invalid localization\"}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": null - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\"Search\":\"\"}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{}" - }, - { - "action": "write", - "filename": "src/pages/About/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/application/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - } - ]); + analyzer.read(); + + fs.writeFileSync('./locales/existing.json', JSON.stringify({ + 'test key': 'test invalid localization' + })); + + fs.actions.length = 0; + + analyzer.write(); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\"test key\":\"test invalid localization\"}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\"Search\":\"\"}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/application/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + } + ]); + }); + + it("doesn't collapse the localization when there is a default and non-default context", () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', }); - it("doesn't collapse the localization when there is a default and non-default context", () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - - fs.writeFileSync('src/pages/Search/index.js', `export default __('test key') + __p('menuitem', 'test key');`); - - analyzer.read(); - - fs.writeFileSync('./locales/existing.json', JSON.stringify({ - 'test key': { - 'default': 'test default translation context', - 'menuitem': 'test menuitem translation context', - } - })); - - fs.actions.length = 0; - - analyzer.write(); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\"test key\":{\"default\":\"test default translation context\",\"menuitem\":\"test menuitem translation context\"}}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n \"default\": \"\"\n },\n \"test key\": {\n // src/pages/Search/index.js:0\n \"default\": \"test default translation context\",\n // src/pages/Search/index.js:0\n \"menuitem\": \"test menuitem translation context\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/pages/.locales/existing.json", - "data": "{\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n}" - }, - { - "action": "write", - "filename": "src/pages/.locales/index.json", - "data": "{\n \"existing\": {\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\"Search\":\"\"}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/index.json", - "data": "{\n \"existing\": {\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{}" - }, - { - "action": "write", - "filename": "src/pages/About/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/application/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - } - ]); - }); - it('works with defaults for language with some prefilled data', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.update(); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - }, - { - "action": "read", - "filename": "src/pages/About/index.js", - "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" - }, - { - "action": "read", - "filename": "src/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" - }, - { - "action": "read", - "filename": "src/test.js", - "data": null - }, - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\"Search\":{\"default\":\"検索\"},\"test unused key\":{\"default\":\"test value\"},\"Application\":{\"default\":\"アプリケーション\"}}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/pages/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "write", - "filename": "src/pages/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\"Search\":\"\"}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{}" - }, - { - "action": "write", - "filename": "src/pages/About/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "write", - "filename": "src/pages/About/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/application/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - }, - { - "action": "write", - "filename": "src/application/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" - } - ]); - - fs.actions.length = 0; - analyzer.update(); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - }, - { - "action": "read", - "filename": "src/pages/About/index.js", - "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" - }, - { - "action": "read", - "filename": "src/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" - }, - { - "action": "read", - "filename": "src/test.js", - "data": null - }, - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - } - ]); + fs.writeFileSync('src/pages/Search/index.js', `export default __('test key') + __p('menuitem', 'test key');`); + + analyzer.read(); + + fs.writeFileSync('./locales/existing.json', JSON.stringify({ + 'test key': { + 'default': 'test default translation context', + 'menuitem': 'test menuitem translation context', + } + })); + + fs.actions.length = 0; + + analyzer.write(); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\"test key\":{\"default\":\"test default translation context\",\"menuitem\":\"test menuitem translation context\"}}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n \"default\": \"\"\n },\n \"test key\": {\n // src/pages/Search/index.js:0\n \"default\": \"test default translation context\",\n // src/pages/Search/index.js:0\n \"menuitem\": \"test menuitem translation context\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/.locales/existing.json", + "data": "{\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n}" + }, + { + "action": "write", + "filename": "src/pages/.locales/index.json", + "data": "{\n \"existing\": {\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\"Search\":\"\"}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"existing\": {\n \"test key\": {\n \"default\": \"test default translation context\",\n \"menuitem\": \"test menuitem translation context\"\n }\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": null + }, + { + "action": "write", + "data": "{}", + "filename": "src/application/.locales/existing.json" + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + } + ]); + }); + + it('works with defaults for language with some prefilled data', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', }); - describe('read', () => { - it('reads all files', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - expect(analyzer.read()).toBe(true); - expect(fs.actions).toEqual( - [ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - }, - { - "action": "read", - "filename": "src/pages/About/index.js", - "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" - }, - { - "action": "read", - "filename": "src/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" - }, - { - "action": "read", - "filename": "src/test.js", - "data": null - } - ] - ); - }); - - it('reads one file', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - fs.actions.length = 0; - - expect(analyzer.read(['src/pages/Search/index.js'])).toBe(true); - - expect(fs.actions).toEqual( - [ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - } - ] - ); - }); + analyzer.update(); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + }, + { + "action": "read", + "filename": "src/pages/About/index.js", + "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" + }, + { + "action": "read", + "filename": "src/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" + }, + { + "action": "read", + "filename": "src/test.js", + "data": null + }, + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\"Search\":{\"default\":\"検索\"},\"test unused key\":{\"default\":\"test value\"},\"Application\":{\"default\":\"アプリケーション\"}}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "write", + "filename": "src/pages/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\"Search\":\"\"}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/application/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" + } + ]); + + fs.actions.length = 0; + analyzer.update(); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + }, + { + "action": "read", + "filename": "src/pages/About/index.js", + "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" + }, + { + "action": "read", + "filename": "src/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" + }, + { + "action": "read", + "filename": "src/test.js", + "data": null + }, + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + } + ]); + }); + + describe('read', () => { + it('reads all files', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); + + expect(analyzer.read()).toBe(true); + expect(fs.actions).toEqual( + [ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + }, + { + "action": "read", + "filename": "src/pages/About/index.js", + "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" + }, + { + "action": "read", + "filename": "src/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" + }, + { + "action": "read", + "filename": "src/test.js", + "data": null + } + ] + ); }); - describe('write', () => { - it('writes when existing files and no changes', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - fs.actions.length = 0; - analyzer.write(); - - expect(fs.actions).toEqual( - [ - ] - ); - }); + it('reads one file', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); + + fs.actions.length = 0; + + expect(analyzer.read(['src/pages/Search/index.js'])).toBe(true); + + expect(fs.actions).toEqual( + [ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + } + ] + ); + }); + }); + + describe('write', () => { + it('writes when existing files and no changes', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); + + fs.actions.length = 0; + analyzer.write(); + + expect(fs.actions).toEqual( + [ + ] + ); + }); + }); + + describe('update', () => { + it('updates, removing file', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); + + analyzer.update(); + + fs.actions.length = 0; + fs.unlinkSync('src/pages/Search/index.js'); + analyzer.options.files = 'test removed file'; + analyzer.options.target = 'test removed directory target'; + + analyzer.update(['src/pages/Search/index.js']); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + } + ]); }); - describe('update', () => { - it('updates, removing file', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.update(); - - fs.actions.length = 0; - fs.unlinkSync('src/pages/Search/index.js'); - analyzer.options.files = 'test removed file'; - analyzer.options.target = 'test removed directory target'; + it('updates metadata while two files reference same localization and one is removed', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); - analyzer.update(['src/pages/Search/index.js']); + analyzer.update(); - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - } - ]); - }); - - it('updates metadata while two files reference same localization and one is removed', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.update(); - - expect(fs.readFileSync('./locales/existing.json')).toEqual( + expect(fs.readFileSync('./locales/existing.json')).toEqual( `{ "%d result": { // NEW @@ -526,16 +546,16 @@ describe('TranslationStaticAnalyzer', () => { "default": "test value" } }` - ); + ); - fs.actions.length = 0; - fs.unlinkSync('src/pages/Search/index.js'); - analyzer.options.files = 'test removed file'; - analyzer.options.target = 'test removed directory target'; + fs.actions.length = 0; + fs.unlinkSync('src/pages/Search/index.js'); + analyzer.options.files = 'test removed file'; + analyzer.options.target = 'test removed directory target'; - analyzer.update(['src/pages/Search/index.js']); + analyzer.update(['src/pages/Search/index.js']); - expect(fs.readFileSync('./locales/existing.json')).toEqual( + expect(fs.readFileSync('./locales/existing.json')).toEqual( `{ "About": { // NEW @@ -555,216 +575,216 @@ describe('TranslationStaticAnalyzer', () => { "default": "test value" } }` - ); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - }, - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - } - ]); - }); - - it('removes unreadable source file', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.update(); - - fs.actions.length = 0; - const originalReadFileSync = fs.readFileSync; - - fs.readFileSync = (filename) => { - if (filename === 'src/pages/Search/index.js') { - const e = new Error("MockError: readFileSync issue"); + ); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + }, + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + } + ]); + }); - e.code = 'EEXIST'; + it('removes unreadable source file', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); + + analyzer.update(); + + fs.actions.length = 0; + const originalReadFileSync = fs.readFileSync; + + fs.readFileSync = (filename) => { + if (filename === 'src/pages/Search/index.js') { + const e = new Error("MockError: readFileSync issue"); + + e.code = 'EEXIST'; + + throw e; + } + + return originalReadFileSync(filename); + }; + + analyzer.update(['src/pages/Search/index.js']); + + fs.readFileSync = originalReadFileSync; + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" + } + ]); + }); - throw e; - } + it('updates, adding file', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); + + analyzer.update(); + + fs.writeFileSync('src/pages/Added/index.js', "__('Added')"); + fs.actions.length = 0; + analyzer.options.files = 'test added file'; + analyzer.options.target = 'test added directory target'; + + analyzer.update(['src/pages/Added/index.js']); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/Added/index.js", + "data": "__('Added')" + }, + { + "action": "read", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "write", + "filename": "./locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Added\": {\n // NEW\n // src/pages/Added/index.js:0\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + }, + { + "action": "read", + "filename": "src/pages/Added/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/Added/.locales/existing.json", + "data": "{\n \"Application\": \"アプリケーション\"\n}" + }, + { + "action": "write", + "filename": "src/pages/Added/.locales/index.json", + "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" + } + ]); + }); - return originalReadFileSync(filename); - }; + it('updates, updating file', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + }); - analyzer.update(['src/pages/Search/index.js']); + analyzer.update(); - fs.readFileSync = originalReadFileSync; + fs.writeFileSync('src/pages/Search/index.js', "__('Changed')"); + fs.actions.length = 0; - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n \"default\": \"検索\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "write", - "filename": "src/pages/About/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n }\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - }, - { - "action": "write", - "filename": "src/application/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" - } - ]); - }); - - it('updates, adding file', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.update(); - - fs.writeFileSync('src/pages/Added/index.js', "__('Added')"); - fs.actions.length = 0; - analyzer.options.files = 'test added file'; - analyzer.options.target = 'test added directory target'; - - analyzer.update(['src/pages/Added/index.js']); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/Added/index.js", - "data": "__('Added')" - }, - { - "action": "read", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "write", - "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Added\": {\n // NEW\n // src/pages/Added/index.js:0\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\",\n \"Search\": \"検索\"\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - }, - { - "action": "read", - "filename": "src/pages/Added/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/pages/Added/.locales/existing.json", - "data": "{\n \"Application\": \"アプリケーション\"\n}" - }, - { - "action": "write", - "filename": "src/pages/Added/.locales/index.json", - "data": "{\n \"existing\": {\n \"Application\": \"アプリケーション\"\n }\n}" - } - ]); - }); - - it('updates, updating file', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - }); - - analyzer.update(); - - fs.writeFileSync('src/pages/Search/index.js', "__('Changed')"); - fs.actions.length = 0; - - analyzer.update(['src/pages/Search/index.js']); - }); + analyzer.update(['src/pages/Search/index.js']); }); +}); - it('records debugging information', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - debug: true, - }); +it('records debugging information', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + debug: true, + }); - analyzer.update(); + analyzer.update(); - /* + /* expect(mocks.consoleLog.mock.calls).toEqual([ [ "translate-static-analyzer: Creating locale gen directory", @@ -830,264 +850,359 @@ describe('TranslationStaticAnalyzer', () => { ], ]); */ - }); +}); - it("rethrows unknown exception reading file", () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets' - }); +it("rethrows unknown exception reading file", () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets' + }); + + fs.readFileSync = jest.fn().mockImplementation((filename) => { + if (filename.endsWith('.json')) { + const e = new Error("MockError: readFileSync issue"); + e.code = 'TEST ERROR'; + throw e; + } - fs.readFileSync = jest.fn().mockImplementation((filename) => { - if (filename.endsWith('.json')) { - const e = new Error("MockError: readFileSync issue"); - e.code = 'TEST ERROR'; - throw e; - } + return ''; + }); - return ''; - }); + expect(() => analyzer.update()).toThrow(new Error("MockError: readFileSync issue")); +}); - expect(() => analyzer.update()).toThrow(new Error("MockError: readFileSync issue")); - }); +it('works with defaults for language with no prefilled data', () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['new'], + target: 'test directory targets' + }); - it('works with defaults for language with no prefilled data', () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['new'], - target: 'test directory targets' - }); - - analyzer.update(); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - }, - { - "action": "read", - "filename": "src/pages/About/index.js", - "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" - }, - { - "action": "read", - "filename": "src/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" - }, - { - "action": "read", - "filename": "src/test.js", - "data": null - }, - { - "action": "read", - "filename": "./locales/new.json", - "data": null - }, - { - "action": "write", - "filename": "./locales/new.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/new.json", - "data": null - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/new.json", - "data": null - }, - { - "action": "read", - "filename": "src/pages/About/.locales/new.json", - "data": null - }, - { - "action": "read", - "filename": "src/application/.locales/new.json", - "data": null - } - ]); - }); + analyzer.update(); - it("runs gracefully with no options", () => { - new TranslationStaticAnalyzer(); - }); + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + }, + { + "action": "read", + "filename": "src/pages/About/index.js", + "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" + }, + { + "action": "read", + "filename": "src/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" + }, + { + "action": "read", + "filename": "src/test.js", + "data": null + }, + { + "action": "read", + "filename": "./locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "./locales/new.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/.locales/index.json", + "data": "{\n \"new\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"new\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/About/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"new\": {}\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/application/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"new\": {}\n}" + } + ]); +}); - it("passing an empty files array will update everything", () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['new'], - target: 'test directory targets', - }); - - analyzer.update([]); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - }, - { - "action": "read", - "filename": "src/pages/About/index.js", - "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" - }, - { - "action": "read", - "filename": "src/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" - }, - { - "action": "read", - "filename": "src/test.js", - "data": null - }, - { - "action": "read", - "filename": "./locales/new.json", - "data": null - }, - { - "action": "write", - "filename": "./locales/new.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/new.json", - "data": null - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/new.json", - "data": null - }, - { - "action": "read", - "filename": "src/pages/About/.locales/new.json", - "data": null - }, - { - "action": "read", - "filename": "src/application/.locales/new.json", - "data": null - } - ]); - }); +it("runs gracefully with no options", () => { + new TranslationStaticAnalyzer(); +}); - it("updates nothing when nothing returns from the glob", () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test no files', - locales: ['new'], - target: 'test directory targets' - }); +it("passing an empty files array will update everything", () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['new'], + target: 'test directory targets', + }); - analyzer.update(); + analyzer.update([]); - expect(fs.actions).toEqual([]); - }); + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + }, + { + "action": "read", + "filename": "src/pages/About/index.js", + "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" + }, + { + "action": "read", + "filename": "src/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" + }, + { + "action": "read", + "filename": "src/test.js", + "data": null + }, + { + "action": "read", + "filename": "./locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "./locales/new.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/.locales/index.json", + "data": "{\n \"new\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"new\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/About/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"new\": {}\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/new.json", + "data": null + }, + { + "action": "write", + "filename": "src/application/.locales/new.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"new\": {}\n}" + } + ]); +}); - it("no locales runs gracefully", () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - target: 'test directory targets', - }); +it("updates nothing when nothing returns from the glob", () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test no files', + locales: ['new'], + target: 'test directory targets' + }); - analyzer.update([]); + analyzer.update(); - expect(fs.actions).toEqual([]); - }); + expect(fs.actions).toEqual([]); +}); + +it("no locales runs gracefully", () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + target: 'test directory targets', + }); + + analyzer.update([]); + + expect(fs.actions).toEqual([]); +}); - it("allows overriding the templates directory", () => { - const analyzer = new TranslationStaticAnalyzer({ - files: 'test files', - locales: ['existing'], - target: 'test directory targets', - templates: 'testtemplatespath' - }); - - analyzer.update(); - - expect(fs.actions).toEqual([ - { - "action": "read", - "filename": "src/pages/Search/index.js", - "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" - }, - { - "action": "read", - "filename": "src/pages/About/index.js", - "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" - }, - { - "action": "read", - "filename": "src/index.js", - "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" - }, - { - "action": "read", - "filename": "src/test.js", - "data": null - }, - { - "action": "read", - "filename": "testtemplatespath/locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "testtemplatespath/locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" - }, - { - "action": "read", - "filename": "src/pages/.locales/existing.json", - "data": null - }, - { - "action": "read", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{\"Search\":\"\"}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/existing.json", - "data": "{}" - }, - { - "action": "write", - "filename": "src/pages/Search/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - }, - { - "action": "read", - "filename": "src/pages/About/.locales/existing.json", - "data": "{}" - }, - { - "action": "write", - "filename": "src/pages/About/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - }, - { - "action": "read", - "filename": "src/application/.locales/existing.json", - "data": null - }, - { - "action": "write", - "filename": "src/application/.locales/index.json", - "data": "{\n \"existing\": {}\n}" - } - - ]); - }); +it("allows overriding the templates directory", () => { + const analyzer = new TranslationStaticAnalyzer({ + files: 'test files', + locales: ['existing'], + target: 'test directory targets', + templates: 'testtemplatespath' + }); + + analyzer.update(); + + expect(fs.actions).toEqual([ + { + "action": "read", + "filename": "src/pages/Search/index.js", + "data": "export default class SearchPage extends Component {\n static get title() {\n return __('Search');\n }\n\n static get template() {\n return '{{__('invalid''string')}} {{__p('menuitem', 'Search')}}
{{__n('%d result', '%d results', 2)}}
{{__np('footer', '%d view', '%d views', 23)}}';\n }\n};" + }, + { + "action": "read", + "filename": "src/pages/About/index.js", + "data": "export default class AboutPage extends Component {\n static get title() {\n return __('About');\n }\n\n static get template() {\n return
{{__('Search')}} Welcome to the about page!
';\n\n }\n};" + }, + { + "action": "read", + "filename": "src/index.js", + "data": "export default class Application extends Component {\n static get title() {\n return __('Application');\n }\n};" + }, + { + "action": "read", + "filename": "src/test.js", + "data": null + }, + { + "action": "read", + "filename": "testtemplatespath/locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "testtemplatespath/locales/existing.json", + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + }, + { + "action": "read", + "filename": "src/pages/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/pages/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{\"Search\":\"\"}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/Search/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/pages/About/.locales/existing.json", + "data": "{}" + }, + { + "action": "write", + "filename": "src/pages/About/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + }, + { + "action": "read", + "filename": "src/application/.locales/existing.json", + "data": null + }, + { + "action": "write", + "filename": "src/application/.locales/existing.json", + "data": "{}", + }, + { + "action": "write", + "filename": "src/application/.locales/index.json", + "data": "{\n \"existing\": {}\n}" + } + + ]); +}); }); diff --git a/src/update-translations.js b/src/update-translations.js new file mode 100644 index 0000000..4142e7d --- /dev/null +++ b/src/update-translations.js @@ -0,0 +1,87 @@ +#!/usr/bin/env node + +const ArgumentParser = require('@zakkudo/argument-parser'); +const TranslationStaticAnalyzer = require('.'); +const argv = process.argv.slice(2); +const path = require('path'); +const chokidar = require('chokidar'); + +const parse = new ArgumentParser({ + name: 'update-translations', + version: __VERSION__, + leftover: 'source-files-glob', + description: 'A console application for updating gettext style translations in a javscript application.', + schema: [{ + long: 'watch', + short: 'w', + type: 'boolean', + description: 'Update the translations as the files change. ctrl-c to quit.', + }, { + long: 'templates', + type: 'string', + typeName: 'path', + description: 'The output target of the developer centric translations. A \'locale\' directory will be created in this localition.', + default: '..' + }, { + long: 'target', + type: 'string', + typeName: 'glob', + description: 'The output target of the developer centric translations. A \'.locale\' directory will be created in this location.', + default: '.' + }, { + long: 'debug', + type: 'boolean', + description: 'Show debugging messages.' + }, { + long: 'locales', + short: 'l', + type: 'list', + typeName: 'es,fr', + description: 'The locales to generate translation templates for, comma separated.', + default: [] + }], +}); + +const parsed = parse(argv) +const files = (parsed.leftover || [])[0] || '**/*.js'; + +var analyzer = new TranslationStaticAnalyzer({ + debug: parsed.debug, + locales: parsed.locales, + target: parsed.target, + templates: parsed.templates, + files +}); + +let debounceTimeout; +let filenames = new Set(); + +function update(filename) { + filenames.add(filename); + clearTimeout(debounceTimeout); + debounceTimeout = setTimeout(() => { + analyzer.update(Array.from(filenames)); + filenames.clear(); + }, 100); +} + +if (parsed.watch) { + const templatesFilePattern = path.resolve(parsed.templates, 'locales', '*'); + + analyzer.read(); + analyzer.write(); + + chokidar.watch(files, {ignoreInitial: true}) + .on('add', update) + .on('change', update) + .on('unlink', update); + + chokidar.watch(templatesFilePattern, {ignoreInitial: true}) + .on('add', update) + .on('change', update) + .on('unlink', update); +} else { + analyzer.read(); + analyzer.write(); +} + diff --git a/yarn.lock b/yarn.lock index 1998a0c..0ab2aa7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,9 +2,9 @@ # yarn lockfile v1 -"@babel/cli@^7.0.0-beta.56": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.0.0.tgz#108b395fd43fff6681d36fb41274df4d8ffeb12e" +"@babel/cli@^7.2.3": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.2.3.tgz#1b262e42a3e959d28ab3d205ba2718e1923cfee6" dependencies: commander "^2.8.1" convert-source-map "^1.1.0" @@ -18,52 +18,36 @@ optionalDependencies: chokidar "^2.0.3" -"@babel/code-frame@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz#bd71d9b192af978df915829d39d4094456439a0c" - dependencies: - "@babel/highlight" "7.0.0-beta.51" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35": +"@babel/code-frame@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@^7.0.0-beta.56": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.0.0.tgz#0cb0c0fd2e78a0a2bec97698f549ae9ce0b99515" +"@babel/core@^7.1.0", "@babel/core@^7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.2.2.tgz#07adba6dde27bb5ad8d8672f15fde3e08184a687" dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.0.0" - "@babel/helpers" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/generator" "^7.2.2" + "@babel/helpers" "^7.2.0" + "@babel/parser" "^7.2.2" + "@babel/template" "^7.2.2" + "@babel/traverse" "^7.2.2" + "@babel/types" "^7.2.2" convert-source-map "^1.1.0" - debug "^3.1.0" - json5 "^0.5.0" + debug "^4.1.0" + json5 "^2.1.0" lodash "^4.17.10" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.51.tgz#6c7575ffde761d07485e04baedc0392c6d9e30f6" +"@babel/generator@^7.0.0", "@babel/generator@^7.2.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.2.tgz#fff31a7b2f2f3dad23ef8e01be45b0d5c2fc0132" dependencies: - "@babel/types" "7.0.0-beta.51" - jsesc "^2.5.1" - lodash "^4.17.5" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0.tgz#1efd58bffa951dc846449e58ce3a1d7f02d393aa" - dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.3.2" jsesc "^2.5.1" lodash "^4.17.10" source-map "^0.5.0" @@ -75,58 +59,44 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.0.0.tgz#ba26336beb2abb547d58b6eba5b84d77975a39eb" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" dependencies: - "@babel/helper-explode-assignable-expression" "^7.0.0" + "@babel/helper-explode-assignable-expression" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-call-delegate@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.0.0.tgz#e036956bb33d76e59c07a04a1fff144e9f62ab78" +"@babel/helper-call-delegate@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a" dependencies: "@babel/helper-hoist-variables" "^7.0.0" - "@babel/traverse" "^7.0.0" + "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-define-map@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.0.0.tgz#a5684dd2adf30f0137cf9b0bde436f8c2db17225" +"@babel/helper-define-map@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c" dependencies: - "@babel/helper-function-name" "^7.0.0" + "@babel/helper-function-name" "^7.1.0" "@babel/types" "^7.0.0" lodash "^4.17.10" -"@babel/helper-explode-assignable-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.0.0.tgz#fdfa4c88603ae3e954d0fc3244d5ca82fb468497" +"@babel/helper-explode-assignable-expression@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" dependencies: - "@babel/traverse" "^7.0.0" + "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-function-name@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.51.tgz#21b4874a227cf99ecafcc30a90302da5a2640561" - dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.51" - "@babel/template" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - -"@babel/helper-function-name@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0.tgz#a68cc8d04420ccc663dd258f9cc41b8261efa2d4" +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" dependencies: "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.0.0" + "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-get-function-arity@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.51.tgz#3281b2d045af95c172ce91b20825d85ea4676411" - dependencies: - "@babel/types" "7.0.0-beta.51" - "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -151,15 +121,15 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-module-transforms@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0.tgz#b01ee7d543e81e8c3fc404b19c9f26acb6e4cf4c" +"@babel/helper-module-transforms@^7.1.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz#ab2f8e8d231409f8370c883d20c335190284b963" dependencies: "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/template" "^7.2.2" + "@babel/types" "^7.2.2" lodash "^4.17.10" "@babel/helper-optimise-call-expression@^7.0.0": @@ -178,68 +148,54 @@ dependencies: lodash "^4.17.10" -"@babel/helper-remap-async-to-generator@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.0.0.tgz#6512273c2feb91587822335cf913fdf680c26901" +"@babel/helper-remap-async-to-generator@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" + "@babel/helper-wrap-function" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-replace-supers@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.0.0.tgz#b6f21237280e0be54f591f63a464b66627ced707" +"@babel/helper-replace-supers@^7.1.0": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz#19970020cf22677d62b3a689561dbd9644d8c5e5" dependencies: "@babel/helper-member-expression-to-functions" "^7.0.0" "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.0.0" + "@babel/traverse" "^7.2.3" "@babel/types" "^7.0.0" -"@babel/helper-simple-access@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.0.0.tgz#ff36a27983ae4c27122da2f7f294dced80ecbd08" +"@babel/helper-simple-access@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" dependencies: - "@babel/template" "^7.0.0" + "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.51.tgz#8a6c3f66c4d265352fc077484f9f6e80a51ab978" - dependencies: - "@babel/types" "7.0.0-beta.51" - "@babel/helper-split-export-declaration@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" dependencies: "@babel/types" "^7.0.0" -"@babel/helper-wrap-function@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.0.0.tgz#1c8e42a2cfb0808e3140189dfe9490782a6fa740" - dependencies: - "@babel/helper-function-name" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - -"@babel/helpers@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.0.0.tgz#7213388341eeb07417f44710fd7e1d00acfa6ac0" +"@babel/helper-wrap-function@^7.1.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" dependencies: - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/helper-function-name" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.2.0" -"@babel/highlight@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.51.tgz#e8844ae25a1595ccfd42b89623b4376ca06d225d" +"@babel/helpers@^7.2.0": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.3.1.tgz#949eec9ea4b45d3210feb7dc1c22db664c9e44b9" dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" + "@babel/template" "^7.1.2" + "@babel/traverse" "^7.1.5" + "@babel/types" "^7.3.0" "@babel/highlight@^7.0.0": version "7.0.0" @@ -249,214 +205,216 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.51.tgz#27cec2df409df60af58270ed8f6aa55409ea86f6" +"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.2.3": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.2.tgz#95cdeddfc3992a6ca2a1315191c1679ca32c55cd" -"@babel/parser@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0.tgz#697655183394facffb063437ddf52c0277698775" - -"@babel/plugin-proposal-async-generator-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.0.0.tgz#5d1eb6b44fd388b97f964350007ab9da090b1d70" +"@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.0.0" - "@babel/plugin-syntax-async-generators" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-json-strings@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz#3b4d7b5cf51e1f2e70f52351d28d44fc2970d01e" +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz#9a17b547f64d0676b6c9cecd4edf74a82ab85e7e" +"@babel/plugin-proposal-object-rest-spread@^7.3.1": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz#6d1859882d4d778578e41f82cc5d7bf3d5daf6c1" dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz#b610d928fe551ff7117d42c8bb410eec312a6425" +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" -"@babel/plugin-proposal-unicode-property-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz#498b39cd72536cd7c4b26177d030226eba08cd33" +"@babel/plugin-proposal-unicode-property-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz#abe7281fe46c95ddc143a65e5358647792039520" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.2.0" -"@babel/plugin-syntax-async-generators@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz#bf0891dcdbf59558359d0c626fdc9490e20bc13c" +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-json-strings@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz#0d259a68090e15b383ce3710e01d5b23f3770cbd" +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-object-rest-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b" +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-optional-catch-binding@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz#886f72008b3a8b185977f7cb70713b45e51ee475" +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-arrow-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz#a6c14875848c68a3b4b3163a486535ef25c7e749" +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-async-to-generator@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.0.0.tgz#feaf18f4bfeaf2236eea4b2d4879da83006cc8f5" +"@babel/plugin-transform-async-to-generator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz#68b8a438663e88519e65b776f8938f3445b1a2ff" dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" -"@babel/plugin-transform-block-scoped-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz#482b3f75103927e37288b3b67b65f848e2aa0d07" +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz#1745075edffd7cdaf69fab2fb6f9694424b7e9bc" +"@babel/plugin-transform-block-scoping@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz#f17c49d91eedbcdf5dd50597d16f5f2f770132d4" dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.10" -"@babel/plugin-transform-classes@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.0.0.tgz#9e65ca401747dde99e344baea90ab50dccb4c468" +"@babel/plugin-transform-classes@^7.2.0", "@babel/plugin-transform-classes@^7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz#6c90542f210ee975aa2aa8c8b5af7fa73a126953" dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.0.0" - "@babel/helper-function-name" "^7.0.0" + "@babel/helper-define-map" "^7.1.0" + "@babel/helper-function-name" "^7.1.0" "@babel/helper-optimise-call-expression" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.0.0" + "@babel/helper-replace-supers" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz#2fbb8900cd3e8258f2a2ede909b90e7556185e31" +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0.tgz#68e911e1935dda2f06b6ccbbf184ffb024e9d43a" +"@babel/plugin-transform-destructuring@^7.2.0": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz#f2f5520be055ba1c38c41c0e094d8a461dd78f2d" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-dotall-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz#73a24da69bc3c370251f43a3d048198546115e58" +"@babel/plugin-transform-dotall-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz#f0aabb93d120a8ac61e925ea0ba440812dbe0e49" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" -"@babel/plugin-transform-duplicate-keys@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz#a0601e580991e7cace080e4cf919cfd58da74e86" +"@babel/plugin-transform-duplicate-keys@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-exponentiation-operator@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.0.0.tgz#c51b45e090a01876f64d32b5b46c0799c85ea56c" +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-for-of@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz#f2ba4eadb83bd17dc3c7e9b30f4707365e1c3e39" +"@babel/plugin-transform-for-of@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz#ab7468befa80f764bb03d3cb5eef8cc998e1cad9" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-function-name@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.0.0.tgz#eeda18dc22584e13c3581a68f6be4822bb1d1d81" +"@babel/plugin-transform-function-name@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz#f7930362829ff99a3174c39f0afcc024ef59731a" dependencies: - "@babel/helper-function-name" "^7.0.0" + "@babel/helper-function-name" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-literals@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz#2aec1d29cdd24c407359c930cdd89e914ee8ff86" +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-amd@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.0.0.tgz#2430ab73db9960c4ca89966f425b803f5d0d0468" +"@babel/plugin-transform-modules-amd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6" dependencies: - "@babel/helper-module-transforms" "^7.0.0" + "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-commonjs@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0.tgz#20b906e5ab130dd8e456b694a94d9575da0fd41f" +"@babel/plugin-transform-modules-commonjs@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz#c4f1933f5991d5145e9cfad1dfd848ea1727f404" dependencies: - "@babel/helper-module-transforms" "^7.0.0" + "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" -"@babel/plugin-transform-modules-systemjs@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz#8873d876d4fee23209decc4d1feab8f198cf2df4" +"@babel/plugin-transform-modules-systemjs@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz#912bfe9e5ff982924c81d0937c92d24994bb9068" dependencies: "@babel/helper-hoist-variables" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-umd@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.0.0.tgz#e7bb4f2a6cd199668964241951a25013450349be" +"@babel/plugin-transform-modules-umd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" dependencies: - "@babel/helper-module-transforms" "^7.0.0" + "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-named-capturing-groups-regex@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz#140b52985b2d6ef0cb092ef3b29502b990f9cd50" + dependencies: + regexp-tree "^0.1.0" + "@babel/plugin-transform-new-target@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-object-super@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.0.0.tgz#b8587d511309b3a0e96e9e38169908b3e392041e" +"@babel/plugin-transform-object-super@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.0.0" + "@babel/helper-replace-supers" "^7.1.0" -"@babel/plugin-transform-parameters@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.0.0.tgz#da864efa111816a6df161d492f33de10e74b1949" +"@babel/plugin-transform-parameters@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz#0d5ad15dc805e2ea866df4dd6682bfe76d1408c2" dependencies: - "@babel/helper-call-delegate" "^7.0.0" + "@babel/helper-call-delegate" "^7.1.0" "@babel/helper-get-function-arity" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -466,168 +424,145 @@ dependencies: regenerator-transform "^0.13.3" -"@babel/plugin-transform-runtime@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.0.0.tgz#0f1443c07bac16dba8efa939e0c61d6922740062" +"@babel/plugin-transform-runtime@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.2.0.tgz#566bc43f7d0aedc880eaddbd29168d0f248966ea" dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" resolve "^1.8.1" + semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz#85f8af592dcc07647541a0350e8c95c7bf419d15" +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz#93583ce48dd8c85e53f3a46056c856e4af30b49b" +"@babel/plugin-transform-spread@^7.2.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-sticky-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz#30a9d64ac2ab46eec087b8530535becd90e73366" +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz#084f1952efe5b153ddae69eb8945f882c7a97c65" +"@babel/plugin-transform-template-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz#d87ed01b8eaac7a92473f608c97c089de2ba1e5b" dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-typeof-symbol@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz#4dcf1e52e943e5267b7313bff347fdbe0f81cec9" +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-unicode-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz#c6780e5b1863a76fe792d90eded9fcd5b51d68fc" +"@babel/plugin-transform-unicode-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz#4eb8db16f972f8abb5062c161b8b115546ade08b" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" -"@babel/preset-env@^7.0.0-beta.56": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.0.0.tgz#f450f200c14e713f98cb14d113bf0c2cfbb89ca9" +"@babel/preset-env@^7.0.0": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db" dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.0.0" - "@babel/plugin-proposal-json-strings" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.0.0" - "@babel/plugin-syntax-async-generators" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.0.0" - "@babel/plugin-transform-block-scoped-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-dotall-regex" "^7.0.0" - "@babel/plugin-transform-duplicate-keys" "^7.0.0" - "@babel/plugin-transform-exponentiation-operator" "^7.0.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-amd" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-modules-systemjs" "^7.0.0" - "@babel/plugin-transform-modules-umd" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.3.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.2.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.2.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.2.0" + "@babel/plugin-transform-classes" "^7.2.0" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.2.0" + "@babel/plugin-transform-dotall-regex" "^7.2.0" + "@babel/plugin-transform-duplicate-keys" "^7.2.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.2.0" + "@babel/plugin-transform-function-name" "^7.2.0" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.2.0" + "@babel/plugin-transform-modules-commonjs" "^7.2.0" + "@babel/plugin-transform-modules-systemjs" "^7.2.0" + "@babel/plugin-transform-modules-umd" "^7.2.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0" "@babel/plugin-transform-new-target" "^7.0.0" - "@babel/plugin-transform-object-super" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.2.0" + "@babel/plugin-transform-parameters" "^7.2.0" "@babel/plugin-transform-regenerator" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typeof-symbol" "^7.0.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - browserslist "^4.1.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.2.0" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.2.0" + browserslist "^4.3.4" invariant "^2.2.2" js-levenshtein "^1.1.3" semver "^5.3.0" -"@babel/runtime-corejs2@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.0.0.tgz#786711ee099c2c2af7875638866c1259eff30a8c" +"@babel/runtime-corejs2@^7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.3.1.tgz#0c113242e2328f9674d42703a89bee6ebebe9a82" dependencies: core-js "^2.5.7" regenerator-runtime "^0.12.0" -"@babel/template@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.51.tgz#9602a40aebcf357ae9677e2532ef5fc810f5fbff" - dependencies: - "@babel/code-frame" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - lodash "^4.17.5" - -"@babel/template@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0.tgz#c2bc9870405959c89a9c814376a2ecb247838c80" +"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/types" "^7.0.0" - -"@babel/traverse@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.51.tgz#981daf2cec347a6231d3aa1d9e1803b03aaaa4a8" - dependencies: - "@babel/code-frame" "7.0.0-beta.51" - "@babel/generator" "7.0.0-beta.51" - "@babel/helper-function-name" "7.0.0-beta.51" - "@babel/helper-split-export-declaration" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - debug "^3.1.0" - globals "^11.1.0" - invariant "^2.2.0" - lodash "^4.17.5" + "@babel/parser" "^7.2.2" + "@babel/types" "^7.2.2" -"@babel/traverse@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0.tgz#b1fe9b6567fdf3ab542cfad6f3b31f854d799a61" +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2", "@babel/traverse@^7.2.3": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8" dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.0.0" - "@babel/helper-function-name" "^7.0.0" + "@babel/generator" "^7.2.2" + "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/types" "^7.0.0" - debug "^3.1.0" + "@babel/parser" "^7.2.3" + "@babel/types" "^7.2.2" + debug "^4.1.0" globals "^11.1.0" lodash "^4.17.10" -"@babel/types@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.51.tgz#d802b7b543b5836c778aa691797abf00f3d97ea9" +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.2.tgz#424f5be4be633fff33fb83ab8d67e4a8290f5a2f" dependencies: esutils "^2.0.2" - lodash "^4.17.5" + lodash "^4.17.10" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0.tgz#6e191793d3c854d19c6749989e3bc55f0e962118" +"@zakkudo/argument-parser@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@zakkudo/argument-parser/-/argument-parser-0.0.1.tgz#10e6bcfff95a7de63f1cece8139951d75b900033" dependencies: - esutils "^2.0.2" - lodash "^4.17.10" - to-fast-properties "^2.0.0" + "@babel/runtime-corejs2" "^7.3.1" abab@^2.0.0: version "2.0.0" @@ -638,59 +573,46 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" acorn-globals@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" + version "4.3.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103" dependencies: - acorn "^5.0.0" + acorn "^6.0.1" + acorn-walk "^6.0.1" -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" +acorn-jsx@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" +acorn-walk@^6.0.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" -acorn@^5.0.0, acorn@^5.5.0, acorn@^5.5.3: - version "5.7.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5" +acorn@^5.5.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" +acorn@^6.0.1, acorn@^6.0.2: + version "6.0.7" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.7.tgz#490180ce18337270232d9488a44be83d9afb7fd3" -ajv@^5.2.3, ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" +ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.8.1.tgz#0890b93742985ebf8973cd365c5b23920ce3cb20" dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" + fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" ansi-escape-sequences@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-4.0.0.tgz#e0ecb042958b71e42942d35c1fcf1d9b00a0f67e" + version "4.0.1" + resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-4.0.1.tgz#6c3f85b55491c81cd7fc30c617a0cb2529a12efc" dependencies: array-back "^2.0.0" -ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" +ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" ansi-regex@^2.0.0: version "2.1.1" @@ -700,9 +622,9 @@ ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-regex@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" @@ -747,17 +669,11 @@ argv-tools@^0.1.1: array-back "^2.0.0" find-replace "^2.0.1" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" -arr-flatten@^1.0.1, arr-flatten@^1.1.0: +arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" @@ -781,25 +697,11 @@ array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" -arrify@^1.0.0, arrify@^1.0.1: +arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -821,7 +723,7 @@ astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" -async-each@^1.0.0: +async-each@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -829,11 +731,7 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@^1.4.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -async@^2.1.4: +async@^2.5.0, async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: @@ -855,163 +753,53 @@ aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.0, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - babel-core@^7.0.0-0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" -babel-generator@^6.18.0, babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" +babel-jest@^24.0.0, babel-jest@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190" dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" + babel-plugin-istanbul "^5.1.0" + babel-preset-jest "^24.1.0" + chalk "^2.4.2" + slash "^2.0.0" -babel-jest@^23.4.2: - version "23.4.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.4.2.tgz#f276de67798a5d68f2d6e87ff518c2f6e1609877" +babel-plugin-istanbul@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.0.tgz#6892f529eff65a3e2d33d87dc5888ffa2ecd4a30" dependencies: - babel-plugin-istanbul "^4.1.6" - babel-preset-jest "^23.2.0" + find-up "^3.0.0" + istanbul-lib-instrument "^3.0.0" + test-exclude "^5.0.0" -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" +babel-plugin-jest-hoist@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8" -babel-plugin-istanbul@^4.1.6: - version "4.1.6" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" +babel-plugin-transform-define@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.3.1.tgz#b21b7bad3b84cf8e3f07cdc8c660b99cbbc01213" dependencies: - babel-plugin-syntax-object-rest-spread "^6.13.0" - find-up "^2.1.0" - istanbul-lib-instrument "^1.10.1" - test-exclude "^4.2.1" - -babel-plugin-jest-hoist@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167" - -babel-plugin-syntax-object-rest-spread@^6.13.0: - version "6.13.0" - resolved "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + lodash "^4.17.11" + traverse "0.6.6" babel-plugin-transform-undefined-to-void@^6.9.4: version "6.9.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz#be241ca81404030678b748717322b89d0c8fe280" -babel-preset-jest@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46" +babel-preset-jest@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e" dependencies: - babel-plugin-jest-hoist "^23.2.0" - babel-plugin-syntax-object-rest-spread "^6.13.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + babel-plugin-jest-hoist "^24.1.0" babylon@7.0.0-beta.19: version "7.0.0-beta.19" resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.19.tgz#e928c7e807e970e0536b078ab3e0c48f9e052503" -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1035,12 +823,12 @@ bcrypt-pbkdf@^1.0.0: tweetnacl "^0.14.3" binary-extensions@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + version "1.13.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" bluebird@~3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" brace-expansion@^1.1.7: version "1.1.11" @@ -1049,15 +837,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -braces@^2.3.0, braces@^2.3.1: +braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: @@ -1073,8 +853,8 @@ braces@^2.3.0, braces@^2.3.1: to-regex "^3.0.1" browser-process-hrtime@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" + version "0.1.3" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" browser-resolve@^1.11.3: version "1.11.3" @@ -1082,13 +862,13 @@ browser-resolve@^1.11.3: dependencies: resolve "1.1.7" -browserslist@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.0.tgz#81cbb8e52dfa09918f93c6e051d779cb7360785d" +browserslist@^4.3.4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.1.tgz#42e828954b6b29a7a53e352277be429478a69062" dependencies: - caniuse-lite "^1.0.30000878" - electron-to-chromium "^1.3.61" - node-releases "^1.0.0-alpha.11" + caniuse-lite "^1.0.30000929" + electron-to-chromium "^1.3.103" + node-releases "^1.1.3" bser@^2.0.0: version "2.0.0" @@ -1100,10 +880,6 @@ buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" -builtin-modules@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -1126,31 +902,17 @@ cache-point@^0.4.1: fs-then-native "^2.0.0" mkdirp2 "^1.0.3" -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" +callsites@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +camelcase@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" -caniuse-lite@^1.0.30000878: - version "1.0.30000883" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000883.tgz#597c1eabfb379bd9fbeaa778632762eb574706ac" +caniuse-lite@^1.0.30000929: + version "1.0.30000935" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000935.tgz#d1b59df00b46f4921bb84a8a34c1d172b346df59" capture-exit@^1.2.0: version "1.2.0" @@ -1168,61 +930,43 @@ catharsis@~0.8.9: dependencies: underscore-contrib "~0.3.0" -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chalk@^1.1.3: - version "1.1.3" - resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" -chokidar@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" +chokidar@^2.0.3, chokidar@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.0.tgz#5fcb70d0b28ebe0867eb0f09d5f6a08f29a1efa0" dependencies: anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" + async-each "^1.0.1" + braces "^2.3.2" glob-parent "^3.1.0" - inherits "^2.0.1" + inherits "^2.0.3" is-binary-path "^1.0.0" is-glob "^4.0.0" - lodash.debounce "^4.0.8" - normalize-path "^2.1.1" + normalize-path "^3.0.0" path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.5" + readdirp "^2.2.1" + upath "^1.1.0" optionalDependencies: - fsevents "^1.2.2" + fsevents "^1.2.7" -chownr@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" +chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" -ci-info@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.4.0.tgz#4841d53cad49f11b827b648ebde27a6e189b412f" +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" circular-json@^0.3.1: version "0.3.3" @@ -1243,18 +987,19 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" @@ -1295,9 +1040,13 @@ color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -combined-stream@1.0.6, combined-stream@~1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" +colors@^1.1.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" dependencies: delayed-stream "~1.0.0" @@ -1331,6 +1080,10 @@ command-line-usage@^4.1.0: typical "^2.6.1" commander@^2.8.1: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + +commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -1338,7 +1091,7 @@ common-sequence@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/common-sequence/-/common-sequence-1.0.2.tgz#30e07f3f8f6f7f9b3dee854f20b2d39eee086de8" -compare-versions@^3.1.0: +compare-versions@^3.2.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" @@ -1350,15 +1103,6 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - config-master@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/config-master/-/config-master-3.1.0.tgz#667663590505a283bf26a484d68489d74c5485da" @@ -1369,33 +1113,37 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" +convert-source-map@^1.1.0, convert-source-map@^1.4.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + dependencies: + safe-buffer "~5.1.1" copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" -core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" +core-js@^2.5.7: + version "2.6.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.3.tgz#4b70938bdffdaf64931e66e2db158f0892289c49" core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -cross-spawn@^5.0.1, cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: - lru-cache "^4.0.1" + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" shebang-command "^1.2.0" which "^1.2.9" cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797" + version "0.3.6" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.6.tgz#f85206cee04efa841f3c5982a74ba96ab20d65ad" cssstyle@^1.0.0: version "1.1.1" @@ -1410,26 +1158,26 @@ dashdash@^1.12.0: assert-plus "^1.0.0" data-urls@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.1.tgz#d416ac3896918f29ca84d81085bc3705834da579" + version "1.1.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" dependencies: abab "^2.0.0" - whatwg-mimetype "^2.1.0" + whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" dependencies: - ms "2.0.0" + ms "^2.1.1" -decamelize@^1.0.0, decamelize@^1.1.1: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1480,18 +1228,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1500,12 +1236,6 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -1514,13 +1244,13 @@ detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" -diff@^3.2.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" +diff-sequences@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013" dmd@^3.0.10: - version "3.0.12" - resolved "https://registry.yarnpkg.com/dmd/-/dmd-3.0.12.tgz#2aad884cd582287f7dc748435017c7dbd510fe0c" + version "3.0.13" + resolved "https://registry.yarnpkg.com/dmd/-/dmd-3.0.13.tgz#73294e8fae1a7a1a1c849d86b027adf04fbd5662" dependencies: array-back "^2.0.0" cache-point "^0.4.1" @@ -1554,9 +1284,15 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.3.61: - version "1.3.62" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.62.tgz#2e8e2dc070c800ec8ce23ff9dfcceb585d6f9ed8" +electron-to-chromium@^1.3.103: + version "1.3.113" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9" + +end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" error-ex@^1.3.1: version "1.3.2" @@ -1565,24 +1301,25 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.5.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" dependencies: - es-to-primitive "^1.1.1" + es-to-primitive "^1.2.0" function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" + has "^1.0.3" + is-callable "^1.1.4" is-regex "^1.0.4" + object-keys "^1.0.12" -es-to-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" dependencies: - is-callable "^1.1.1" + is-callable "^1.1.4" is-date-object "^1.0.1" - is-symbol "^1.0.1" + is-symbol "^1.0.2" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5: +escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1598,34 +1335,34 @@ escodegen@^1.9.1: source-map "~0.6.1" eslint-plugin-es@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz#5acb2565db4434803d1d46a9b4cbc94b345bd028" + version "1.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz#475f65bb20c993fc10e8c8fe77d1d60068072da6" dependencies: eslint-utils "^1.3.0" - regexpp "^2.0.0" + regexpp "^2.0.1" eslint-plugin-jasmine@^2.10.1: version "2.10.1" resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.10.1.tgz#5733b709e751f4bc40e31e1c16989bd2cdfbec97" -eslint-plugin-jest@^21.21.0: - version "21.22.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-21.22.0.tgz#1b9e49b3e5ce9a3d0a51af4579991d517f33726e" +eslint-plugin-jest@^22.1.3: + version "22.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.2.2.tgz#2a80d70a20c27dfb1503a6f32cdcb647fe5476df" -eslint-plugin-node@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz#a6e054e50199b2edd85518b89b4e7b323c9f36db" +eslint-plugin-node@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz#55ae3560022863d141fa7a11799532340a685964" dependencies: eslint-plugin-es "^1.3.1" eslint-utils "^1.3.1" - ignore "^4.0.2" + ignore "^5.0.2" minimatch "^3.0.4" resolve "^1.8.1" semver "^5.5.0" -eslint-scope@^3.7.1: - version "3.7.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -1638,55 +1375,54 @@ eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" -eslint@^4.19.1: - version "4.19.1" - resolved "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" +eslint@^5.12.1: + version "5.13.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.13.0.tgz#ce71cc529c450eed9504530939aa97527861ede9" dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" + "@babel/code-frame" "^7.0.0" + ajv "^6.5.3" chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" doctrine "^2.1.0" - eslint-scope "^3.7.1" + eslint-scope "^4.0.0" + eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^3.5.4" - esquery "^1.0.0" + espree "^5.0.0" + esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" + inquirer "^6.1.0" + js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" + lodash "^4.17.5" + minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^7.0.0" progress "^2.0.0" - regexpp "^1.0.1" - require-uncached "^1.0.3" - semver "^5.3.0" + regexpp "^2.0.1" + semver "^5.5.1" strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" + strip-json-comments "^2.0.1" + table "^5.0.2" + text-table "^0.2.0" -espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" +espree@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.0.tgz#fc7f984b62b36a0f543b13fb9cd7b9f4a7f5b65c" dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" + acorn "^6.0.2" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" esprima@^3.1.3: version "3.1.3" @@ -1696,7 +1432,7 @@ esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" -esquery@^1.0.0: +esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" dependencies: @@ -1722,12 +1458,12 @@ exec-sh@^0.2.0: dependencies: merge "^1.2.0" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" + cross-spawn "^6.0.0" + get-stream "^4.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" @@ -1738,12 +1474,6 @@ exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -1756,22 +1486,15 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -expect@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-23.5.0.tgz#18999a0eef8f8acf99023fde766d9c323c2562ed" +expect@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2" dependencies: ansi-styles "^3.2.0" - jest-diff "^23.5.0" - jest-get-type "^22.1.0" - jest-matcher-utils "^23.5.0" - jest-message-util "^23.4.0" - jest-regex-util "^23.3.0" + jest-get-type "^24.0.0" + jest-matcher-utils "^24.0.0" + jest-message-util "^24.0.0" + jest-regex-util "^24.0.0" extend-shallow@^2.0.1: version "2.0.1" @@ -1790,20 +1513,14 @@ extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" -external-editor@^2.0.4: - version "2.2.0" - resolved "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" +external-editor@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" + chardet "^0.7.0" + iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -1825,9 +1542,9 @@ extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" fast-json-stable-stringify@^2.0.0: version "2.0.0" @@ -1857,33 +1574,19 @@ file-entry-cache@^2.0.0: object-assign "^4.0.1" file-set@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-set/-/file-set-2.0.0.tgz#11831a388ec378aba881311a94f69814118849c3" + version "2.0.1" + resolved "https://registry.yarnpkg.com/file-set/-/file-set-2.0.1.tgz#db9bc4b70a7e5ba81c9d279c20a37f13369c7850" dependencies: array-back "^2.0.0" - glob "^7.1.2" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + glob "^7.1.3" -fileset@^2.0.2: +fileset@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" dependencies: glob "^7.0.3" minimatch "^3.0.3" -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1900,41 +1603,35 @@ find-replace@^2.0.1: array-back "^2.0.0" test-value "^3.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" dependencies: - locate-path "^2.0.0" + locate-path "^3.0.0" flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" dependencies: circular-json "^0.3.1" - del "^2.0.2" graceful-fs "^4.1.2" + rimraf "~2.6.2" write "^0.2.1" -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" dependencies: asynckit "^0.4.0" - combined-stream "1.0.6" + combined-stream "^1.0.6" mime-types "^2.1.12" fragment-cache@^0.2.1: @@ -1943,9 +1640,9 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fs-extra@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -1969,9 +1666,9 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@^1.2.2, fsevents@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" +fsevents@^1.2.3, fsevents@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -2001,9 +1698,11 @@ get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + dependencies: + pump "^3.0.0" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" @@ -2015,19 +1714,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -2035,7 +1721,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" dependencies: @@ -2046,68 +1732,47 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.0.1, globals@^11.1.0: - version "11.7.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" +globals@^11.1.0, globals@^11.7.0: + version "11.10.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.10.0.tgz#1e09776dffda5e01816b3bb4077c8b59c24eaa50" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" handlebars@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" + version "4.0.12" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" dependencies: - async "^1.4.0" + async "^2.5.0" optimist "^0.6.1" - source-map "^0.4.4" + source-map "^0.6.1" optionalDependencies: - uglify-js "^2.6" + uglify-js "^3.1.4" har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" dependencies: - ajv "^5.3.0" + ajv "^6.5.5" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -2139,19 +1804,12 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1: +has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: function-bind "^1.1.1" -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" @@ -2170,13 +1828,7 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.4.17, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" dependencies: @@ -2188,19 +1840,26 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.3: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - -ignore@^4.0.2: +ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" -import-local@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" +ignore@^5.0.2: + version "5.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" + +import-fresh@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" dependencies: - pkg-dir "^2.0.0" + pkg-dir "^3.0.0" resolve-cwd "^2.0.0" imurmurhash@^0.1.4: @@ -2214,7 +1873,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -2222,34 +1881,37 @@ ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inquirer@^3.0.6: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" +inquirer@^6.1.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" + ansi-escapes "^3.2.0" + chalk "^2.4.2" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^2.0.4" + external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.3.0" + lodash "^4.17.11" mute-stream "0.0.7" run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" + rxjs "^6.4.0" string-width "^2.1.0" - strip-ansi "^4.0.0" + strip-ansi "^5.0.0" through "^2.3.6" -invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.4: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: loose-envify "^1.0.0" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" is-accessor-descriptor@^0.1.6: version "0.1.6" @@ -2277,21 +1939,15 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-callable@^1.1.1, is-callable@^1.1.3: +is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" -is-ci@^1.0.10: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.0.tgz#3f4a08d6303a09882cef3f0fb97439c5f5ce2d53" +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" dependencies: - ci-info "^1.3.0" + ci-info "^2.0.0" is-data-descriptor@^0.1.4: version "0.1.4" @@ -2325,16 +1981,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -2345,20 +1991,10 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -2369,15 +2005,9 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" -is-generator-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" +is-generator-fn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" is-glob@^3.1.0: version "3.1.0" @@ -2391,38 +2021,12 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - dependencies: - path-is-inside "^1.0.1" - is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -2433,14 +2037,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -2451,17 +2047,15 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" -is-symbol@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + dependencies: + has-symbols "^1.0.0" is-typedarray@~1.0.0: version "1.0.0" @@ -2471,6 +2065,10 @@ is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2493,391 +2091,383 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-api@^1.3.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.6.tgz#0c695f17e533131de8c49e0657175dcfd8af8a8f" - dependencies: - async "^2.1.4" - compare-versions "^3.1.0" - fileset "^2.0.2" - istanbul-lib-coverage "^1.2.0" - istanbul-lib-hook "^1.2.0" - istanbul-lib-instrument "^2.1.0" - istanbul-lib-report "^1.1.4" - istanbul-lib-source-maps "^1.2.5" - istanbul-reports "^1.4.1" - js-yaml "^3.7.0" - mkdirp "^0.5.1" +istanbul-api@^2.0.8: + version "2.1.0" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.0.tgz#37ab0c2c3e83065462f5254b94749d6157846c4e" + dependencies: + async "^2.6.1" + compare-versions "^3.2.1" + fileset "^2.0.3" + istanbul-lib-coverage "^2.0.3" + istanbul-lib-hook "^2.0.3" + istanbul-lib-instrument "^3.1.0" + istanbul-lib-report "^2.0.4" + istanbul-lib-source-maps "^3.0.2" + istanbul-reports "^2.1.0" + js-yaml "^3.12.0" + make-dir "^1.3.0" + minimatch "^3.0.4" once "^1.4.0" -istanbul-lib-coverage@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" - -istanbul-lib-coverage@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda" +istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba" -istanbul-lib-hook@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz#f614ec45287b2a8fc4f07f5660af787575601805" +istanbul-lib-hook@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb" dependencies: append-transform "^1.0.0" -istanbul-lib-instrument@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b" +istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971" dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.2.0" - semver "^5.3.0" - -istanbul-lib-instrument@^2.1.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-2.3.2.tgz#b287cbae2b5f65f3567b05e2e29b275eaf92d25e" - dependencies: - "@babel/generator" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/template" "7.0.0-beta.51" - "@babel/traverse" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - istanbul-lib-coverage "^2.0.1" + "@babel/generator" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + istanbul-lib-coverage "^2.0.3" semver "^5.5.0" -istanbul-lib-report@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz#e886cdf505c4ebbd8e099e4396a90d0a28e2acb5" +istanbul-lib-report@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz#bfd324ee0c04f59119cb4f07dab157d09f24d7e4" dependencies: - istanbul-lib-coverage "^1.2.0" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" + istanbul-lib-coverage "^2.0.3" + make-dir "^1.3.0" + supports-color "^6.0.0" -istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1" +istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156" dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^1.2.0" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" + debug "^4.1.1" + istanbul-lib-coverage "^2.0.3" + make-dir "^1.3.0" + rimraf "^2.6.2" + source-map "^0.6.1" -istanbul-reports@^1.4.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.0.tgz#c6c2867fa65f59eb7dcedb7f845dfc76aaee70f9" +istanbul-reports@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.0.tgz#87b8b55cd1901ba1748964c98ddd8900ce306d59" dependencies: handlebars "^4.0.11" -jest-changed-files@^23.4.2: - version "23.4.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83" +jest-changed-files@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0.tgz#c02c09a8cc9ca93f513166bc773741bd39898ff7" dependencies: + execa "^1.0.0" throat "^4.0.0" -jest-cli@^23.4.2, jest-cli@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.5.0.tgz#d316b8e34a38a610a1efc4f0403d8ef8a55e4492" +jest-cli@^24.0.0, jest-cli@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.1.0.tgz#f7cc98995f36e7210cce3cbb12974cbf60940843" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.2" - graceful-fs "^4.1.11" - import-local "^1.0.0" - is-ci "^1.0.10" - istanbul-api "^1.3.1" - istanbul-lib-coverage "^1.2.0" - istanbul-lib-instrument "^1.10.1" - istanbul-lib-source-maps "^1.2.4" - jest-changed-files "^23.4.2" - jest-config "^23.5.0" - jest-environment-jsdom "^23.4.0" - jest-get-type "^22.1.0" - jest-haste-map "^23.5.0" - jest-message-util "^23.4.0" - jest-regex-util "^23.3.0" - jest-resolve-dependencies "^23.5.0" - jest-runner "^23.5.0" - jest-runtime "^23.5.0" - jest-snapshot "^23.5.0" - jest-util "^23.4.0" - jest-validate "^23.5.0" - jest-watcher "^23.4.0" - jest-worker "^23.2.0" - micromatch "^2.3.11" + graceful-fs "^4.1.15" + import-local "^2.0.0" + is-ci "^2.0.0" + istanbul-api "^2.0.8" + istanbul-lib-coverage "^2.0.2" + istanbul-lib-instrument "^3.0.1" + istanbul-lib-source-maps "^3.0.1" + jest-changed-files "^24.0.0" + jest-config "^24.1.0" + jest-environment-jsdom "^24.0.0" + jest-get-type "^24.0.0" + jest-haste-map "^24.0.0" + jest-message-util "^24.0.0" + jest-regex-util "^24.0.0" + jest-resolve-dependencies "^24.1.0" + jest-runner "^24.1.0" + jest-runtime "^24.1.0" + jest-snapshot "^24.1.0" + jest-util "^24.0.0" + jest-validate "^24.0.0" + jest-watcher "^24.0.0" + jest-worker "^24.0.0" + micromatch "^3.1.10" node-notifier "^5.2.1" - prompts "^0.1.9" + p-each-series "^1.0.0" + pirates "^4.0.0" + prompts "^2.0.1" realpath-native "^1.0.0" rimraf "^2.5.4" - slash "^1.0.0" + slash "^2.0.0" string-length "^2.0.0" - strip-ansi "^4.0.0" + strip-ansi "^5.0.0" which "^1.2.12" - yargs "^11.0.0" + yargs "^12.0.2" -jest-config@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.5.0.tgz#3770fba03f7507ee15f3b8867c742e48f31a9773" +jest-config@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.1.0.tgz#6ea6881cfdd299bc86cc144ee36d937c97c3850c" dependencies: - babel-core "^6.0.0" - babel-jest "^23.4.2" + "@babel/core" "^7.1.0" + babel-jest "^24.1.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^23.4.0" - jest-environment-node "^23.4.0" - jest-get-type "^22.1.0" - jest-jasmine2 "^23.5.0" - jest-regex-util "^23.3.0" - jest-resolve "^23.5.0" - jest-util "^23.4.0" - jest-validate "^23.5.0" - micromatch "^2.3.11" - pretty-format "^23.5.0" - -jest-diff@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.5.0.tgz#250651a433dd0050290a07642946cc9baaf06fba" + jest-environment-jsdom "^24.0.0" + jest-environment-node "^24.0.0" + jest-get-type "^24.0.0" + jest-jasmine2 "^24.1.0" + jest-regex-util "^24.0.0" + jest-resolve "^24.1.0" + jest-util "^24.0.0" + jest-validate "^24.0.0" + micromatch "^3.1.10" + pretty-format "^24.0.0" + realpath-native "^1.0.2" + +jest-diff@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34" dependencies: chalk "^2.0.1" - diff "^3.2.0" - jest-get-type "^22.1.0" - pretty-format "^23.5.0" + diff-sequences "^24.0.0" + jest-get-type "^24.0.0" + pretty-format "^24.0.0" -jest-docblock@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7" +jest-docblock@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0.tgz#54d77a188743e37f62181a91a01eb9222289f94e" dependencies: detect-newline "^2.1.0" -jest-each@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.5.0.tgz#77f7e2afe6132a80954b920006e78239862b10ba" +jest-each@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55" dependencies: chalk "^2.0.1" - pretty-format "^23.5.0" + jest-get-type "^24.0.0" + jest-util "^24.0.0" + pretty-format "^24.0.0" -jest-environment-jsdom@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023" +jest-environment-jsdom@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz#5affa0654d6e44cd798003daa1a8701dbd6e4d11" dependencies: - jest-mock "^23.2.0" - jest-util "^23.4.0" + jest-mock "^24.0.0" + jest-util "^24.0.0" jsdom "^11.5.1" -jest-environment-node@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10" +jest-environment-node@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0.tgz#330948980656ed8773ce2e04eb597ed91e3c7190" dependencies: - jest-mock "^23.2.0" - jest-util "^23.4.0" + jest-mock "^24.0.0" + jest-util "^24.0.0" -jest-get-type@^22.1.0: - version "22.4.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" +jest-get-type@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0.tgz#36e72930b78e33da59a4f63d44d332188278940b" -jest-haste-map@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.5.0.tgz#d4ca618188bd38caa6cb20349ce6610e194a8065" +jest-haste-map@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0.tgz#e9ef51b2c9257384b4d6beb83bd48c65b37b5e6e" dependencies: fb-watchman "^2.0.0" - graceful-fs "^4.1.11" + graceful-fs "^4.1.15" invariant "^2.2.4" - jest-docblock "^23.2.0" - jest-serializer "^23.0.1" - jest-worker "^23.2.0" - micromatch "^2.3.11" - sane "^2.0.0" + jest-serializer "^24.0.0" + jest-util "^24.0.0" + jest-worker "^24.0.0" + micromatch "^3.1.10" + sane "^3.0.0" -jest-jasmine2@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.5.0.tgz#05fe7f1788e650eeb5a03929e6461ea2e9f3db53" +jest-jasmine2@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz#8377324b967037c440f0a549ee0bbd9912055db6" dependencies: - babel-traverse "^6.0.0" + "@babel/traverse" "^7.1.0" chalk "^2.0.1" co "^4.6.0" - expect "^23.5.0" - is-generator-fn "^1.0.0" - jest-diff "^23.5.0" - jest-each "^23.5.0" - jest-matcher-utils "^23.5.0" - jest-message-util "^23.4.0" - jest-snapshot "^23.5.0" - jest-util "^23.4.0" - pretty-format "^23.5.0" - -jest-leak-detector@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.5.0.tgz#14ac2a785bd625160a2ea968fd5d98b7dcea3e64" - dependencies: - pretty-format "^23.5.0" - -jest-matcher-utils@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.5.0.tgz#0e2ea67744cab78c9ab15011c4d888bdd3e49e2a" + expect "^24.1.0" + is-generator-fn "^2.0.0" + jest-each "^24.0.0" + jest-matcher-utils "^24.0.0" + jest-message-util "^24.0.0" + jest-snapshot "^24.1.0" + jest-util "^24.0.0" + pretty-format "^24.0.0" + throat "^4.0.0" + +jest-leak-detector@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz#78280119fd05ee98317daee62cddb3aa537a31c6" + dependencies: + pretty-format "^24.0.0" + +jest-matcher-utils@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz#fc9c41cfc49b2c3ec14e576f53d519c37729d579" dependencies: chalk "^2.0.1" - jest-get-type "^22.1.0" - pretty-format "^23.5.0" + jest-diff "^24.0.0" + jest-get-type "^24.0.0" + pretty-format "^24.0.0" -jest-message-util@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f" +jest-message-util@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0.tgz#a07a141433b2c992dbaec68d4cbfe470ba289619" dependencies: - "@babel/code-frame" "^7.0.0-beta.35" + "@babel/code-frame" "^7.0.0" chalk "^2.0.1" - micromatch "^2.3.11" - slash "^1.0.0" + micromatch "^3.1.10" + slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134" +jest-mock@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0.tgz#9a4b53e01d66a0e780f7d857462d063e024c617d" -jest-regex-util@^23.3.0: - version "23.3.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5" +jest-regex-util@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0.tgz#4feee8ec4a358f5bee0a654e94eb26163cb9089a" -jest-resolve-dependencies@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.5.0.tgz#10c4d135beb9d2256de1fedc7094916c3ad74af7" +jest-resolve-dependencies@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz#78f738a2ec59ff4d00751d9da56f176e3f589f6c" dependencies: - jest-regex-util "^23.3.0" - jest-snapshot "^23.5.0" + jest-regex-util "^24.0.0" + jest-snapshot "^24.1.0" -jest-resolve@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.5.0.tgz#3b8e7f67e84598f0caf63d1530bd8534a189d0e6" +jest-resolve@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.1.0.tgz#42ff0169b0ea47bfdbd0c52a0067ca7d022c7688" dependencies: browser-resolve "^1.11.3" chalk "^2.0.1" realpath-native "^1.0.0" -jest-runner@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.5.0.tgz#570f7a044da91648b5bb9b6baacdd511076c71d7" +jest-runner@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.1.0.tgz#3686a2bb89ce62800da23d7fdc3da2c32792943b" dependencies: + chalk "^2.4.2" exit "^0.1.2" - graceful-fs "^4.1.11" - jest-config "^23.5.0" - jest-docblock "^23.2.0" - jest-haste-map "^23.5.0" - jest-jasmine2 "^23.5.0" - jest-leak-detector "^23.5.0" - jest-message-util "^23.4.0" - jest-runtime "^23.5.0" - jest-util "^23.4.0" - jest-worker "^23.2.0" + graceful-fs "^4.1.15" + jest-config "^24.1.0" + jest-docblock "^24.0.0" + jest-haste-map "^24.0.0" + jest-jasmine2 "^24.1.0" + jest-leak-detector "^24.0.0" + jest-message-util "^24.0.0" + jest-runtime "^24.1.0" + jest-util "^24.0.0" + jest-worker "^24.0.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.5.0.tgz#eb503525a196dc32f2f9974e3482d26bdf7b63ce" +jest-runtime@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.1.0.tgz#7c157a2e776609e8cf552f956a5a19ec9c985214" dependencies: - babel-core "^6.0.0" - babel-plugin-istanbul "^4.1.6" + "@babel/core" "^7.1.0" + babel-plugin-istanbul "^5.1.0" chalk "^2.0.1" convert-source-map "^1.4.0" exit "^0.1.2" fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.1.11" - jest-config "^23.5.0" - jest-haste-map "^23.5.0" - jest-message-util "^23.4.0" - jest-regex-util "^23.3.0" - jest-resolve "^23.5.0" - jest-snapshot "^23.5.0" - jest-util "^23.4.0" - jest-validate "^23.5.0" - micromatch "^2.3.11" + glob "^7.1.3" + graceful-fs "^4.1.15" + jest-config "^24.1.0" + jest-haste-map "^24.0.0" + jest-message-util "^24.0.0" + jest-regex-util "^24.0.0" + jest-resolve "^24.1.0" + jest-snapshot "^24.1.0" + jest-util "^24.0.0" + jest-validate "^24.0.0" + micromatch "^3.1.10" realpath-native "^1.0.0" - slash "^1.0.0" - strip-bom "3.0.0" - write-file-atomic "^2.1.0" - yargs "^11.0.0" + slash "^2.0.0" + strip-bom "^3.0.0" + write-file-atomic "2.4.1" + yargs "^12.0.2" -jest-serializer@^23.0.1: - version "23.0.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165" +jest-serializer@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0.tgz#522c44a332cdd194d8c0531eb06a1ee5afb4256b" -jest-snapshot@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.5.0.tgz#cc368ebd8513e1175e2a7277f37a801b7358ae79" +jest-snapshot@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.1.0.tgz#85e22f810357aa5994ab61f236617dc2205f2f5b" dependencies: - babel-types "^6.0.0" + "@babel/types" "^7.0.0" chalk "^2.0.1" - jest-diff "^23.5.0" - jest-matcher-utils "^23.5.0" - jest-message-util "^23.4.0" - jest-resolve "^23.5.0" + jest-diff "^24.0.0" + jest-matcher-utils "^24.0.0" + jest-message-util "^24.0.0" + jest-resolve "^24.1.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^23.5.0" + pretty-format "^24.0.0" semver "^5.5.0" -jest-util@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561" +jest-util@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0.tgz#fd38fcafd6dedbd0af2944d7a227c0d91b68f7d6" dependencies: - callsites "^2.0.0" + callsites "^3.0.0" chalk "^2.0.1" - graceful-fs "^4.1.11" - is-ci "^1.0.10" - jest-message-util "^23.4.0" + graceful-fs "^4.1.15" + is-ci "^2.0.0" + jest-message-util "^24.0.0" mkdirp "^0.5.1" - slash "^1.0.0" + slash "^2.0.0" source-map "^0.6.0" -jest-validate@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.5.0.tgz#f5df8f761cf43155e1b2e21d6e9de8a2852d0231" +jest-validate@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0.tgz#aa8571a46983a6538328fef20406b4a496b6c020" dependencies: + camelcase "^5.0.0" chalk "^2.0.1" - jest-get-type "^22.1.0" + jest-get-type "^24.0.0" leven "^2.1.0" - pretty-format "^23.5.0" + pretty-format "^24.0.0" -jest-watcher@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c" +jest-watcher@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0.tgz#20d44244d10b0b7312410aefd256c1c1eef68890" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" + jest-util "^24.0.0" string-length "^2.0.0" -jest-worker@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9" +jest-worker@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d" dependencies: merge-stream "^1.0.1" + supports-color "^6.1.0" -jest@^23.4.2: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-23.5.0.tgz#80de353d156ea5ea4a7332f7962ac79135fbc62e" +jest@^24.0.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2" dependencies: - import-local "^1.0.0" - jest-cli "^23.5.0" + import-local "^2.0.0" + jest-cli "^24.1.0" js-levenshtein@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.3.tgz#3ef627df48ec8cf24bacf05c0f184ff30ef413c5" - -js-tokens@^3.0.0, js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" -js-yaml@^3.7.0, js-yaml@^3.9.1: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" +js-yaml@^3.12.0: + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -2977,13 +2567,9 @@ jsdom@^11.5.1: ws "^5.2.0" xml-name-validator "^3.0.0" -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" jsesc@~0.5.0: version "0.5.0" @@ -2993,9 +2579,9 @@ json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" json-schema@0.2.3: version "0.2.3" @@ -3009,13 +2595,9 @@ json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" -json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" +json5@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" dependencies: minimist "^1.2.0" @@ -3060,19 +2642,15 @@ klaw@~2.0.0: dependencies: graceful-fs "^4.1.9" -kleur@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" +kleur@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.1.tgz#4f5b313f5fa315432a400f19a24db78d451ede62" -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" dependencies: - invert-kv "^1.0.0" + invert-kv "^2.0.0" left-pad@^1.3.0: version "1.3.0" @@ -3098,21 +2676,17 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" dependencies: - p-locate "^2.0.0" + p-locate "^3.0.0" path-exists "^3.0.0" lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - lodash.omit@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" @@ -3129,13 +2703,9 @@ lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" -lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: - version "4.17.10" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" +lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.5: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" loose-envify@^1.0.0: version "1.4.0" @@ -3143,12 +2713,11 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^4.0.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" +make-dir@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + pify "^3.0.0" makeerror@1.0.x: version "1.0.11" @@ -3156,6 +2725,12 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + dependencies: + p-defer "^1.0.0" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -3170,15 +2745,13 @@ marked@^0.3.16, marked@~0.3.6: version "0.3.19" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790" -math-random@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" +mem@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" dependencies: + map-age-cleaner "^0.1.1" mimic-fn "^1.0.0" + p-is-promise "^2.0.0" merge-stream@^1.0.1: version "1.0.1" @@ -3187,28 +2760,10 @@ merge-stream@^1.0.1: readable-stream "^2.0.1" merge@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" - -micromatch@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" + version "1.2.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" -micromatch@^3.1.4: +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: @@ -3226,21 +2781,21 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" + version "2.1.21" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" dependencies: - mime-db "~1.36.0" + mime-db "~1.37.0" mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" -minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -3248,26 +2803,26 @@ minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: minimist@0.0.8: version "0.0.8" - resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" - resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" minimist@~0.0.1: version "0.0.10" - resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" -minipass@^2.2.1, minipass@^2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" +minipass@^2.2.1, minipass@^2.3.4: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" +minizlib@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" dependencies: minipass "^2.2.1" @@ -3284,7 +2839,7 @@ mkdirp2@^1.0.3: mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" - resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" @@ -3292,13 +2847,17 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" nan@^2.9.2: - version "2.11.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" nanomatch@^1.2.9: version "1.2.13" @@ -3321,23 +2880,32 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" needle@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.2.tgz#1120ca4c41f2fcc6976fd28a8968afe239929418" + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" dependencies: debug "^2.1.2" iconv-lite "^0.4.4" sax "^1.2.4" +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + node-notifier@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" + version "5.4.0" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.0.tgz#7b455fdce9f7de0c63538297354f3db468426e6a" dependencies: growly "^1.3.0" - semver "^5.4.1" + is-wsl "^1.1.0" + semver "^5.5.0" shellwords "^0.1.1" which "^1.3.0" @@ -3356,9 +2924,9 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.0.0-alpha.11: - version "1.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.11.tgz#73c810acc2e5b741a17ddfbb39dfca9ab9359d8a" +node-releases@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.7.tgz#b09a10394d0ed8f7778f72bb861dde68b146303b" dependencies: semver "^5.3.0" @@ -3370,27 +2938,31 @@ nopt@^4.0.1: osenv "^0.1.4" normalize-package-data@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" dependencies: hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" + resolve "^1.10.0" semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + npm-bundled@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" npm-packlist@^1.1.6: - version "1.1.11" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + version "1.3.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.3.0.tgz#7f01e8e44408341379ca98cfd756e7b29bd2626c" dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -3415,8 +2987,8 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" nwsapi@^2.0.7: - version "2.0.8" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.8.tgz#e3603579b7e162b3dbedae4fb24e46f771d8fa24" + version "2.1.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.0.tgz#781065940aed90d9bb01ca5d0ce0fcf81c32712f" oauth-sign@~0.9.0: version "0.9.0" @@ -3459,20 +3031,13 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.2" es-abstract "^1.5.1" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" dependencies: isobject "^3.0.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -3506,15 +3071,15 @@ os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" +os-locale@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -3533,34 +3098,49 @@ output-file-sync@^2.0.0: is-plain-obj "^1.1.0" mkdirp "^0.5.1" +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + +p-each-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" + dependencies: + p-reduce "^1.0.0" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" +p-is-promise@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" + +p-limit@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" dependencies: - p-try "^1.0.0" + p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" dependencies: - p-limit "^1.1.0" + p-limit "^2.0.0" -p-try@^1.0.0: +p-reduce@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" +p-try@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" + +parent-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" + callsites "^3.0.0" parse-json@^4.0.0: version "4.0.0" @@ -3585,19 +3165,19 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" -path-key@^2.0.0: +path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" -path-parse@^1.0.5: +path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -3611,33 +3191,21 @@ performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" +pirates@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.0.tgz#850b18781b4ac6ec58a43c9ed9ec5fe6796addbd" dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + node-modules-regexp "^1.0.0" -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" dependencies: - find-up "^2.1.0" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + find-up "^3.0.0" pn@^1.1.0: version "1.1.0" @@ -3651,22 +3219,14 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -pretty-format@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.5.0.tgz#0f9601ad9da70fe690a269cd3efca732c210687c" +pretty-format@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0.tgz#cb6599fd73ac088e37ed682f61291e4678f48591" dependencies: - ansi-regex "^3.0.0" + ansi-regex "^4.0.0" ansi-styles "^3.2.0" -printf@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/printf/-/printf-0.5.1.tgz#e0466788260859ed153006dc6867f09ddf240cf3" - -private@^0.1.6, private@^0.1.8: +private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -3675,29 +3235,32 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" -prompts@^0.1.9: - version "0.1.14" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2" +prompts@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.1.tgz#201b3718b4276fb407f037db48c0029d6465245c" dependencies: - kleur "^2.0.1" - sisteransi "^0.1.1" + kleur "^3.0.0" + sisteransi "^1.0.0" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +psl@^1.1.24, psl@^1.1.28: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" -psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -3705,14 +3268,6 @@ qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" -randomatic@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -3722,11 +3277,11 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" +read-pkg-up@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" dependencies: - find-up "^2.0.0" + find-up "^3.0.0" read-pkg "^3.0.0" read-pkg@^3.0.0: @@ -3737,7 +3292,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -3749,18 +3304,17 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" + graceful-fs "^4.1.11" + micromatch "^3.1.10" readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" -realpath-native@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.1.tgz#07f40a0cce8f8261e2e8b7ebebf5c95965d7b633" +realpath-native@^1.0.0, realpath-native@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.2.tgz#cd51ce089b513b45cf9b1516c82989b51ccc6560" dependencies: util.promisify "^1.0.0" @@ -3794,10 +3348,6 @@ regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - regenerator-runtime@^0.12.0: version "0.12.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" @@ -3808,12 +3358,6 @@ regenerator-transform@^0.13.3: dependencies: private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -3821,32 +3365,36 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" +regexp-tree@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.1.tgz#27b455f9b138ca2e84c090e9aff1ffe2a04d97fa" + dependencies: + cli-table3 "^0.5.0" + colors "^1.1.2" + yargs "^12.0.5" -regexpp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.0.tgz#b2a7534a85ca1b033bcf5ce9ff8e56d4e0755365" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" + version "4.4.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.4.0.tgz#8d43e0d1266883969720345e70c275ee0aec0d32" dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^7.0.0" - regjsgen "^0.4.0" - regjsparser "^0.3.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.0.2" -regjsgen@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561" +regjsgen@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" -regjsparser@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96" +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" dependencies: jsesc "~0.5.0" @@ -3858,16 +3406,10 @@ repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" @@ -3915,13 +3457,6 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - requizzle@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.1.tgz#6943c3530c4d9a7e46f1cddd51c158fc670cdbde" @@ -3934,14 +3469,14 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -3950,11 +3485,11 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.3.2, resolve@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" +resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" restore-cursor@^2.0.0: version "2.0.0" @@ -3967,17 +3502,11 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" dependencies: - glob "^7.0.5" + glob "^7.1.3" rsvp@^3.3.3: version "3.6.2" @@ -3989,15 +3518,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" +rxjs@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + tslib "^1.9.0" safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" @@ -4017,13 +3542,14 @@ safe-regex@^1.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" -sane@^2.0.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" +sane@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6" dependencies: anymatch "^2.0.0" capture-exit "^1.2.0" exec-sh "^0.2.0" + execa "^1.0.0" fb-watchman "^2.0.0" micromatch "^3.1.4" minimist "^1.1.1" @@ -4036,18 +3562,14 @@ sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" @@ -4084,22 +3606,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -sisteransi@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" - -slash@^1.0.0: +sisteransi@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c" slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: @@ -4147,15 +3667,9 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - dependencies: - source-map "^0.5.6" - source-map-support@^0.5.6: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -4164,30 +3678,24 @@ source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" -source-map@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" - -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" -source-map@^0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" spdx-correct@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" spdx-expression-parse@^3.0.0: version "3.0.0" @@ -4197,8 +3705,8 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + version "3.0.3" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -4211,23 +3719,22 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" ecc-jsbn "~0.1.1" + getpass "^0.1.1" jsbn "~0.1.0" + safer-buffer "^2.0.2" tweetnacl "~0.14.0" stack-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" + version "1.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" static-extend@^0.1.1: version "0.1.2" @@ -4290,7 +3797,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-bom@3.0.0, strip-bom@^3.0.0: +strip-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" + dependencies: + ansi-regex "^4.0.0" + +strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -4298,26 +3811,22 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" -strip-json-comments@~2.0.1: +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.1.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - dependencies: - has-flag "^1.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" dependencies: has-flag "^3.0.0" +supports-color@^6.0.0, supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + dependencies: + has-flag "^3.0.0" + symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -4332,15 +3841,13 @@ table-layout@^0.4.2: typical "^2.6.1" wordwrapjs "^3.0.0" -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" +table@^5.0.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/table/-/table-5.2.2.tgz#61d474c9e4d8f4f7062c98c7504acb3c08aa738f" dependencies: - ajv "^5.2.3" - ajv-keywords "^2.1.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" + ajv "^6.6.1" + lodash "^4.17.11" + slice-ansi "^2.0.0" string-width "^2.1.1" taffydb@2.6.2: @@ -4348,13 +3855,13 @@ taffydb@2.6.2: resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" tar@^4: - version "4.4.6" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" dependencies: - chownr "^1.0.1" + chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" + minipass "^2.3.4" + minizlib "^1.1.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.2" @@ -4363,13 +3870,13 @@ temp-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-path/-/temp-path-1.0.0.tgz#24b1543973ab442896d9ad367dd9cbdbfafe918b" -test-exclude@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.2.tgz#8b67aa8408f84afc225b06669e25c510f8582820" +test-exclude@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.1.0.tgz#6ba6b25179d2d38724824661323b73e03c0c1de1" dependencies: arrify "^1.0.1" minimatch "^3.0.4" - read-pkg-up "^3.0.0" + read-pkg-up "^4.0.0" require-main-filename "^1.0.1" test-value@^1.0.1: @@ -4393,7 +3900,7 @@ test-value@^3.0.0: array-back "^2.0.0" typical "^2.6.1" -text-table@~0.2.0: +text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -4415,10 +3922,6 @@ tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -4445,7 +3948,22 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@>=2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.4.3: +tough-cookie@>=2.3.3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@^2.3.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" dependencies: @@ -4458,10 +3976,18 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +traverse@0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -4478,26 +4004,16 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - typical@^2.4.2, typical@^2.6.0, typical@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" -uglify-js@^2.6: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" +uglify-js@^3.1.4: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + commander "~2.17.1" + source-map "~0.6.1" underscore-contrib@~0.3.0: version "0.3.0" @@ -4552,10 +4068,16 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.0.5: +upath@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + dependencies: + punycode "^2.1.0" + urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -4605,8 +4127,8 @@ walk-back@^2.0.1: resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-2.0.1.tgz#554e2a9d874fac47a8cb006bf44c2f0c4998a0a4" walk-back@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-3.0.0.tgz#2358787a35da91032dad5e92f80b12370d8795c5" + version "3.0.1" + resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-3.0.1.tgz#0c0012694725604960d6c2f75aaf1a1e7d455d35" walker@~1.0.5: version "1.0.7" @@ -4626,14 +4148,14 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz#63fb016b7435b795d9025632c086a5209dbd2621" + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" dependencies: - iconv-lite "0.4.23" + iconv-lite "0.4.24" -whatwg-mimetype@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" +whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" whatwg-url@^6.4.1: version "6.5.0" @@ -4667,14 +4189,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" @@ -4692,7 +4206,7 @@ wordwrapjs@^3.0.0: wrap-ansi@^2.0.0: version "2.1.0" - resolved "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -4701,9 +4215,9 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -write-file-atomic@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" +write-file-atomic@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529" dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" @@ -4729,46 +4243,34 @@ xmlcreate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-1.0.2.tgz#fa6bf762a60a413fb3dd8f4b03c5b269238d308f" -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +"y18n@^3.2.1 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" dependencies: - camelcase "^4.1.0" + camelcase "^5.0.0" + decamelize "^1.2.0" -yargs@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" +yargs@^12.0.2, yargs@^12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" dependencies: cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" + decamelize "^1.2.0" + find-up "^3.0.0" get-caller-file "^1.0.1" - os-locale "^2.0.0" + os-locale "^3.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" string-width "^2.0.0" which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1"