From 100c1adecef70bcc0fec292a97150d4db132f37c Mon Sep 17 00:00:00 2001 From: Fluvf <14368815+Fluvf@users.noreply.github.com> Date: Tue, 22 Sep 2020 19:26:21 +0300 Subject: [PATCH 1/3] package: install prettier-standard and define linting scripts This'll help to catch any errors in new code and keep its style consistent While we're at it also uninstall unused `coffeelint` and remove files belonging to it --- .eslintrc.json | 9 + .coffeelintignore => .prettierignore | 0 .prettierrc.json | 3 + coffeelint.json | 37 - package-lock.json | 3406 +++++++++++++++++++++++++- package.json | 6 +- 6 files changed, 3306 insertions(+), 155 deletions(-) create mode 100644 .eslintrc.json rename .coffeelintignore => .prettierignore (100%) create mode 100644 .prettierrc.json delete mode 100644 coffeelint.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..a724318 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "env": { + "jasmine": true + }, + "globals": { + "waitsForPromise": true, + "atom": true + } +} diff --git a/.coffeelintignore b/.prettierignore similarity index 100% rename from .coffeelintignore rename to .prettierignore diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..544138b --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/coffeelint.json b/coffeelint.json deleted file mode 100644 index a5dd715..0000000 --- a/coffeelint.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "max_line_length": { - "level": "ignore" - }, - "no_empty_param_list": { - "level": "error" - }, - "arrow_spacing": { - "level": "error" - }, - "no_interpolation_in_single_quotes": { - "level": "error" - }, - "no_debugger": { - "level": "error" - }, - "prefer_english_operator": { - "level": "error" - }, - "colon_assignment_spacing": { - "spacing": { - "left": 0, - "right": 1 - }, - "level": "error" - }, - "braces_spacing": { - "spaces": 0, - "level": "error" - }, - "spacing_after_comma": { - "level": "error" - }, - "no_stand_alone_at": { - "level": "error" - } -} diff --git a/package-lock.json b/package-lock.json index c085050..6841349 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,11 +4,317 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@angular/compiler": { + "version": "8.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.14.tgz", + "integrity": "sha512-ABZO4E7eeFA1QyJ2trDezxeQM5ZFa1dXw1Mpl/+1vuXDKNjJgNyWYwKp/NwRkLmrsuV0yv4UDCDe4kJOGbPKnw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "dev": true + }, + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@glimmer/interfaces": { + "version": "0.41.4", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.41.4.tgz", + "integrity": "sha512-MzXwMyod3MlwSZezHSaVBsCEIW/giYYfTDYARR46QnYsaFVatMVbydjsI7jkAuBCbnLCyNOIc1TrYIj71i/rpg==", + "dev": true + }, + "@glimmer/syntax": { + "version": "0.41.4", + "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.41.4.tgz", + "integrity": "sha512-NLPNirZDbNmpZ8T/ccle22zt2rhUq5il7ST6IJk62T58QZeJsdr3m3RS4kaGSBsQhXoKELrgX048yYEX5sC+fw==", + "dev": true, + "requires": { + "@glimmer/interfaces": "^0.41.4", + "@glimmer/util": "^0.41.4", + "handlebars": "^4.0.13", + "simple-html-tokenizer": "^0.5.7" + } + }, + "@glimmer/util": { + "version": "0.41.4", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.41.4.tgz", + "integrity": "sha512-DwS94K+M0vtG+cymxH0rslJr09qpdjyOLdCjmpKcG/nNiZQfMA1ybAaFEmwk9UaVlUG9STENFeQwyrLevJB+7g==", + "dev": true + }, + "@iarna/toml": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.3.tgz", + "integrity": "sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "14.11.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", + "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==", + "dev": true + }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz", + "integrity": "sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "glob": "^7.1.4", + "is-glob": "^4.0.1", + "lodash.unescape": "4.0.1", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "angular-estree-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/angular-estree-parser/-/angular-estree-parser-1.3.1.tgz", + "integrity": "sha512-jvlnNk4aoEmA6EKK12OnsOkCSdsWleBsYB+aWyH8kpfTB6Li1kxWVbHKVldH9zDCwVVi1hXfqPi/gbSv49tkbQ==", + "dev": true, + "requires": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.9.3" + } + }, + "angular-html-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.4.0.tgz", + "integrity": "sha512-5KyzzYOeZV9g9ahXw4rbi8IIbMjUdXoarXJ0CfbWue5U1YsvMnjMZJ3oadpU8ZtnIx1zR/dsyt+FLJx2U65d2Q==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-differ": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", + "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", @@ -28,6 +334,12 @@ "resolved": "https://registry.npmjs.org/atom-slick/-/atom-slick-2.0.0.tgz", "integrity": "sha1-/w2+Fb4sTtomi50w124lF+C308o=" }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -42,11 +354,153 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cjk-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-2.0.0.tgz", + "integrity": "sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA==", + "dev": true, + "requires": { + "regexp-util": "^1.2.1", + "unicode-regex": "^2.0.0" + }, + "dependencies": { + "unicode-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-2.0.0.tgz", + "integrity": "sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ==", + "dev": true, + "requires": { + "regexp-util": "^1.2.0" + } + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + } + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -67,42 +521,88 @@ "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" }, - "coffeelint": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-1.16.0.tgz", - "integrity": "sha1-g9jtHa/eOmd95E57ihi+YHdh5tg=", + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "requires": { - "coffee-script": "~1.11.0", - "glob": "^7.0.6", - "ignore": "^3.0.9", - "optimist": "^0.6.1", - "resolve": "^0.6.3", - "strip-json-comments": "^1.0.2" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" }, "dependencies": { - "coffee-script": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.11.1.tgz", - "integrity": "sha1-vxxHrWREOg2V0S3ysUfMCk2q1uk=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true } } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } }, "cson-parser": { "version": "1.3.5", @@ -120,37 +620,225 @@ "es5-ext": "~0.10.2" } }, + "dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "dev": true + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "emissary": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/emissary/-/emissary-1.3.3.tgz", - "integrity": "sha1-phjZLWgrIy0xER3DYlpd9mF5lgY=", - "requires": { - "es6-weak-map": "^0.1.2", - "mixto": "1.x", - "property-accessors": "^1.1", - "underscore-plus": "1.x" - } + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true }, - "es5-ext": { - "version": "0.10.30", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", - "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", + "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", + "dev": true, "requires": { - "es6-iterator": "2", - "es6-symbol": "~3.1" + "globby": "^10.0.1", + "graceful-fs": "^4.2.2", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.1", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0" }, "dependencies": { - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "^0.10.9" + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "editorconfig-to-prettier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/editorconfig-to-prettier/-/editorconfig-to-prettier-0.1.1.tgz", + "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "emissary": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/emissary/-/emissary-1.3.3.tgz", + "integrity": "sha1-phjZLWgrIy0xER3DYlpd9mF5lgY=", + "requires": { + "es6-weak-map": "^0.1.2", + "mixto": "1.x", + "property-accessors": "^1.1", + "underscore-plus": "1.x" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.30", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", + "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "requires": { + "es6-iterator": "2", + "es6-symbol": "~3.1" + }, + "dependencies": { + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" } }, "es6-iterator": { @@ -204,6 +892,168 @@ "es6-symbol": "~2.0.1" } }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "etch": { "version": "0.12.8", "resolved": "https://registry.npmjs.org/etch/-/etch-0.12.8.tgz", @@ -217,6 +1067,227 @@ "grim": "^1.2.1" } }, + "execa": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", + "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^3.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-project-root": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/find-project-root/-/find-project-root-1.1.1.tgz", + "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, + "flow-parser": { + "version": "0.111.3", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.111.3.tgz", + "integrity": "sha512-iEjGZ94OBMcESxnLorXNjJmtd/JtQYXUVrQpfwvtAKkuyawRmv+2LM6nqyOsOJkISEYbyY6ziudRE0u4VyPSVA==", + "dev": true + }, "fs-plus": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.0.1.tgz", @@ -240,11 +1311,38 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "fuzzaldrin": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz", "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps=" }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -258,6 +1356,52 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "graphql": { + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.6.0.tgz", + "integrity": "sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg==", + "dev": true, + "requires": { + "iterall": "^1.2.2" + } + }, "grim": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/grim/-/grim-1.5.0.tgz", @@ -266,11 +1410,102 @@ "emissary": "^1.2.0" } }, - "ignore": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz", - "integrity": "sha1-xOcVRV9gc6jX5drnLS/J1xZj26Y=", - "dev": true + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "html-element-attributes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/html-element-attributes/-/html-element-attributes-2.2.1.tgz", + "integrity": "sha512-gGTgCeQu+g1OFExZKWQ1LwbFXxLJ6cGdCGj64ByEaxatr/EPVc23D6Gxngb37ao+SNInP/sGu8FXxRsSxMm7aQ==", + "dev": true + }, + "html-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/html-styles/-/html-styles-1.0.0.tgz", + "integrity": "sha1-oYBh/WUfmca3XEXI4FSaO8PgGnU=", + "dev": true + }, + "html-tag-names": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/html-tag-names/-/html-tag-names-1.1.5.tgz", + "integrity": "sha512-aI5tKwNTBzOZApHIynaAwecLBv8TlZTEy/P4Sj2SzzAhBrGuI8yGZ0UIXVPQzOHGS+to2mjb04iy6VWt/8+d8A==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true }, "inflight": { "version": "1.0.6", @@ -286,11 +1521,171 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -299,6 +1694,166 @@ "number-is-nan": "^1.0.0" } }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", + "dev": true + }, + "jest-docblock": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.3.0.tgz", + "integrity": "sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, "key-path-helpers": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/key-path-helpers/-/key-path-helpers-0.1.0.tgz", @@ -312,86 +1867,1214 @@ "invert-kv": "^1.0.0" } }, - "loophole": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loophole/-/loophole-1.1.0.tgz", - "integrity": "sha1-N5Sf6kU7YlasxyXDIM4MWn9wor0=" + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true }, - "mixto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mixto/-/mixto-1.0.0.tgz", - "integrity": "sha1-wyDvYbUvKJj1IuF9i7xtUG2EJbY=" + "linguist-languages": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.6.0.tgz", + "integrity": "sha512-DBZPIWjrQmb/52UlSEN8MTiwwugrAh4NBX9/DyIG8IuO8rDLYDRM+KVPbuiPVKd3ResxYtZB5AiSuc8dTzOSog==", + "dev": true }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "lint-staged": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-9.4.3.tgz", + "integrity": "sha512-PejnI+rwOAmKAIO+5UuAZU9gxdej/ovSEOAY34yMfC3OS4Ac82vCBPzAWLReR9zCPOMqeVwQRaZ3bUBpAsaL2Q==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "commander": "^2.20.0", + "cosmiconfig": "^5.2.1", + "debug": "^4.1.1", + "dedent": "^0.7.0", + "del": "^5.0.0", + "execa": "^2.0.3", + "listr": "^0.14.3", + "log-symbols": "^3.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.1.1", + "string-argv": "^0.3.0", + "stringify-object": "^3.3.0" + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, + "lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "loophole": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loophole/-/loophole-1.1.0.tgz", + "integrity": "sha1-N5Sf6kU7YlasxyXDIM4MWn9wor0=" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true + }, + "mem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mixto/-/mixto-1.0.0.tgz", + "integrity": "sha1-wyDvYbUvKJj1IuF9i7xtUG2EJbY=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multimatch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-3.0.0.tgz", + "integrity": "sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==", + "dev": true, + "requires": { + "array-differ": "^2.0.3", + "array-union": "^1.0.2", + "arrify": "^1.0.1", + "minimatch": "^3.0.4" + } + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "n-readlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/n-readlines/-/n-readlines-1.0.0.tgz", + "integrity": "sha512-ISDqGcspVu6U3VKqtJZG1uR55SmNNF9uK0EMq1IvNVVZOui6MW6VR0+pIZhqz85ORAGp+4zW+5fJ/SE7bwEibA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + }, + "dependencies": { + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + } + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pegjs": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.8.0.tgz", + "integrity": "sha1-l28GfaE+XFsVAcAXklZoolOBFWE=" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postcss-less": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-2.0.0.tgz", + "integrity": "sha512-pPNsVnpCB13nBMOcl5GVh8JGmB0JGFjqkLUDzKdVpptFFKEe9wFdEzvh2j4lD2AD+7qcrUfw9Ta+oi5+Fw7jjQ==", + "dev": true, + "requires": { + "postcss": "^5.2.16" + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-scss": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.0.0.tgz", + "integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", + "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-values-parser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz", + "integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier-standard": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/prettier-standard/-/prettier-standard-16.4.1.tgz", + "integrity": "sha512-IW3Sct4GOdqc1s4+1HZjH2HegzLZQ6mDMl2xz6i6KHCac7kCM+obLbvm2e0zp8PytKkLQCdOpj0cWWa48Ruetw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "diff": "^4.0.2", + "eslint": "^6.8.0", + "execa": "^2.0.4", + "find-up": "^4.1.0", + "get-stdin": "^7.0.0", + "globby": "^6.1.0", + "ignore": "^3.3.7", + "lint-staged": "9.4.3", + "mri": "^1.1.5", + "multimatch": "^3.0.0", + "prettierx": "0.11.3" + } + }, + "prettierx": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/prettierx/-/prettierx-0.11.3.tgz", + "integrity": "sha512-Xf04LEfD3ITo26i5U/zR++hwqKPG3feR06rrjB0t2o+QFv8ZidFp4o7nPqPGLfE4UwHJgd0qwnZKwm0MsUQHUA==", + "dev": true, + "requires": { + "@angular/compiler": "8.2.14", + "@babel/code-frame": "7.8.3", + "@babel/parser": "7.9.4", + "@glimmer/syntax": "0.41.4", + "@iarna/toml": "2.2.3", + "@typescript-eslint/typescript-estree": "2.6.1", + "angular-estree-parser": "1.3.1", + "angular-html-parser": "1.4.0", + "camelcase": "5.3.1", + "chalk": "3.0.0", + "cjk-regex": "2.0.0", + "cosmiconfig": "5.2.1", + "dashify": "2.0.0", + "dedent": "0.7.0", + "diff": "4.0.2", + "editorconfig": "0.15.3", + "editorconfig-to-prettier": "0.1.1", + "escape-string-regexp": "2.0.0", + "esutils": "2.0.3", + "find-parent-dir": "0.3.0", + "find-project-root": "1.1.1", + "flow-parser": "0.111.3", + "get-stream": "4.1.0", + "globby": "6.1.0", + "graphql": "14.6.0", + "html-element-attributes": "2.2.1", + "html-styles": "1.0.0", + "html-tag-names": "1.1.5", + "ignore": "4.0.6", + "is-ci": "2.0.0", + "jest-docblock": "25.3.0", + "json-stable-stringify": "1.0.1", + "leven": "3.1.0", + "lines-and-columns": "1.1.6", + "linguist-languages": "7.6.0", + "lodash.uniqby": "4.7.0", + "mem": "5.1.1", + "minimatch": "3.0.4", + "minimist": "1.2.5", + "n-readlines": "1.0.0", + "normalize-path": "3.0.0", + "parse-srcset": "1.0.2", + "postcss-less": "2.0.0", + "postcss-media-query-parser": "0.2.3", + "postcss-scss": "2.0.0", + "postcss-selector-parser": "2.2.3", + "postcss-values-parser": "1.5.0", + "regexp-util": "1.2.2", + "remark-math": "1.0.6", + "remark-parse": "5.0.0", + "resolve": "1.15.1", + "semver": "6.3.0", + "string-width": "4.2.0", + "unicode-regex": "3.0.0", + "unified": "8.4.2", + "vnopts": "1.0.2", + "yaml": "1.8.3", + "yaml-unist-parser": "1.1.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "property-accessors": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/property-accessors/-/property-accessors-1.1.3.tgz", + "integrity": "sha1-Hd6EAkYxhlkJ7zBwM2VoDF+SixU=", + "requires": { + "es6-weak-map": "^0.1.2", + "mixto": "1.x" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regexp-util": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/regexp-util/-/regexp-util-1.2.2.tgz", + "integrity": "sha512-5/rl2UD18oAlLQEIuKBeiSIOp1hb5wCXcakl5yvHxlY1wyWI4D5cUKKzCibBeu741PA9JKvZhMqbkDQqPusX3w==", + "dev": true, "requires": { - "minimist": "0.0.8" + "tslib": "^1.9.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "remark-math": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-1.0.6.tgz", + "integrity": "sha512-I43wU/QOQpXvVFXKjA4FHp5xptK65+5F6yolm8+69/JV0EqSOB64wURUZ3JK50JtnTL8FvwLiH2PZ+fvsBxviA==", + "dev": true, "requires": { - "wrappy": "1" + "trim-trailing-lines": "^1.1.0" } }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, "requires": { - "lcid": "^1.0.0" + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true }, - "pegjs": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.8.0.tgz", - "integrity": "sha1-l28GfaE+XFsVAcAXklZoolOBFWE=" + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } }, - "property-accessors": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/property-accessors/-/property-accessors-1.1.3.tgz", - "integrity": "sha1-Hd6EAkYxhlkJ7zBwM2VoDF+SixU=", + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "requires": { - "es6-weak-map": "^0.1.2", - "mixto": "1.x" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" } }, - "resolve": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", - "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, "rimraf": { @@ -402,6 +3085,33 @@ "glob": "^7.0.5" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "scoped-property-store": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/scoped-property-store/-/scoped-property-store-0.17.0.tgz", @@ -424,6 +3134,100 @@ "yargs": "^3.23.0" } }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-html-tokenizer": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.9.tgz", + "integrity": "sha512-w/3FEDN94r4JQ9WoYrIr8RqDIPZdyNkdpbK9glFady1CAEyD97XWCv8HFetQO21w81e7h7Nh59iYTyG1mUJftg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true + }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -434,6 +3238,17 @@ "strip-ansi": "^3.0.0" } }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -442,12 +3257,85 @@ "ansi-regex": "^2.0.0" } }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", @@ -464,6 +3352,91 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==", + "dev": true + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "uglify-js": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz", + "integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==", + "dev": true, + "optional": true + }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", @@ -477,15 +3450,173 @@ "underscore": "~1.6.0" } }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "unicode-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-3.0.0.tgz", + "integrity": "sha512-WiDJdORsqgxkZrjC8WsIP573130HNn7KsB0IDnUccW2BG2b19QQNloNhVe6DKk3Aef0UcoIHhNVj7IkkcYWrNw==", + "dev": true, + "requires": { + "regexp-util": "^1.2.0" + } + }, + "unified": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", + "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true + }, + "unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "vfile": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz", + "integrity": "sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + } + }, + "vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", + "dev": true + }, + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vnopts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vnopts/-/vnopts-1.0.2.tgz", + "integrity": "sha512-d2rr2EFhAGHnTlURu49G7GWmiJV80HbAnkYdD9IFAtfhmxC+kSWEaZ6ZF064DJFTv9lQZQV1vuLTntyQpoanGQ==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "leven": "^2.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrap-ansi": { @@ -502,11 +3633,52 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yaml": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.3.tgz", + "integrity": "sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.7" + } + }, + "yaml-unist-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yaml-unist-parser/-/yaml-unist-parser-1.1.1.tgz", + "integrity": "sha512-cGtqhHBlcft+rTKiPsVcSyi43Eqm5a1buYokW9VkztroKMErBSdR9ANHx+/XxNppHZTu2KMEn4yY8MdhuGoFuA==", + "dev": true, + "requires": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.10.0", + "yaml": "^1.7.1" + } + }, "yargs": { "version": "3.32.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", diff --git a/package.json b/package.json index 7ced027..2c09fe1 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,10 @@ "engines": { "atom": "*" }, + "scripts": { + "lint": "prettier-standard --lint", + "test": "npm run lint && atom --test spec" + }, "dependencies": { "async": "~0.2.6", "atom-select-list": "^0.7.0", @@ -28,6 +32,6 @@ } }, "devDependencies": { - "coffeelint": "^1.9.7" + "prettier-standard": "^16.4.1" } } From e8024c87ca74fd8a5d278e2be1dc0002c915e434 Mon Sep 17 00:00:00 2001 From: Fluvf <14368815+Fluvf@users.noreply.github.com> Date: Tue, 22 Sep 2020 19:41:37 +0300 Subject: [PATCH 2/3] package: update deps and reorder package.json Also moves `temp` to `devDependencies`, as it's only used by specs The reorder isn't necessary, but I feel it is cleaner --- package-lock.json | 158 ++++++++++++++++++++++++++++++++-------------- package.json | 24 +++---- 2 files changed, 122 insertions(+), 60 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6841349..7ecbbef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -316,9 +316,9 @@ "dev": true }, "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, "atom-select-list": { "version": "0.7.2", @@ -825,39 +825,41 @@ } }, "es5-ext": { - "version": "0.10.30", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", - "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "requires": { - "es6-iterator": "2", - "es6-symbol": "~3.1" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" }, "dependencies": { "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "es6-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", - "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "requires": { "d": "1", - "es5-ext": "^0.10.14", - "es6-symbol": "^3.1" + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "^1.0.1", + "ext": "^1.1.2" } } } @@ -1127,6 +1129,21 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1289,9 +1306,9 @@ "dev": true }, "fs-plus": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.0.1.tgz", - "integrity": "sha1-VMFpxA4ohKZtNSeA0Y3TH5HToQ0=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.1.1.tgz", + "integrity": "sha512-Se2PJdOWXqos1qVTkvqqjb0CSnfBnwwD+pq+z4ksT+e97mEShod/hrNg0TRCCsXPbJzcIq+NuzQhigunMWMJUA==", "requires": { "async": "^1.5.2", "mkdirp": "^0.5.1", @@ -1347,6 +1364,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2352,6 +2370,11 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -2425,7 +2448,7 @@ }, "os-locale": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { "lcid": "^1.0.0" @@ -2434,7 +2457,8 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "p-defer": { "version": "1.0.0", @@ -3078,11 +3102,26 @@ "dev": true }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "run-async": { @@ -3337,18 +3376,36 @@ } }, "temp": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.1.tgz", + "integrity": "sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA==", + "dev": true, "requires": { - "os-tmpdir": "^1.0.0", - "rimraf": "~2.2.6" + "rimraf": "~2.6.2" }, "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -3415,6 +3472,11 @@ "tslib": "^1.8.1" } }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -3438,16 +3500,16 @@ "optional": true }, "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", + "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" }, "underscore-plus": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.6.6.tgz", - "integrity": "sha1-ZezeG9xEGjXYnmUP1w3PE65Dmn0=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.7.0.tgz", + "integrity": "sha512-A3BEzkeicFLnr+U/Q3EyWwJAQPbA19mtZZ4h+lLq3ttm9kn8WC4R3YpuJZEXmWdLjYP47Zc8aLZm9kwdv+zzvA==", "requires": { - "underscore": "~1.6.0" + "underscore": "^1.9.1" } }, "unherit": { @@ -3621,7 +3683,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", @@ -3681,7 +3743,7 @@ }, "yargs": { "version": "3.32.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "requires": { "camelcase": "^2.0.1", diff --git a/package.json b/package.json index 2c09fe1..cfed826 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,30 @@ { "name": "snippets", "version": "1.6.0", - "main": "./lib/snippets", "description": "Expand snippets matching the current prefix with `tab`.", "repository": "https://github.com/atom/snippets", "license": "MIT", - "engines": { - "atom": "*" - }, + "main": "./lib/snippets", "scripts": { "lint": "prettier-standard --lint", "test": "npm run lint && atom --test spec" }, "dependencies": { - "async": "~0.2.6", - "atom-select-list": "^0.7.0", - "fs-plus": "^3.0.0", + "async": "^3.2.0", + "atom-select-list": "^0.7.2", + "fs-plus": "^3.1.1", "loophole": "^1", "pegjs": "~0.8.0", "scoped-property-store": "^0.17.0", "season": "^6.0.2", - "temp": "~0.8.0", - "underscore-plus": "^1.0.0" + "underscore-plus": "^1.7.0" + }, + "devDependencies": { + "prettier-standard": "^16.4.1", + "temp": "^0.9.1" + }, + "engines": { + "atom": "*" }, "providedServices": { "snippets": { @@ -30,8 +33,5 @@ "0.1.0": "provideSnippets" } } - }, - "devDependencies": { - "prettier-standard": "^16.4.1" } } From 4e658b33470ec11b6f0c87ca268c62ed189c53b0 Mon Sep 17 00:00:00 2001 From: Fluvf <14368815+Fluvf@users.noreply.github.com> Date: Sat, 26 Sep 2020 19:54:00 +0300 Subject: [PATCH 3/3] package: run `prettier-standard --lint` and fix errors Almost all of these changes were made automatically List of errors that had to be resolved manually: (`no-template-curly-in-string` errors were resolved by turning the rule off) .../snippets/lib/snippets.js 156:31 error Expected error to be handled handle-callback-err 164:9 error Unexpected literal in error position of callback standard/no-callback-literal 171:31 error Expected error to be handled handle-callback-err 286:7 error Expected error to be handled handle-callback-err 358:11 error Expected error to be handled handle-callback-err 372:14 error Unexpected literal in error position of callback standard/no-callback-literal .../snippets/spec/body-parser-spec.js 26:7 error Unexpected template string expression no-template-curly-in-string 54:39 error Unexpected template string expression no-template-curly-in-string 65:39 error Unexpected template string expression no-template-curly-in-string 79:7 error Unexpected template string expression no-template-curly-in-string 111:39 error Unexpected template string expression no-template-curly-in-string 129:39 error Unexpected template string expression no-template-curly-in-string 151:39 error Unexpected template string expression no-template-curly-in-string 171:39 error Unexpected template string expression no-template-curly-in-string 189:39 error Unexpected template string expression no-template-curly-in-string .../snippets/spec/snippets-spec.js 75:41 error Unexpected template string expression no-template-curly-in-string 199:19 error Unexpected template string expression no-template-curly-in-string 257:19 error Unexpected template string expression no-template-curly-in-string 271:19 error Unexpected template string expression no-template-curly-in-string 276:19 error Unexpected template string expression no-template-curly-in-string 280:19 error Unexpected template string expression no-template-curly-in-string 285:15 error Unexpected template string expression no-template-curly-in-string 289:19 error Unexpected template string expression no-template-curly-in-string 293:19 error Unexpected template string expression no-template-curly-in-string 297:19 error Unexpected template string expression no-template-curly-in-string 301:19 error Unexpected template string expression no-template-curly-in-string 1335:23 error Unexpected template string expression no-template-curly-in-string 1355:19 error Unexpected template string expression no-template-curly-in-string 1360:19 error Unexpected template string expression no-template-curly-in-string 1385:14 error Unexpected template string expression no-template-curly-in-string 1397:14 error Unexpected template string expression no-template-curly-in-string --- .eslintrc.json | 3 + ISSUE_TEMPLATE.md | 12 +- PULL_REQUEST_TEMPLATE.md | 4 +- README.md | 23 +- appveyor.yml | 10 +- lib/editor-store.js | 17 +- lib/helpers.js | 4 +- lib/insertion.js | 22 +- lib/snippet-body-parser.js | 9 +- lib/snippet-expansion.js | 121 +- lib/snippet-history-provider.js | 2 +- lib/snippet.js | 22 +- lib/snippets-available.js | 12 +- lib/snippets.js | 474 +++++-- lib/tab-stop-list.js | 8 +- lib/tab-stop.js | 18 +- spec/body-parser-spec.js | 216 ++- spec/insertion-spec.js | 26 +- spec/snippet-loading-spec.js | 503 ++++--- spec/snippets-spec.js | 2249 +++++++++++++++++-------------- 20 files changed, 2138 insertions(+), 1617 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index a724318..3639ff8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,5 +5,8 @@ "globals": { "waitsForPromise": true, "atom": true + }, + "rules": { + "no-template-curly-in-string": "off" } } diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index b60bb86..bd8b5f5 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -8,12 +8,12 @@ Do you want to ask a question? Are you looking for support? The Atom message boa ### Prerequisites -* [ ] Put an X between the brackets on this line if you have done all of the following: - * Reproduced the problem in Safe Mode: http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode - * Followed all applicable steps in the debugging guide: http://flight-manual.atom.io/hacking-atom/sections/debugging/ - * Checked the FAQs on the message board for common solutions: https://discuss.atom.io/c/faq - * Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=is%3Aissue+user%3Aatom - * Checked that there is not already an Atom package that provides the described functionality: https://atom.io/packages +- [ ] Put an X between the brackets on this line if you have done all of the following: + - Reproduced the problem in Safe Mode: http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode + - Followed all applicable steps in the debugging guide: http://flight-manual.atom.io/hacking-atom/sections/debugging/ + - Checked the FAQs on the message board for common solutions: https://discuss.atom.io/c/faq + - Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=is%3Aissue+user%3Aatom + - Checked that there is not already an Atom package that provides the described functionality: https://atom.io/packages ### Description diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index cdaa94a..b4a55e7 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,7 @@ ### Requirements -* Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. -* All new code requires tests to ensure against regressions +- Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. +- All new code requires tests to ensure against regressions ### Description of the Change diff --git a/README.md b/README.md index 267f42c..1526d2f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Snippets package + [![macOS Build Status](https://travis-ci.org/atom/snippets.svg?branch=master)](https://travis-ci.org/atom/snippets) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/8hlc0onofkgbxw53/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/snippets/branch/master) [![Dependency Status](https://david-dm.org/atom/snippets.svg)](https://david-dm.org/atom/snippets) Expand snippets matching the current prefix with tab in Atom. @@ -27,23 +28,25 @@ Under each snippet name is a `prefix` that should trigger the snippet and a `bod The above example adds a `log` snippet to JavaScript files that would expand to. ```js -console.log("crash"); +console.log('crash') ``` The string `"crash"` would be initially selected and pressing tab again would place the cursor after the `;` ### Optional parameters + These parameters are meant to provide extra information about your snippet to [autocomplete-plus](https://github.com/atom/autocomplete-plus/wiki/Provider-API). -* `leftLabel` will add text to the left part of the autocomplete results box. -* `leftLabelHTML` will overwrite what's in `leftLabel` and allow you to use a bit of CSS such as `color`. -* `rightLabelHTML`. By default, in the right part of the results box you will see the name of the snippet. When using `rightLabelHTML` the name of the snippet will no longer be displayed, and you will be able to use a bit of CSS. -* `description` will add text to a description box under the autocomplete results list. -* `descriptionMoreURL` URL to the documentation of the snippet. +- `leftLabel` will add text to the left part of the autocomplete results box. +- `leftLabelHTML` will overwrite what's in `leftLabel` and allow you to use a bit of CSS such as `color`. +- `rightLabelHTML`. By default, in the right part of the results box you will see the name of the snippet. When using `rightLabelHTML` the name of the snippet will no longer be displayed, and you will be able to use a bit of CSS. +- `description` will add text to a description box under the autocomplete results list. +- `descriptionMoreURL` URL to the documentation of the snippet. ![autocomplete-description](http://i.imgur.com/cvI2lOq.png) Example: + ```coffee '.source.js': 'console.log': @@ -55,7 +58,7 @@ Example: ### Determining the correct scope for a snippet -The outmost key of a snippet is the "scope" that you want the descendent snippets to be available in. The key should be prefixed with a period (`text.html.basic` => `.text.html.basic`). You can find out the correct scope by opening the Settings (cmd-, on macOS) and selecting the corresponding *Language [xxx]* package, e.g. for *Language Html*: +The outmost key of a snippet is the "scope" that you want the descendent snippets to be available in. The key should be prefixed with a period (`text.html.basic` => `.text.html.basic`). You can find out the correct scope by opening the Settings (cmd-, on macOS) and selecting the corresponding _Language [xxx]_ package, e.g. for _Language Html_: ![Screenshot of Language Html settings](https://cloud.githubusercontent.com/assets/1038121/5137632/126beb66-70f2-11e4-839b-bc7e84103f67.png) @@ -68,9 +71,9 @@ This package supports a subset of the features of TextMate snippets, [documented The following features are not yet supported: -* Variables -* Interpolated shell code -* Conditional insertions in transformations +- Variables +- Interpolated shell code +- Conditional insertions in transformations ### Multi-line Snippet Body diff --git a/appveyor.yml b/appveyor.yml index 2b0fde4..49981c8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,10 @@ -version: "{build}" +version: '{build}' platform: x64 branches: - only: - - master + only: + - master clone_depth: 10 @@ -14,8 +14,8 @@ environment: APM_TEST_PACKAGES: matrix: - - ATOM_CHANNEL: stable - - ATOM_CHANNEL: beta + - ATOM_CHANNEL: stable + - ATOM_CHANNEL: beta install: - ps: Install-Product node 4 diff --git a/lib/editor-store.js b/lib/editor-store.js index c57cb7a..631b220 100644 --- a/lib/editor-store.js +++ b/lib/editor-store.js @@ -31,23 +31,32 @@ class EditorStore { this.existingHistoryProvider = this.buffer.historyProvider } - const newProvider = SnippetHistoryProvider(this.existingHistoryProvider, delegates) + const newProvider = SnippetHistoryProvider( + this.existingHistoryProvider, + delegates + ) this.buffer.setHistoryProvider(newProvider) } stopObservingHistory (editor) { - if (this.existingHistoryProvider == null) { return } + if (this.existingHistoryProvider == null) { + return + } this.buffer.setHistoryProvider(this.existingHistoryProvider) this.existingHistoryProvider = null } observe (callback) { - if (this.observer != null) { this.observer.dispose() } + if (this.observer != null) { + this.observer.dispose() + } this.observer = this.buffer.onDidChangeText(callback) } stopObserving () { - if (this.observer == null) { return false } + if (this.observer == null) { + return false + } this.observer.dispose() this.observer = null return true diff --git a/lib/helpers.js b/lib/helpers.js index 0814a3d..461e774 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -2,8 +2,8 @@ import path from 'path' -export function getPackageRoot() { - const {resourcePath} = atom.getLoadSettings() +export function getPackageRoot () { + const { resourcePath } = atom.getLoadSettings() const currentFileWasRequiredFromSnapshot = !path.isAbsolute(__dirname) if (currentFileWasRequiredFromSnapshot) { return path.join(resourcePath, 'node_modules', 'snippets') diff --git a/lib/insertion.js b/lib/insertion.js index 96065d1..02442d2 100644 --- a/lib/insertion.js +++ b/lib/insertion.js @@ -1,21 +1,21 @@ const ESCAPES = { - u: (flags) => { + u: flags => { flags.lowercaseNext = false flags.uppercaseNext = true }, - l: (flags) => { + l: flags => { flags.uppercaseNext = false flags.lowercaseNext = true }, - U: (flags) => { + U: flags => { flags.lowercaseAll = false flags.uppercaseAll = true }, - L: (flags) => { + L: flags => { flags.uppercaseAll = false flags.lowercaseAll = true }, - E: (flags) => { + E: flags => { flags.uppercaseAll = false flags.lowercaseAll = false }, @@ -62,21 +62,21 @@ class Insertion { makeReplacer (replace) { return function replacer (...match) { - let flags = { + const flags = { uppercaseAll: false, lowercaseAll: false, uppercaseNext: false, lowercaseNext: false } replace = [...replace] - let result = [] + const result = [] replace.forEach(token => { if (typeof token === 'string') { result.push(transformText(token, flags)) } else if (token.escape) { ESCAPES[token.escape](flags, result) } else if (token.backreference) { - let transformed = transformText(match[token.backreference], flags) + const transformed = transformText(match[token.backreference], flags) result.push(transformed) } }) @@ -85,8 +85,10 @@ class Insertion { } transform (input) { - let { substitution } = this - if (!substitution) { return input } + const { substitution } = this + if (!substitution) { + return input + } return input.replace(substitution.find, this.replacer) } } diff --git a/lib/snippet-body-parser.js b/lib/snippet-body-parser.js index d4293ec..a0deb53 100644 --- a/lib/snippet-body-parser.js +++ b/lib/snippet-body-parser.js @@ -2,13 +2,16 @@ let parser try { parser = require('./snippet-body') } catch (error) { - const {allowUnsafeEval} = require('loophole') + const { allowUnsafeEval } = require('loophole') const fs = require('fs-plus') const PEG = require('pegjs') - const grammarSrc = fs.readFileSync(require.resolve('./snippet-body.pegjs'), 'utf8') + const grammarSrc = fs.readFileSync( + require.resolve('./snippet-body.pegjs'), + 'utf8' + ) parser = null - allowUnsafeEval(() => parser = PEG.buildParser(grammarSrc)) + allowUnsafeEval(() => (parser = PEG.buildParser(grammarSrc))) } module.exports = parser diff --git a/lib/snippet-expansion.js b/lib/snippet-expansion.js index 54a525b..3463cea 100644 --- a/lib/snippet-expansion.js +++ b/lib/snippet-expansion.js @@ -1,7 +1,7 @@ -const {CompositeDisposable, Range, Point} = require('atom') +const { CompositeDisposable, Range, Point } = require('atom') module.exports = class SnippetExpansion { - constructor(snippet, editor, cursor, snippets) { + constructor (snippet, editor, cursor, snippets) { this.settingTabStop = false this.isIgnoringBufferChanges = false this.onUndoOrRedo = this.onUndoOrRedo.bind(this) @@ -9,15 +9,17 @@ module.exports = class SnippetExpansion { this.editor = editor this.cursor = cursor this.snippets = snippets - this.subscriptions = new CompositeDisposable + this.subscriptions = new CompositeDisposable() this.tabStopMarkers = [] this.selections = [this.cursor.selection] const startPosition = this.cursor.selection.getBufferRange().start - let {body, tabStopList} = this.snippet + let { body, tabStopList } = this.snippet let tabStops = tabStopList.toArray() - let indent = this.editor.lineTextForBufferRow(startPosition.row).match(/^\s*/)[0] + const indent = this.editor + .lineTextForBufferRow(startPosition.row) + .match(/^\s*/)[0] if (this.snippet.lineCount > 1 && indent) { // Add proper leading indentation to the snippet body = body.replace(/\n/g, `\n${indent}`) @@ -28,10 +30,16 @@ module.exports = class SnippetExpansion { this.editor.transact(() => { this.ignoringBufferChanges(() => { this.editor.transact(() => { - const newRange = this.cursor.selection.insertText(body, {autoIndent: false}) + const newRange = this.cursor.selection.insertText(body, { + autoIndent: false + }) if (this.snippet.tabStopList.length > 0) { - this.subscriptions.add(this.cursor.onDidChangePosition(event => this.cursorMoved(event))) - this.subscriptions.add(this.cursor.onDidDestroy(() => this.cursorDestroyed())) + this.subscriptions.add( + this.cursor.onDidChangePosition(event => this.cursorMoved(event)) + ) + this.subscriptions.add( + this.cursor.onDidDestroy(() => this.cursorDestroyed()) + ) this.placeTabStopMarkers(startPosition, tabStops) this.snippets.addExpansion(this.editor, this) this.editor.normalizeTabsInBufferRange(newRange) @@ -47,19 +55,31 @@ module.exports = class SnippetExpansion { this.isUndoingOrRedoing = true } - cursorMoved ({oldBufferPosition, newBufferPosition, textChanged}) { - if (this.settingTabStop || textChanged) { return } - const itemWithCursor = this.tabStopMarkers[this.tabStopIndex].find(item => item.marker.getBufferRange().containsPoint(newBufferPosition)) + cursorMoved ({ oldBufferPosition, newBufferPosition, textChanged }) { + if (this.settingTabStop || textChanged) { + return + } + const itemWithCursor = this.tabStopMarkers[this.tabStopIndex].find(item => + item.marker.getBufferRange().containsPoint(newBufferPosition) + ) - if (itemWithCursor && !itemWithCursor.insertion.isTransformation()) { return } + if (itemWithCursor && !itemWithCursor.insertion.isTransformation()) { + return + } this.destroy() } - cursorDestroyed () { if (!this.settingTabStop) { this.destroy() } } + cursorDestroyed () { + if (!this.settingTabStop) { + this.destroy() + } + } textChanged (event) { - if (this.isIgnoringBufferChanges) { return } + if (this.isIgnoringBufferChanges) { + return + } // Don't try to alter the buffer if all we're doing is restoring a // snapshot from history. @@ -81,13 +101,16 @@ module.exports = class SnippetExpansion { applyAllTransformations () { this.editor.transact(() => { this.tabStopMarkers.forEach((item, index) => - this.applyTransformations(index, true)) + this.applyTransformations(index, true) + ) }) } applyTransformations (tabStop, initial = false) { const items = [...this.tabStopMarkers[tabStop]] - if (items.length === 0) { return } + if (items.length === 0) { + return + } const primary = items.shift() const primaryRange = primary.marker.getBufferRange() @@ -95,15 +118,19 @@ module.exports = class SnippetExpansion { this.ignoringBufferChanges(() => { for (const item of items) { - const {marker, insertion} = item + const { marker, insertion } = item var range = marker.getBufferRange() // Don't transform mirrored tab stops. They have their own cursors, so // mirroring happens automatically. - if (!insertion.isTransformation()) { continue } + if (!insertion.isTransformation()) { + continue + } var outputText = insertion.transform(inputText) - this.editor.transact(() => this.editor.setTextInBufferRange(range, outputText)) + this.editor.transact(() => + this.editor.setTextInBufferRange(range, outputText) + ) const newRange = new Range( range.start, range.start.traverse(new Point(0, outputText.length)) @@ -115,14 +142,16 @@ module.exports = class SnippetExpansion { placeTabStopMarkers (startPosition, tabStops) { for (const tabStop of tabStops) { - const {insertions} = tabStop + const { insertions } = tabStop const markers = [] - if (!tabStop.isValid()) { continue } + if (!tabStop.isValid()) { + continue + } for (const insertion of insertions) { - const {range} = insertion - const {start, end} = range + const { range } = insertion + const { start, end } = range const marker = this.getMarkerLayer(this.editor).markBufferRange([ startPosition.traverse(start), startPosition.traverse(end) @@ -164,7 +193,9 @@ module.exports = class SnippetExpansion { } goToPreviousTabStop () { - if (this.tabStopIndex > 0) { this.setTabStopIndex(this.tabStopIndex - 1) } + if (this.tabStopIndex > 0) { + this.setTabStopIndex(this.tabStopIndex - 1) + } } setTabStopIndex (tabStopIndex) { @@ -173,14 +204,20 @@ module.exports = class SnippetExpansion { let markerSelected = false const items = this.tabStopMarkers[this.tabStopIndex] - if (items.length === 0) { return false } + if (items.length === 0) { + return false + } const ranges = [] this.hasTransforms = false for (const item of items) { - const {marker, insertion} = item - if (marker.isDestroyed()) { continue } - if (!marker.isValid()) { continue } + const { marker, insertion } = item + if (marker.isDestroyed()) { + continue + } + if (!marker.isValid()) { + continue + } if (insertion.isTransformation()) { this.hasTransforms = true continue @@ -189,7 +226,9 @@ module.exports = class SnippetExpansion { } if (ranges.length > 0) { - for (const selection of this.selections.slice(ranges.length)) { selection.destroy() } + for (const selection of this.selections.slice(ranges.length)) { + selection.destroy() + } this.selections = this.selections.slice(0, ranges.length) for (let i = 0; i < ranges.length; i++) { const range = ranges[i] @@ -197,8 +236,14 @@ module.exports = class SnippetExpansion { this.selections[i].setBufferRange(range) } else { const newSelection = this.editor.addSelectionForBufferRange(range) - this.subscriptions.add(newSelection.cursor.onDidChangePosition(event => this.cursorMoved(event))) - this.subscriptions.add(newSelection.cursor.onDidDestroy(() => this.cursorDestroyed())) + this.subscriptions.add( + newSelection.cursor.onDidChangePosition(event => + this.cursorMoved(event) + ) + ) + this.subscriptions.add( + newSelection.cursor.onDidDestroy(() => this.cursorDestroyed()) + ) this.selections.push(newSelection) } } @@ -208,16 +253,22 @@ module.exports = class SnippetExpansion { this.settingTabStop = false // If this snippet has at least one transform, we need to observe changes // made to the editor so that we can update the transformed tab stops. - if (this.hasTransforms) { this.snippets.observeEditor(this.editor) } + if (this.hasTransforms) { + this.snippets.observeEditor(this.editor) + } return markerSelected } goToEndOfLastTabStop () { - if (this.tabStopMarkers.length === 0) { return } + if (this.tabStopMarkers.length === 0) { + return + } const items = this.tabStopMarkers[this.tabStopMarkers.length - 1] - if (items.length === 0) { return } - const {marker: lastMarker} = items[items.length - 1] + if (items.length === 0) { + return + } + const { marker: lastMarker } = items[items.length - 1] if (lastMarker.isDestroyed()) { return false } else { diff --git a/lib/snippet-history-provider.js b/lib/snippet-history-provider.js index b1b3e57..0c78f3f 100644 --- a/lib/snippet-history-provider.js +++ b/lib/snippet-history-provider.js @@ -1,5 +1,5 @@ function wrap (manager, callbacks) { - let klass = new SnippetHistoryProvider(manager) + const klass = new SnippetHistoryProvider(manager) return new Proxy(manager, { get (target, name) { if (name in callbacks) { diff --git a/lib/snippet.js b/lib/snippet.js index fcdfed9..e22a283 100644 --- a/lib/snippet.js +++ b/lib/snippet.js @@ -1,8 +1,18 @@ -const {Range} = require('atom') +const { Range } = require('atom') const TabStopList = require('./tab-stop-list') module.exports = class Snippet { - constructor({name, prefix, bodyText, description, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML, bodyTree}) { + constructor ({ + name, + prefix, + bodyText, + description, + descriptionMoreURL, + rightLabelHTML, + leftLabel, + leftLabelHTML, + bodyTree + }) { this.name = name this.prefix = prefix this.bodyText = bodyText @@ -21,11 +31,13 @@ module.exports = class Snippet { let column = 0 // recursive helper function; mutates vars above - let extractTabStops = bodyTree => { + const extractTabStops = bodyTree => { for (const segment of bodyTree) { if (segment.index != null) { - let {index, content, substitution} = segment - if (index === 0) { index = Infinity; } + let { index, content, substitution } = segment + if (index === 0) { + index = Infinity + } const start = [row, column] extractTabStops(content) const range = new Range(start, [row, column]) diff --git a/lib/snippets-available.js b/lib/snippets-available.js index d244cb1..db53687 100644 --- a/lib/snippets-available.js +++ b/lib/snippets-available.js @@ -9,8 +9,8 @@ export default class SnippetsAvailable { this.snippets = snippets this.selectListView = new SelectListView({ items: [], - filterKeyForItem: (snippet) => snippet.searchText, - elementForItem: (snippet) => { + filterKeyForItem: snippet => snippet.searchText, + elementForItem: snippet => { const li = document.createElement('li') li.classList.add('two-lines') @@ -26,7 +26,7 @@ export default class SnippetsAvailable { return li }, - didConfirmSelection: (snippet) => { + didConfirmSelection: snippet => { for (const cursor of this.editor.getCursors()) { this.snippets.insert(snippet.bodyText, this.editor, cursor) } @@ -70,15 +70,15 @@ export default class SnippetsAvailable { populate () { const snippets = Object.values(this.snippets.getSnippets(this.editor)) - for (let snippet of snippets) { + for (const snippet of snippets) { snippet.searchText = _.compact([snippet.prefix, snippet.name]).join(' ') } - return this.selectListView.update({items: snippets}) + return this.selectListView.update({ items: snippets }) } attach () { this.previouslyFocusedElement = document.activeElement - this.panel = atom.workspace.addModalPanel({item: this}) + this.panel = atom.workspace.addModalPanel({ item: this }) this.selectListView.focus() } } diff --git a/lib/snippets.js b/lib/snippets.js index 8e67ec0..81419d1 100644 --- a/lib/snippets.js +++ b/lib/snippets.js @@ -1,5 +1,5 @@ const path = require('path') -const {Emitter, Disposable, CompositeDisposable, File} = require('atom') +const { Emitter, Disposable, CompositeDisposable, File } = require('atom') const _ = require('underscore-plus') const async = require('async') const CSON = require('season') @@ -9,72 +9,87 @@ const ScopedPropertyStore = require('scoped-property-store') const Snippet = require('./snippet') const SnippetExpansion = require('./snippet-expansion') const EditorStore = require('./editor-store') -const {getPackageRoot} = require('./helpers') +const { getPackageRoot } = require('./helpers') module.exports = { activate () { this.loaded = false this.userSnippetsPath = null this.snippetIdCounter = 0 - this.snippetsByPackage = new Map - this.parsedSnippetsById = new Map - this.editorMarkerLayers = new WeakMap + this.snippetsByPackage = new Map() + this.parsedSnippetsById = new Map() + this.editorMarkerLayers = new WeakMap() - this.scopedPropertyStore = new ScopedPropertyStore + this.scopedPropertyStore = new ScopedPropertyStore() // The above ScopedPropertyStore will store the main registry of snippets. // But we need a separate ScopedPropertyStore for the snippets that come // from disabled packages. They're isolated so that they're not considered // as candidates when the user expands a prefix, but we still need the data // around so that the snippets provided by those packages can be shown in // the settings view. - this.disabledSnippetsScopedPropertyStore = new ScopedPropertyStore + this.disabledSnippetsScopedPropertyStore = new ScopedPropertyStore() - this.subscriptions = new CompositeDisposable - this.subscriptions.add(atom.workspace.addOpener(uri => { - if (uri === 'atom://.atom/snippets') { - return atom.workspace.openTextFile(this.getUserSnippetsPath()) - } - })) + this.subscriptions = new CompositeDisposable() + this.subscriptions.add( + atom.workspace.addOpener(uri => { + if (uri === 'atom://.atom/snippets') { + return atom.workspace.openTextFile(this.getUserSnippetsPath()) + } + }) + ) this.loadAll() this.watchUserSnippets(watchDisposable => { this.subscriptions.add(watchDisposable) }) - this.subscriptions.add(atom.config.onDidChange('core.packagesWithSnippetsDisabled', ({newValue, oldValue}) => { - this.handleDisabledPackagesDidChange(newValue, oldValue) - })) + this.subscriptions.add( + atom.config.onDidChange( + 'core.packagesWithSnippetsDisabled', + ({ newValue, oldValue }) => { + this.handleDisabledPackagesDidChange(newValue, oldValue) + } + ) + ) const snippets = this - this.subscriptions.add(atom.commands.add('atom-text-editor', { - 'snippets:expand'(event) { - const editor = this.getModel() - if (snippets.snippetToExpandUnderCursor(editor)) { - snippets.clearExpansions(editor) - snippets.expandSnippetsUnderCursors(editor) - } else { - event.abortKeyBinding() + this.subscriptions.add( + atom.commands.add('atom-text-editor', { + 'snippets:expand' (event) { + const editor = this.getModel() + if (snippets.snippetToExpandUnderCursor(editor)) { + snippets.clearExpansions(editor) + snippets.expandSnippetsUnderCursors(editor) + } else { + event.abortKeyBinding() + } + }, + + 'snippets:next-tab-stop' (event) { + const editor = this.getModel() + if (!snippets.goToNextTabStop(editor)) { + event.abortKeyBinding() + } + }, + + 'snippets:previous-tab-stop' (event) { + const editor = this.getModel() + if (!snippets.goToPreviousTabStop(editor)) { + event.abortKeyBinding() + } + }, + + 'snippets:available' (event) { + const editor = this.getModel() + const SnippetsAvailable = require('./snippets-available') + if (snippets.availableSnippetsView == null) { + snippets.availableSnippetsView = new SnippetsAvailable(snippets) + } + snippets.availableSnippetsView.toggle(editor) } - }, - - 'snippets:next-tab-stop'(event) { - const editor = this.getModel() - if (!snippets.goToNextTabStop(editor)) { event.abortKeyBinding() } - }, - - 'snippets:previous-tab-stop'(event) { - const editor = this.getModel() - if (!snippets.goToPreviousTabStop(editor)) { event.abortKeyBinding() } - }, - - 'snippets:available'(event) { - const editor = this.getModel() - const SnippetsAvailable = require('./snippets-available') - if (snippets.availableSnippetsView == null) { snippets.availableSnippetsView = new SnippetsAvailable(snippets) } - snippets.availableSnippetsView.toggle(editor) - } - })) + }) + ) }, deactivate () { @@ -87,19 +102,32 @@ module.exports = { }, getUserSnippetsPath () { - if (this.userSnippetsPath != null) { return this.userSnippetsPath } + if (this.userSnippetsPath != null) { + return this.userSnippetsPath + } - this.userSnippetsPath = CSON.resolve(path.join(atom.getConfigDirPath(), 'snippets')) - if (this.userSnippetsPath == null) { this.userSnippetsPath = path.join(atom.getConfigDirPath(), 'snippets.cson') } + this.userSnippetsPath = CSON.resolve( + path.join(atom.getConfigDirPath(), 'snippets') + ) + if (this.userSnippetsPath == null) { + this.userSnippetsPath = path.join( + atom.getConfigDirPath(), + 'snippets.cson' + ) + } return this.userSnippetsPath }, loadAll () { this.loadBundledSnippets(bundledSnippets => { this.loadPackageSnippets(packageSnippets => { - this.loadUserSnippets(userSnippets => { + this.loadUserSnippets((userSnippets = {}) => { atom.config.transact(() => { - for (const snippetSet of [bundledSnippets, packageSnippets, userSnippets]) { + for (const snippetSet of [ + bundledSnippets, + packageSnippets, + userSnippets + ]) { for (const filepath in snippetSet) { const snippetsBySelector = snippetSet[filepath] this.add(filepath, snippetsBySelector) @@ -113,8 +141,10 @@ module.exports = { }, loadBundledSnippets (callback) { - const bundledSnippetsPath = CSON.resolve(path.join(getPackageRoot(), 'lib', 'snippets')) - this.loadSnippetsFile(bundledSnippetsPath, snippets => { + const bundledSnippetsPath = CSON.resolve( + path.join(getPackageRoot(), 'lib', 'snippets') + ) + this.loadSnippetsFile(bundledSnippetsPath, (snippets = {}) => { const snippetsByPath = {} snippetsByPath[bundledSnippetsPath] = snippets callback(snippetsByPath) @@ -124,14 +154,14 @@ module.exports = { loadUserSnippets (callback) { const userSnippetsPath = this.getUserSnippetsPath() fs.stat(userSnippetsPath, (error, stat) => { - if (stat != null && stat.isFile()) { - this.loadSnippetsFile(userSnippetsPath, snippets => { + if (!error && stat.isFile()) { + this.loadSnippetsFile(userSnippetsPath, (snippets = {}) => { const result = {} result[userSnippetsPath] = snippets callback(result) }) } else { - callback({}) + callback() } }) }, @@ -139,13 +169,25 @@ module.exports = { watchUserSnippets (callback) { const userSnippetsPath = this.getUserSnippetsPath() fs.stat(userSnippetsPath, (error, stat) => { - if (stat != null && stat.isFile()) { + if (!error && stat.isFile()) { const userSnippetsFileDisposable = new CompositeDisposable() const userSnippetsFile = new File(userSnippetsPath) try { - userSnippetsFileDisposable.add(userSnippetsFile.onDidChange(() => this.handleUserSnippetsDidChange())) - userSnippetsFileDisposable.add(userSnippetsFile.onDidDelete(() => this.handleUserSnippetsDidChange())) - userSnippetsFileDisposable.add(userSnippetsFile.onDidRename(() => this.handleUserSnippetsDidChange())) + userSnippetsFileDisposable.add( + userSnippetsFile.onDidChange(() => + this.handleUserSnippetsDidChange() + ) + ) + userSnippetsFileDisposable.add( + userSnippetsFile.onDidDelete(() => + this.handleUserSnippetsDidChange() + ) + ) + userSnippetsFileDisposable.add( + userSnippetsFile.onDidRename(() => + this.handleUserSnippetsDidChange() + ) + ) } catch (e) { const message = `\ Unable to watch path: \`snippets.cson\`. Make sure you have permissions @@ -155,7 +197,7 @@ module.exports = { [this document][watches] for more info. [watches]:https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#typeerror-unable-to-watch-path\ ` - atom.notifications.addError(message, {dismissable: true}) + atom.notifications.addError(message, { dismissable: true }) } callback(userSnippetsFileDisposable) @@ -171,7 +213,7 @@ module.exports = { const userSnippetsPath = this.getUserSnippetsPath() atom.config.transact(() => { this.clearSnippetsForPath(userSnippetsPath) - this.loadSnippetsFile(userSnippetsPath, result => { + this.loadSnippetsFile(userSnippetsPath, (result = {}) => { this.add(userSnippetsPath, result) }) }) @@ -179,20 +221,31 @@ module.exports = { // Called when the "Enable" checkbox is checked/unchecked in the Snippets // section of a package's settings view. - handleDisabledPackagesDidChange (newDisabledPackages = [], oldDisabledPackages = []) { + handleDisabledPackagesDidChange ( + newDisabledPackages = [], + oldDisabledPackages = [] + ) { const packagesToAdd = [] const packagesToRemove = [] for (const p of oldDisabledPackages) { - if (!newDisabledPackages.includes(p)) { packagesToAdd.push(p) } + if (!newDisabledPackages.includes(p)) { + packagesToAdd.push(p) + } } for (const p of newDisabledPackages) { - if (!oldDisabledPackages.includes(p)) { packagesToRemove.push(p) } + if (!oldDisabledPackages.includes(p)) { + packagesToRemove.push(p) + } } atom.config.transact(() => { - for (const p of packagesToRemove) { this.removeSnippetsForPackage(p) } - for (const p of packagesToAdd) { this.addSnippetsForPackage(p) } + for (const p of packagesToRemove) { + this.removeSnippetsForPackage(p) + } + for (const p of packagesToAdd) { + this.addSnippetsForPackage(p) + } }) }, @@ -216,7 +269,8 @@ module.exports = { }, loadPackageSnippets (callback) { - const disabledPackageNames = atom.config.get('core.packagesWithSnippetsDisabled') || [] + const disabledPackageNames = + atom.config.get('core.packagesWithSnippetsDisabled') || [] const packages = atom.packages.getLoadedPackages().sort((pack, _) => { return /\/node_modules\//.test(pack.path) ? -1 : 1 }) @@ -226,34 +280,43 @@ module.exports = { snippetsDirPaths.push(path.join(pack.path, 'snippets')) } - async.map(snippetsDirPaths, this.loadSnippetsDirectory.bind(this), (error, results) => { - const zipped = [] - for (const key in results) { - zipped.push({result: results[key], pack: packages[key]}) - } + async.map( + snippetsDirPaths, + this.loadSnippetsDirectory.bind(this), + (error, results) => { + if (error) { + callback() + } + const zipped = [] + for (const key in results) { + zipped.push({ result: results[key], pack: packages[key] }) + } - const enabledPackages = [] - for (const o of zipped) { - // Skip packages that contain no snippets. - if (Object.keys(o.result).length === 0) { continue } - // Keep track of which snippets come from which packages so we can - // unload them selectively later. All packages get put into this map, - // even disabled packages, because we need to know which snippets to add - // if those packages are enabled again. - this.snippetsByPackage.set(o.pack.name, o.result) - if (disabledPackageNames.includes(o.pack.name)) { - // Since disabled packages' snippets won't get added to the main - // ScopedPropertyStore, we'll keep track of them in a separate - // ScopedPropertyStore so that they can still be represented in the - // settings view. - this.addSnippetsInDisabledPackage(o.result) - } else { - enabledPackages.push(o.result) + const enabledPackages = [] + for (const o of zipped) { + // Skip packages that contain no snippets. + if (Object.keys(o.result).length === 0) { + continue + } + // Keep track of which snippets come from which packages so we can + // unload them selectively later. All packages get put into this map, + // even disabled packages, because we need to know which snippets to add + // if those packages are enabled again. + this.snippetsByPackage.set(o.pack.name, o.result) + if (disabledPackageNames.includes(o.pack.name)) { + // Since disabled packages' snippets won't get added to the main + // ScopedPropertyStore, we'll keep track of them in a separate + // ScopedPropertyStore so that they can still be represented in the + // settings view. + this.addSnippetsInDisabledPackage(o.result) + } else { + enabledPackages.push(o.result) + } } - } - callback(_.extend({}, ...enabledPackages)) - }) + callback(_.extend({}, ...enabledPackages)) + } + ) }, doneLoading () { @@ -267,18 +330,23 @@ module.exports = { getEmitter () { if (this.emitter == null) { - this.emitter = new Emitter + this.emitter = new Emitter() } return this.emitter }, loadSnippetsDirectory (snippetsDirPath, callback) { fs.isDirectory(snippetsDirPath, isDirectory => { - if (!isDirectory) { return callback(null, {}) } + if (!isDirectory) { + return callback(null, {}) + } fs.readdir(snippetsDirPath, (error, entries) => { if (error) { - console.warn(`Error reading snippets directory ${snippetsDirPath}`, error) + console.warn( + `Error reading snippets directory ${snippetsDirPath}`, + error + ) return callback(null, {}) } @@ -286,28 +354,44 @@ module.exports = { entries, (entry, done) => { const filePath = path.join(snippetsDirPath, entry) - this.loadSnippetsFile(filePath, snippets => done(null, {filePath, snippets})) + this.loadSnippetsFile(filePath, (snippets = {}) => + done(null, { filePath, snippets }) + ) }, (error, results) => { const snippetsByPath = {} - for (const {filePath, snippets} of results) { + for (const { filePath, snippets } of results) { snippetsByPath[filePath] = snippets } - callback(null, snippetsByPath) - }) + callback(error, snippetsByPath) + } + ) }) }) }, loadSnippetsFile (filePath, callback) { - if (!CSON.isObjectPath(filePath)) { return callback({}) } - CSON.readFile(filePath, {allowDuplicateKeys: false}, (error, object = {}) => { - if (error != null) { - console.warn(`Error reading snippets file '${filePath}': ${error.stack != null ? error.stack : error}`) - atom.notifications.addError(`Failed to load snippets from '${filePath}'`, {detail: error.message, dismissable: true}) + if (!CSON.isObjectPath(filePath)) { + return callback() + } + CSON.readFile( + filePath, + { allowDuplicateKeys: false }, + (error, object = {}) => { + if (error != null) { + console.warn( + `Error reading snippets file '${filePath}': ${ + error.stack != null ? error.stack : error + }` + ) + atom.notifications.addError( + `Failed to load snippets from '${filePath}'`, + { detail: error.message, dismissable: true } + ) + } + callback(object) } - callback(object) - }) + ) }, add (filePath, snippetsBySelector, isDisabled = false) { @@ -316,7 +400,7 @@ module.exports = { const unparsedSnippetsByPrefix = {} for (const name in snippetsByName) { const attributes = snippetsByName[name] - const {prefix, body} = attributes + const { prefix, body } = attributes attributes.name = name attributes.id = this.snippetIdCounter++ if (typeof body === 'string') { @@ -326,7 +410,12 @@ module.exports = { } } - this.storeUnparsedSnippets(unparsedSnippetsByPrefix, filePath, selector, isDisabled) + this.storeUnparsedSnippets( + unparsedSnippetsByPrefix, + filePath, + selector, + isDisabled + ) } }, @@ -344,7 +433,7 @@ module.exports = { } return scopesArray - .map(scope => scope[0] === '.' ? scope : `.${scope}`) + .map(scope => (scope[0] === '.' ? scope : `.${scope}`)) .join(' ') }, @@ -355,20 +444,32 @@ module.exports = { // prefix for expansion, but both stores have their contents exported when // the settings view asks for all available snippets. const unparsedSnippets = {} - unparsedSnippets[selector] = {"snippets": value} - const store = isDisabled ? this.disabledSnippetsScopedPropertyStore : this.scopedPropertyStore - store.addProperties(path, unparsedSnippets, {priority: this.priorityForSource(path)}) + unparsedSnippets[selector] = { snippets: value } + const store = isDisabled + ? this.disabledSnippetsScopedPropertyStore + : this.scopedPropertyStore + store.addProperties(path, unparsedSnippets, { + priority: this.priorityForSource(path) + }) }, clearSnippetsForPath (path) { - for (const scopeSelector in this.scopedPropertyStore.propertiesForSource(path)) { - const object = this.scopedPropertyStore.propertiesForSourceAndSelector(path, scopeSelector) + for (const scopeSelector in this.scopedPropertyStore.propertiesForSource( + path + )) { + const object = this.scopedPropertyStore.propertiesForSourceAndSelector( + path, + scopeSelector + ) for (const prefix in object) { const attributes = object[prefix] this.parsedSnippetsById.delete(attributes.id) } - this.scopedPropertyStore.removePropertiesForSourceAndSelector(path, scopeSelector) + this.scopedPropertyStore.removePropertiesForSourceAndSelector( + path, + scopeSelector + ) } }, @@ -377,17 +478,20 @@ module.exports = { const unparsedSnippetsByPrefix = this.scopedPropertyStore.getPropertyValue( this.getScopeChain(scopeDescriptor), - "snippets" + 'snippets' ) - const legacyScopeDescriptor = atom.config.getLegacyScopeDescriptorForNewScopeDescriptor - ? atom.config.getLegacyScopeDescriptorForNewScopeDescriptor(scopeDescriptor) + const legacyScopeDescriptor = atom.config + .getLegacyScopeDescriptorForNewScopeDescriptor + ? atom.config.getLegacyScopeDescriptorForNewScopeDescriptor( + scopeDescriptor + ) : undefined if (legacyScopeDescriptor) { unparsedLegacySnippetsByPrefix = this.scopedPropertyStore.getPropertyValue( this.getScopeChain(legacyScopeDescriptor), - "snippets" + 'snippets' ) } @@ -396,7 +500,11 @@ module.exports = { if (unparsedSnippetsByPrefix) { for (const prefix in unparsedSnippetsByPrefix) { const attributes = unparsedSnippetsByPrefix[prefix] - if (typeof (attributes != null ? attributes.body : undefined) !== 'string') { continue } + if ( + typeof (attributes != null ? attributes.body : undefined) !== 'string' + ) { + continue + } snippets[prefix] = this.getParsedSnippet(attributes) } } @@ -404,8 +512,14 @@ module.exports = { if (unparsedLegacySnippetsByPrefix) { for (const prefix in unparsedLegacySnippetsByPrefix) { const attributes = unparsedLegacySnippetsByPrefix[prefix] - if (snippets[prefix]) { continue } - if (typeof (attributes != null ? attributes.body : undefined) !== 'string') { continue } + if (snippets[prefix]) { + continue + } + if ( + typeof (attributes != null ? attributes.body : undefined) !== 'string' + ) { + continue + } snippets[prefix] = this.getParsedSnippet(attributes) } } @@ -416,9 +530,33 @@ module.exports = { getParsedSnippet (attributes) { let snippet = this.parsedSnippetsById.get(attributes.id) if (snippet == null) { - let {id, prefix, name, body, bodyTree, description, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML} = attributes - if (bodyTree == null) { bodyTree = this.getBodyParser().parse(body) } - snippet = new Snippet({id, name, prefix, bodyTree, description, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML, bodyText: body}) + let { + id, + prefix, + name, + body, + bodyTree, + description, + descriptionMoreURL, + rightLabelHTML, + leftLabel, + leftLabelHTML + } = attributes + if (bodyTree == null) { + bodyTree = this.getBodyParser().parse(body) + } + snippet = new Snippet({ + id, + name, + prefix, + bodyTree, + description, + descriptionMoreURL, + rightLabelHTML, + leftLabel, + leftLabelHTML, + bodyText: body + }) this.parsedSnippetsById.set(attributes.id, snippet) } return snippet @@ -453,18 +591,24 @@ module.exports = { for (const cursor of editor.getCursors()) { const position = cursor.getBufferPosition() - const prefixStart = cursor.getBeginningOfCurrentWordBufferPosition({wordRegex}) + const prefixStart = cursor.getBeginningOfCurrentWordBufferPosition({ + wordRegex + }) const cursorSnippetPrefix = editor.getTextInRange([prefixStart, position]) - if ((snippetPrefix != null) && (cursorSnippetPrefix !== snippetPrefix)) { return null } + if (snippetPrefix != null && cursorSnippetPrefix !== snippetPrefix) { + return null + } snippetPrefix = cursorSnippetPrefix const wordStart = cursor.getBeginningOfCurrentWordBufferPosition() const cursorWordPrefix = editor.getTextInRange([wordStart, position]) - if ((wordPrefix != null) && (cursorWordPrefix !== wordPrefix)) { return null } + if (wordPrefix != null && cursorWordPrefix !== wordPrefix) { + return null + } wordPrefix = cursorWordPrefix } - return {snippetPrefix, wordPrefix} + return { snippetPrefix, wordPrefix } }, // Get a RegExp of all the characters used in the snippet prefixes @@ -472,7 +616,9 @@ module.exports = { const prefixes = {} for (const prefix in snippets) { - for (const character of prefix) { prefixes[character] = true } + for (const character of prefix) { + prefixes[character] = true + } } const prefixCharacters = Object.keys(prefixes).join('') @@ -486,8 +632,14 @@ module.exports = { for (const snippetPrefix in snippets) { const snippet = snippets[snippetPrefix] - if (prefix.endsWith(snippetPrefix) && (wordPrefix.length <= snippetPrefix.length)) { - if ((longestPrefixMatch == null) || (snippetPrefix.length > longestPrefixMatch.prefix.length)) { + if ( + prefix.endsWith(snippetPrefix) && + wordPrefix.length <= snippetPrefix.length + ) { + if ( + longestPrefixMatch == null || + snippetPrefix.length > longestPrefixMatch.prefix.length + ) { longestPrefixMatch = snippet } } @@ -497,27 +649,43 @@ module.exports = { }, getSnippets (editor) { - return this.parsedSnippetsForScopes(editor.getLastCursor().getScopeDescriptor()) + return this.parsedSnippetsForScopes( + editor.getLastCursor().getScopeDescriptor() + ) }, snippetToExpandUnderCursor (editor) { - if (!editor.getLastSelection().isEmpty()) { return false } + if (!editor.getLastSelection().isEmpty()) { + return false + } const snippets = this.getSnippets(editor) - if (_.isEmpty(snippets)) { return false } + if (_.isEmpty(snippets)) { + return false + } const prefixData = this.getPrefixText(snippets, editor) if (prefixData) { - return this.snippetForPrefix(snippets, prefixData.snippetPrefix, prefixData.wordPrefix) + return this.snippetForPrefix( + snippets, + prefixData.snippetPrefix, + prefixData.wordPrefix + ) } }, expandSnippetsUnderCursors (editor) { const snippet = this.snippetToExpandUnderCursor(editor) - if (!snippet) { return false } + if (!snippet) { + return false + } this.getStore(editor).observeHistory({ - undo: event => { this.onUndoOrRedo(editor, event, true) }, - redo: event => { this.onUndoOrRedo(editor, event, false) } + undo: event => { + this.onUndoOrRedo(editor, event, true) + }, + redo: event => { + this.onUndoOrRedo(editor, event, false) + } }) this.findOrCreateMarkerLayer(editor) @@ -525,7 +693,10 @@ module.exports = { const cursors = editor.getCursors() for (const cursor of cursors) { const cursorPosition = cursor.getBufferPosition() - const startPoint = cursorPosition.translate([0, -snippet.prefix.length], [0, 0]) + const startPoint = cursorPosition.translate( + [0, -snippet.prefix.length], + [0, 0] + ) cursor.selection.setBufferRange([startPoint, cursorPosition]) this.insert(snippet, editor, cursor) } @@ -560,7 +731,7 @@ module.exports = { findOrCreateMarkerLayer (editor) { let layer = this.editorMarkerLayers.get(editor) if (layer === undefined) { - layer = editor.addMarkerLayer({maintainHistory: true}) + layer = editor.addMarkerLayer({ maintainHistory: true }) this.editorMarkerLayers.set(editor, layer) } return layer @@ -587,11 +758,17 @@ module.exports = { const store = this.getStore(editor) const activeExpansions = store.getExpansions() - if ((activeExpansions.length === 0) || activeExpansions[0].isIgnoringBufferChanges) { return } + if ( + activeExpansions.length === 0 || + activeExpansions[0].isIgnoringBufferChanges + ) { + return + } this.ignoringTextChangesForEditor(editor, () => editor.transact(() => - activeExpansions.map(expansion => expansion.textChanged(event))) + activeExpansions.map(expansion => expansion.textChanged(event)) + ) ) // Create a checkpoint here to consolidate all the changes we just made into @@ -620,11 +797,20 @@ module.exports = { }, insert (snippet, editor, cursor) { - if (editor == null) { editor = atom.workspace.getActiveTextEditor() } - if (cursor == null) { cursor = editor.getLastCursor() } + if (editor == null) { + editor = atom.workspace.getActiveTextEditor() + } + if (cursor == null) { + cursor = editor.getLastCursor() + } if (typeof snippet === 'string') { const bodyTree = this.getBodyParser().parse(snippet) - snippet = new Snippet({name: '__anonymous', prefix: '', bodyTree, bodyText: snippet}) + snippet = new Snippet({ + name: '__anonymous', + prefix: '', + bodyTree, + bodyText: snippet + }) } return new SnippetExpansion(snippet, editor, cursor, this) }, diff --git a/lib/tab-stop-list.js b/lib/tab-stop-list.js index 0d3bd01..7391b24 100644 --- a/lib/tab-stop-list.js +++ b/lib/tab-stop-list.js @@ -22,12 +22,12 @@ class TabStopList { } forEachIndex (iterator) { - let indices = Object.keys(this.list).sort((a1, a2) => a1 - a2) + const indices = Object.keys(this.list).sort((a1, a2) => a1 - a2) indices.forEach(iterator) } getInsertions () { - let results = [] + const results = [] this.forEachIndex(index => { results.push(...this.list[index].insertions) }) @@ -35,9 +35,9 @@ class TabStopList { } toArray () { - let results = [] + const results = [] this.forEachIndex(index => { - let tabStop = this.list[index] + const tabStop = this.list[index] if (!tabStop.isValid()) return results.push(tabStop) }) diff --git a/lib/tab-stop.js b/lib/tab-stop.js index 61a423e..e6af340 100644 --- a/lib/tab-stop.js +++ b/lib/tab-stop.js @@ -1,4 +1,4 @@ -const {Range} = require('atom') +const { Range } = require('atom') const Insertion = require('./insertion') // A tab stop: @@ -12,22 +12,22 @@ class TabStop { } isValid () { - let any = this.insertions.some(insertion => insertion.isTransformation()) + const any = this.insertions.some(insertion => insertion.isTransformation()) if (!any) return true - let all = this.insertions.every(insertion => insertion.isTransformation()) + const all = this.insertions.every(insertion => insertion.isTransformation()) // If there are any transforming insertions, there must be at least one // non-transforming insertion to act as the primary. return !all } addInsertion ({ range, substitution }) { - let insertion = new Insertion({ range, substitution }) + const insertion = new Insertion({ range, substitution }) let insertions = this.insertions insertions.push(insertion) insertions = insertions.sort((i1, i2) => { return i1.range.start.compare(i2.range.start) }) - let initial = insertions.find(insertion => !insertion.isTransformation()) + const initial = insertions.find(insertion => !insertion.isTransformation()) if (initial) { insertions.splice(insertions.indexOf(initial), 1) insertions.unshift(initial) @@ -36,10 +36,10 @@ class TabStop { } copyWithIndent (indent) { - let { snippet, index, insertions } = this - let newInsertions = insertions.map(insertion => { - let { range, substitution } = insertion - let newRange = Range.fromObject(range, true) + const { snippet, index, insertions } = this + const newInsertions = insertions.map(insertion => { + const { range, substitution } = insertion + const newRange = Range.fromObject(range, true) if (newRange.start.row) { newRange.start.column += indent.length newRange.end.column += indent.length diff --git a/spec/body-parser-spec.js b/spec/body-parser-spec.js index 35492de..3e62e6c 100644 --- a/spec/body-parser-spec.js +++ b/spec/body-parser-spec.js @@ -1,227 +1,205 @@ -const BodyParser = require('../lib/snippet-body-parser'); +const BodyParser = require('../lib/snippet-body-parser') -describe("Snippet Body Parser", () => { - it("breaks a snippet body into lines, with each line containing tab stops at the appropriate position", () => { +describe('Snippet Body Parser', () => { + it('breaks a snippet body into lines, with each line containing tab stops at the appropriate position', () => { const bodyTree = BodyParser.parse(`\ the quick brown $1fox \${2:jumped \${3:over} }the \${4:lazy} dog\ -` - ); +`) expect(bodyTree).toEqual([ - "the quick brown ", - {index: 1, content: []}, - "fox ", + 'the quick brown ', + { index: 1, content: [] }, + 'fox ', { index: 2, - content: [ - "jumped ", - {index: 3, content: ["over"]}, - "\n" - ], + content: ['jumped ', { index: 3, content: ['over'] }, '\n'] }, - "the ", - {index: 4, content: ["lazy"]}, - " dog" - ]); - }); + 'the ', + { index: 4, content: ['lazy'] }, + ' dog' + ]) + }) it("removes interpolated variables in placeholder text (we don't currently support it)", () => { - const bodyTree = BodyParser.parse("module ${1:ActiveRecord::${TM_FILENAME/(?:\\A|_)([A-Za-z0-9]+)(?:\\.rb)?/(?2::\\u$1)/g}}"); + const bodyTree = BodyParser.parse( + 'module ${1:ActiveRecord::${TM_FILENAME/(?:\\A|_)([A-Za-z0-9]+)(?:\\.rb)?/(?2::\\u$1)/g}}' + ) expect(bodyTree).toEqual([ - "module ", + 'module ', { - "index": 1, - "content": ["ActiveRecord::", ""] + index: 1, + content: ['ActiveRecord::', ''] } - ]); - }); + ]) + }) - it("skips escaped tabstops", () => { - const bodyTree = BodyParser.parse("snippet $1 escaped \\$2 \\\\$3"); + it('skips escaped tabstops', () => { + const bodyTree = BodyParser.parse('snippet $1 escaped \\$2 \\\\$3') expect(bodyTree).toEqual([ - "snippet ", + 'snippet ', { index: 1, content: [] }, - " escaped $2 \\", + ' escaped $2 \\', { index: 3, content: [] } - ]); - }); + ]) + }) - it("includes escaped right-braces", () => { - const bodyTree = BodyParser.parse("snippet ${1:{\\}}"); + it('includes escaped right-braces', () => { + const bodyTree = BodyParser.parse(`snippet \${1:{\\}}`) expect(bodyTree).toEqual([ - "snippet ", + 'snippet ', { index: 1, - content: ["{}"] + content: ['{}'] } - ]); - }); + ]) + }) - it("parses a snippet with transformations", () => { - const bodyTree = BodyParser.parse("<${1:p}>$0"); + it('parses a snippet with transformations', () => { + const bodyTree = BodyParser.parse('<${1:p}>$0') expect(bodyTree).toEqual([ '<', - {index: 1, content: ['p']}, + { index: 1, content: ['p'] }, '>', - {index: 0, content: []}, + { index: 0, content: [] }, '' - ]); - }); + ]) + }) - it("parses a snippet with multiple tab stops with transformations", () => { - const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"); + it('parses a snippet with multiple tab stops with transformations', () => { + const bodyTree = BodyParser.parse( + '${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2' + ) expect(bodyTree).toEqual([ - {index: 1, content: ['placeholder']}, + { index: 1, content: ['placeholder'] }, ' ', { index: 1, content: [], substitution: { find: /(.)/g, - replace: [ - {escape: 'u'}, - {backreference: 1} - ] + replace: [{ escape: 'u' }, { backreference: 1 }] } }, ' ', - {index: 1, content: []}, + { index: 1, content: [] }, ' ', - {index: 2, content: ['ANOTHER']}, + { index: 2, content: ['ANOTHER'] }, ' ', { index: 2, content: [], substitution: { find: /^(.*)$/g, - replace: [ - {escape: 'L'}, - {backreference: 1} - ] + replace: [{ escape: 'L' }, { backreference: 1 }] } }, ' ', - {index: 2, content: []}, - ]); - }); - + { index: 2, content: [] } + ]) + }) - it("parses a snippet with transformations and mirrors", () => { - const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/}\n$1"); + it('parses a snippet with transformations and mirrors', () => { + const bodyTree = BodyParser.parse('${1:placeholder}\n${1/(.)/\\u$1/}\n$1') expect(bodyTree).toEqual([ - {index: 1, content: ['placeholder']}, + { index: 1, content: ['placeholder'] }, '\n', { index: 1, content: [], substitution: { find: /(.)/g, - replace: [ - {escape: 'u'}, - {backreference: 1} - ] + replace: [{ escape: 'u' }, { backreference: 1 }] } }, '\n', - {index: 1, content: []} - ]); - }); + { index: 1, content: [] } + ]) + }) - it("parses a snippet with a format string and case-control flags", () => { - const bodyTree = BodyParser.parse("<${1:p}>$0"); + it('parses a snippet with a format string and case-control flags', () => { + const bodyTree = BodyParser.parse('<${1:p}>$0') expect(bodyTree).toEqual([ '<', - {index: 1, content: ['p']}, + { index: 1, content: ['p'] }, '>', - {index: 0, content: []}, + { index: 0, content: [] }, '' - ]); - }); + ]) + }) - it("parses a snippet with an escaped forward slash in a transform", () => { + it('parses a snippet with an escaped forward slash in a transform', () => { // Annoyingly, a forward slash needs to be double-backslashed just like the // other escapes. - const bodyTree = BodyParser.parse("<${1:p}>$0"); + const bodyTree = BodyParser.parse('<${1:p}>$0') expect(bodyTree).toEqual([ '<', - {index: 1, content: ['p']}, + { index: 1, content: ['p'] }, '>', - {index: 0, content: []}, + { index: 0, content: [] }, '' - ]); - }); + ]) + }) it("parses a snippet with a placeholder that mirrors another tab stop's content", () => { - const bodyTree = BodyParser.parse("$4console.${3:log}('${2:$1}', $1);$0"); + const bodyTree = BodyParser.parse("$4console.${3:log}('${2:$1}', $1);$0") expect(bodyTree).toEqual([ - {index: 4, content: []}, + { index: 4, content: [] }, 'console.', - {index: 3, content: ['log']}, - '(\'', + { index: 3, content: ['log'] }, + "('", { - index: 2, content: [ - {index: 1, content: []} - ] + index: 2, + content: [{ index: 1, content: [] }] }, - '\', ', - {index: 1, content: []}, + "', ", + { index: 1, content: [] }, ');', - {index: 0, content: []} - ]); - }); + { index: 0, content: [] } + ]) + }) - it("parses a snippet with a placeholder that mixes text and tab stop references", () => { - const bodyTree = BodyParser.parse("$4console.${3:log}('${2:uh $1}', $1);$0"); + it('parses a snippet with a placeholder that mixes text and tab stop references', () => { + const bodyTree = BodyParser.parse("$4console.${3:log}('${2:uh $1}', $1);$0") expect(bodyTree).toEqual([ - {index: 4, content: []}, + { index: 4, content: [] }, 'console.', - {index: 3, content: ['log']}, - '(\'', + { index: 3, content: ['log'] }, + "('", { - index: 2, content: [ - 'uh ', - {index: 1, content: []} - ] + index: 2, + content: ['uh ', { index: 1, content: [] }] }, - '\', ', - {index: 1, content: []}, + "', ", + { index: 1, content: [] }, ');', - {index: 0, content: []} - ]); - }); -}); + { index: 0, content: [] } + ]) + }) +}) diff --git a/spec/insertion-spec.js b/spec/insertion-spec.js index 83fac92..949870d 100644 --- a/spec/insertion-spec.js +++ b/spec/insertion-spec.js @@ -5,30 +5,30 @@ const range = new Range(0, 0) describe('Insertion', () => { it('returns what it was given when it has no substitution', () => { - let insertion = new Insertion({ + const insertion = new Insertion({ range, substitution: undefined }) - let transformed = insertion.transform('foo!') + const transformed = insertion.transform('foo!') expect(transformed).toEqual('foo!') }) it('transforms what it was given when it has a regex transformation', () => { - let insertion = new Insertion({ + const insertion = new Insertion({ range, substitution: { find: /foo/g, replace: ['bar'] } }) - let transformed = insertion.transform('foo!') + const transformed = insertion.transform('foo!') expect(transformed).toEqual('bar!') }) it('transforms the case of the next character when encountering a \\u or \\l flag', () => { - let uInsertion = new Insertion({ + const uInsertion = new Insertion({ range, substitution: { find: /(.)(.)(.*)/g, @@ -45,7 +45,7 @@ describe('Insertion', () => { expect(uInsertion.transform('fOo!')).toEqual('fOo!') expect(uInsertion.transform('FOO!')).toEqual('FOO!') - let lInsertion = new Insertion({ + const lInsertion = new Insertion({ range, substitution: { find: /(.{2})(.)(.*)/g, @@ -65,15 +65,11 @@ describe('Insertion', () => { }) it('transforms the case of all remaining characters when encountering a \\U or \\L flag, up until it sees a \\E flag', () => { - let uInsertion = new Insertion({ + const uInsertion = new Insertion({ range, substitution: { find: /(.)(.*)/, - replace: [ - { backreference: 1 }, - { escape: 'U' }, - { backreference: 2 } - ] + replace: [{ backreference: 1 }, { escape: 'U' }, { backreference: 2 }] } }) @@ -81,7 +77,7 @@ describe('Insertion', () => { expect(uInsertion.transform('lOREM IPSUM!')).toEqual('lOREM IPSUM!') expect(uInsertion.transform('LOREM IPSUM!')).toEqual('LOREM IPSUM!') - let ueInsertion = new Insertion({ + const ueInsertion = new Insertion({ range, substitution: { find: /(.)(.{3})(.*)/, @@ -99,7 +95,7 @@ describe('Insertion', () => { expect(ueInsertion.transform('lOREm ipsum!')).toEqual('lOREm ipsum!') expect(ueInsertion.transform('LOREM IPSUM!')).toEqual('LOREM IPSUM!') - let lInsertion = new Insertion({ + const lInsertion = new Insertion({ range, substitution: { find: /(.{4})(.)(.*)/, @@ -114,7 +110,7 @@ describe('Insertion', () => { expect(lInsertion.transform('LOREM IPSUM!')).toEqual('LOREmwhat') - let leInsertion = new Insertion({ + const leInsertion = new Insertion({ range, substitution: { find: /^([A-Fa-f])(.*)(.)$/, diff --git a/spec/snippet-loading-spec.js b/spec/snippet-loading-spec.js index d6c5dd1..a9b280d 100644 --- a/spec/snippet-loading-spec.js +++ b/spec/snippet-loading-spec.js @@ -1,132 +1,164 @@ -const path = require('path'); -const fs = require('fs-plus'); -const temp = require('temp').track(); +const path = require('path') +const fs = require('fs-plus') +const temp = require('temp').track() -describe("Snippet Loading", () => { - let configDirPath, snippetsService; +describe('Snippet Loading', () => { + let configDirPath, snippetsService beforeEach(() => { - configDirPath = temp.mkdirSync('atom-config-dir-'); - spyOn(atom, 'getConfigDirPath').andReturn(configDirPath); + configDirPath = temp.mkdirSync('atom-config-dir-') + spyOn(atom, 'getConfigDirPath').andReturn(configDirPath) - spyOn(console, 'warn'); - if (atom.notifications != null) { spyOn(atom.notifications, 'addError'); } + spyOn(console, 'warn') + if (atom.notifications != null) { + spyOn(atom.notifications, 'addError') + } spyOn(atom.packages, 'getLoadedPackages').andReturn([ - atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-snippets')), - atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-broken-snippets')), - ]); - }); + atom.packages.loadPackage( + path.join(__dirname, 'fixtures', 'package-with-snippets') + ), + atom.packages.loadPackage( + path.join(__dirname, 'fixtures', 'package-with-broken-snippets') + ) + ]) + }) afterEach(() => { - waitsForPromise(() => Promise.resolve(atom.packages.deactivatePackages('snippets'))); + waitsForPromise(() => + Promise.resolve(atom.packages.deactivatePackages('snippets')) + ) runs(() => { - jasmine.unspy(atom.packages, 'getLoadedPackages'); - }); - }); + jasmine.unspy(atom.packages, 'getLoadedPackages') + }) + }) const activateSnippetsPackage = () => { - waitsForPromise(() => atom.packages.activatePackage("snippets").then(({mainModule}) => { - snippetsService = mainModule.provideSnippets(); - mainModule.loaded = false; - })); - - waitsFor("all snippets to load", 3000, () => snippetsService.bundledSnippetsLoaded()); - }; + waitsForPromise(() => + atom.packages.activatePackage('snippets').then(({ mainModule }) => { + snippetsService = mainModule.provideSnippets() + mainModule.loaded = false + }) + ) + + waitsFor('all snippets to load', 3000, () => + snippetsService.bundledSnippetsLoaded() + ) + } - it("loads the bundled snippet template snippets", () => { - activateSnippetsPackage(); + it('loads the bundled snippet template snippets', () => { + activateSnippetsPackage() runs(() => { - const jsonSnippet = snippetsService.snippetsForScopes(['.source.json'])['snip']; - expect(jsonSnippet.name).toBe('Atom Snippet'); - expect(jsonSnippet.prefix).toBe('snip'); - expect(jsonSnippet.body).toContain('"prefix":'); - expect(jsonSnippet.body).toContain('"body":'); - expect(jsonSnippet.tabStopList.length).toBeGreaterThan(0); - - const csonSnippet = snippetsService.snippetsForScopes(['.source.coffee'])['snip']; - expect(csonSnippet.name).toBe('Atom Snippet'); - expect(csonSnippet.prefix).toBe('snip'); - expect(csonSnippet.body).toContain("'prefix':"); - expect(csonSnippet.body).toContain("'body':"); - expect(csonSnippet.tabStopList.length).toBeGreaterThan(0); - }); - }); - - it("loads non-hidden snippet files from atom packages with snippets directories", () => { - activateSnippetsPackage(); + const jsonSnippet = snippetsService.snippetsForScopes(['.source.json']) + .snip + expect(jsonSnippet.name).toBe('Atom Snippet') + expect(jsonSnippet.prefix).toBe('snip') + expect(jsonSnippet.body).toContain('"prefix":') + expect(jsonSnippet.body).toContain('"body":') + expect(jsonSnippet.tabStopList.length).toBeGreaterThan(0) + + const csonSnippet = snippetsService.snippetsForScopes(['.source.coffee']) + .snip + expect(csonSnippet.name).toBe('Atom Snippet') + expect(csonSnippet.prefix).toBe('snip') + expect(csonSnippet.body).toContain("'prefix':") + expect(csonSnippet.body).toContain("'body':") + expect(csonSnippet.tabStopList.length).toBeGreaterThan(0) + }) + }) + + it('loads non-hidden snippet files from atom packages with snippets directories', () => { + activateSnippetsPackage() runs(() => { - let snippet = snippetsService.snippetsForScopes(['.test'])['test']; - expect(snippet.prefix).toBe('test'); - expect(snippet.body).toBe('testing 123'); - - snippet = snippetsService.snippetsForScopes(['.test'])['testd']; - expect(snippet.prefix).toBe('testd'); - expect(snippet.body).toBe('testing 456'); - expect(snippet.description).toBe('a description'); - expect(snippet.descriptionMoreURL).toBe('http://google.com'); - - snippet = snippetsService.snippetsForScopes(['.test'])['testlabelleft']; - expect(snippet.prefix).toBe('testlabelleft'); - expect(snippet.body).toBe('testing 456'); - expect(snippet.leftLabel).toBe('a label'); - - snippet = snippetsService.snippetsForScopes(['.test'])['testhtmllabels']; - expect(snippet.prefix).toBe('testhtmllabels'); - expect(snippet.body).toBe('testing 456'); - expect(snippet.leftLabelHTML).toBe('Label'); - expect(snippet.rightLabelHTML).toBe('Label'); - }); - }); - - it("logs a warning if package snippets files cannot be parsed", () => { - activateSnippetsPackage(); + let snippet = snippetsService.snippetsForScopes(['.test']).test + expect(snippet.prefix).toBe('test') + expect(snippet.body).toBe('testing 123') + + snippet = snippetsService.snippetsForScopes(['.test']).testd + expect(snippet.prefix).toBe('testd') + expect(snippet.body).toBe('testing 456') + expect(snippet.description).toBe('a description') + expect(snippet.descriptionMoreURL).toBe('http://google.com') + + snippet = snippetsService.snippetsForScopes(['.test']).testlabelleft + expect(snippet.prefix).toBe('testlabelleft') + expect(snippet.body).toBe('testing 456') + expect(snippet.leftLabel).toBe('a label') + + snippet = snippetsService.snippetsForScopes(['.test']).testhtmllabels + expect(snippet.prefix).toBe('testhtmllabels') + expect(snippet.body).toBe('testing 456') + expect(snippet.leftLabelHTML).toBe('Label') + expect(snippet.rightLabelHTML).toBe( + 'Label' + ) + }) + }) + + it('logs a warning if package snippets files cannot be parsed', () => { + activateSnippetsPackage() runs(() => { // Warn about invalid-file, but don't even try to parse a hidden file - expect(console.warn.calls.length).toBeGreaterThan(0); - expect(console.warn.mostRecentCall.args[0]).toMatch(/Error reading.*package-with-broken-snippets/); - }); - }); - - describe("::loadPackageSnippets(callback)", () => { - beforeEach(() => { // simulate a list of packages where the javascript core package is returned at the end - atom.packages.getLoadedPackages.andReturn([ - atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-snippets')), + expect(console.warn.calls.length).toBeGreaterThan(0) + expect(console.warn.mostRecentCall.args[0]).toMatch( + /Error reading.*package-with-broken-snippets/ + ) + }) + }) + + describe('::loadPackageSnippets(callback)', () => { + beforeEach(() => { + // simulate a list of packages where the javascript core package is returned at the end + atom.packages.getLoadedPackages.andReturn([ + atom.packages.loadPackage( + path.join(__dirname, 'fixtures', 'package-with-snippets') + ), atom.packages.loadPackage('language-javascript') ]) - }); + }) it("allows other packages to override core packages' snippets", () => { - waitsForPromise(() => atom.packages.activatePackage("language-javascript")); + waitsForPromise(() => + atom.packages.activatePackage('language-javascript') + ) - activateSnippetsPackage(); + activateSnippetsPackage() runs(() => { - const snippet = snippetsService.snippetsForScopes(['.source.js'])['log']; - expect(snippet.body).toBe("from-a-community-package"); - }); - }); - }); - - describe("::onDidLoadSnippets(callback)", () => { - it("invokes listeners when all snippets are loaded", () => { - let loadedCallback = null; - - waitsFor("package to activate", done => atom.packages.activatePackage("snippets").then(({mainModule}) => { - mainModule.onDidLoadSnippets(loadedCallback = jasmine.createSpy('onDidLoadSnippets callback')); - done(); - })); - - waitsFor("onDidLoad callback to be called", () => loadedCallback.callCount > 0); - }); - }); - - describe("when ~/.atom/snippets.json exists", () => { + const snippet = snippetsService.snippetsForScopes(['.source.js']).log + expect(snippet.body).toBe('from-a-community-package') + }) + }) + }) + + describe('::onDidLoadSnippets(callback)', () => { + it('invokes listeners when all snippets are loaded', () => { + let loadedCallback = null + + waitsFor('package to activate', done => + atom.packages.activatePackage('snippets').then(({ mainModule }) => { + mainModule.onDidLoadSnippets( + (loadedCallback = jasmine.createSpy('onDidLoadSnippets callback')) + ) + done() + }) + ) + + waitsFor( + 'onDidLoad callback to be called', + () => loadedCallback.callCount > 0 + ) + }) + }) + + describe('when ~/.atom/snippets.json exists', () => { beforeEach(() => { - fs.writeFileSync(path.join(configDirPath, 'snippets.json'), `\ + fs.writeFileSync( + path.join(configDirPath, 'snippets.json'), + `\ { ".foo": { "foo snippet": { @@ -136,25 +168,29 @@ describe("Snippet Loading", () => { } }\ ` - ); - activateSnippetsPackage(); - }); + ) + activateSnippetsPackage() + }) - it("loads the snippets from that file", () => { - let snippet = null; + it('loads the snippets from that file', () => { + let snippet = null - waitsFor(() => snippet = snippetsService.snippetsForScopes(['.foo'])['foo']); + waitsFor( + () => (snippet = snippetsService.snippetsForScopes(['.foo']).foo) + ) runs(() => { - expect(snippet.name).toBe('foo snippet'); - expect(snippet.prefix).toBe("foo"); - expect(snippet.body).toBe("bar1"); - }); - }); - - describe("when that file changes", () => { - it("reloads the snippets", () => { - fs.writeFileSync(path.join(configDirPath, 'snippets.json'), `\ + expect(snippet.name).toBe('foo snippet') + expect(snippet.prefix).toBe('foo') + expect(snippet.body).toBe('bar1') + }) + }) + + describe('when that file changes', () => { + it('reloads the snippets', () => { + fs.writeFileSync( + path.join(configDirPath, 'snippets.json'), + `\ { ".foo": { "foo snippet": { @@ -164,146 +200,181 @@ describe("Snippet Loading", () => { } }\ ` - ); + ) - waitsFor("snippets to be changed", () => { - const snippet = snippetsService.snippetsForScopes(['.foo'])['foo']; - return snippet && snippet.body === 'bar2'; - }); + waitsFor('snippets to be changed', () => { + const snippet = snippetsService.snippetsForScopes(['.foo']).foo + return snippet && snippet.body === 'bar2' + }) runs(() => { - fs.writeFileSync(path.join(configDirPath, 'snippets.json'), ""); - }); - - waitsFor("snippets to be removed", () => !snippetsService.snippetsForScopes(['.foo'])['foo']); - }); - }); - }); - - describe("when ~/.atom/snippets.cson exists", () => { + fs.writeFileSync(path.join(configDirPath, 'snippets.json'), '') + }) + + waitsFor( + 'snippets to be removed', + () => !snippetsService.snippetsForScopes(['.foo']).foo + ) + }) + }) + }) + + describe('when ~/.atom/snippets.cson exists', () => { beforeEach(() => { - fs.writeFileSync(path.join(configDirPath, 'snippets.cson'), `\ + fs.writeFileSync( + path.join(configDirPath, 'snippets.cson'), + `\ ".foo": "foo snippet": "prefix": "foo" "body": "bar1"\ ` - ); - activateSnippetsPackage(); - }); + ) + activateSnippetsPackage() + }) - it("loads the snippets from that file", () => { - let snippet = null; + it('loads the snippets from that file', () => { + let snippet = null - waitsFor(() => snippet = snippetsService.snippetsForScopes(['.foo'])['foo']); + waitsFor( + () => (snippet = snippetsService.snippetsForScopes(['.foo']).foo) + ) runs(() => { - expect(snippet.name).toBe('foo snippet'); - expect(snippet.prefix).toBe("foo"); - expect(snippet.body).toBe("bar1"); - }); - }); - - describe("when that file changes", () => { - it("reloads the snippets", () => { - fs.writeFileSync(path.join(configDirPath, 'snippets.cson'), `\ + expect(snippet.name).toBe('foo snippet') + expect(snippet.prefix).toBe('foo') + expect(snippet.body).toBe('bar1') + }) + }) + + describe('when that file changes', () => { + it('reloads the snippets', () => { + fs.writeFileSync( + path.join(configDirPath, 'snippets.cson'), + `\ ".foo": "foo snippet": "prefix": "foo" "body": "bar2"\ ` - ); + ) - waitsFor("snippets to be changed", () => { - const snippet = snippetsService.snippetsForScopes(['.foo'])['foo']; - return snippet && snippet.body === 'bar2'; - }); + waitsFor('snippets to be changed', () => { + const snippet = snippetsService.snippetsForScopes(['.foo']).foo + return snippet && snippet.body === 'bar2' + }) runs(() => { - fs.writeFileSync(path.join(configDirPath, 'snippets.cson'), ""); - }); + fs.writeFileSync(path.join(configDirPath, 'snippets.cson'), '') + }) - waitsFor("snippets to be removed", () => { - const snippet = snippetsService.snippetsForScopes(['.foo'])['foo']; - return snippet == null; - }); - }); - }); - }); + waitsFor('snippets to be removed', () => { + const snippet = snippetsService.snippetsForScopes(['.foo']).foo + return snippet == null + }) + }) + }) + }) - it("notifies the user when the user snippets file cannot be loaded", () => { - fs.writeFileSync(path.join(configDirPath, 'snippets.cson'), '".junk":::'); + it('notifies the user when the user snippets file cannot be loaded', () => { + fs.writeFileSync(path.join(configDirPath, 'snippets.cson'), '".junk":::') - activateSnippetsPackage(); + activateSnippetsPackage() runs(() => { - expect(console.warn).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled() if (atom.notifications != null) { - expect(atom.notifications.addError).toHaveBeenCalled(); + expect(atom.notifications.addError).toHaveBeenCalled() } - }); - }); + }) + }) - describe("packages-with-snippets-disabled feature", () => { - it("disables no snippets if the config option is empty", () => { - const originalConfig = atom.config.get('core.packagesWithSnippetsDisabled'); - atom.config.set('core.packagesWithSnippetsDisabled', []); + describe('packages-with-snippets-disabled feature', () => { + it('disables no snippets if the config option is empty', () => { + const originalConfig = atom.config.get( + 'core.packagesWithSnippetsDisabled' + ) + atom.config.set('core.packagesWithSnippetsDisabled', []) - activateSnippetsPackage(); + activateSnippetsPackage() runs(() => { - const snippets = snippetsService.snippetsForScopes(['.package-with-snippets-unique-scope']); - expect(Object.keys(snippets).length).toBe(1); - atom.config.set('core.packagesWithSnippetsDisabled', originalConfig); - }); - }); + const snippets = snippetsService.snippetsForScopes([ + '.package-with-snippets-unique-scope' + ]) + expect(Object.keys(snippets).length).toBe(1) + atom.config.set('core.packagesWithSnippetsDisabled', originalConfig) + }) + }) it("still includes a disabled package's snippets in the list of unparsed snippets", () => { - let originalConfig = atom.config.get('core.packagesWithSnippetsDisabled'); - atom.config.set('core.packagesWithSnippetsDisabled', []); + const originalConfig = atom.config.get( + 'core.packagesWithSnippetsDisabled' + ) + atom.config.set('core.packagesWithSnippetsDisabled', []) - activateSnippetsPackage(); + activateSnippetsPackage() runs(() => { - atom.config.set('core.packagesWithSnippetsDisabled', ['package-with-snippets']); - const allSnippets = snippetsService.getUnparsedSnippets(); - const scopedSnippet = allSnippets.find(s => s.selectorString === '.package-with-snippets-unique-scope'); - expect(scopedSnippet).not.toBe(undefined); - atom.config.set('core.packagesWithSnippetsDisabled', originalConfig); - }); - }); + atom.config.set('core.packagesWithSnippetsDisabled', [ + 'package-with-snippets' + ]) + const allSnippets = snippetsService.getUnparsedSnippets() + const scopedSnippet = allSnippets.find( + s => s.selectorString === '.package-with-snippets-unique-scope' + ) + expect(scopedSnippet).not.toBe(undefined) + atom.config.set('core.packagesWithSnippetsDisabled', originalConfig) + }) + }) it("never loads a package's snippets when that package is disabled in config", () => { - const originalConfig = atom.config.get('core.packagesWithSnippetsDisabled'); - atom.config.set('core.packagesWithSnippetsDisabled', ['package-with-snippets']); + const originalConfig = atom.config.get( + 'core.packagesWithSnippetsDisabled' + ) + atom.config.set('core.packagesWithSnippetsDisabled', [ + 'package-with-snippets' + ]) - activateSnippetsPackage(); + activateSnippetsPackage() runs(() => { - const snippets = snippetsService.snippetsForScopes(['.package-with-snippets-unique-scope']); - expect(Object.keys(snippets).length).toBe(0); - atom.config.set('core.packagesWithSnippetsDisabled', originalConfig); - }); - }); - - it("unloads and/or reloads snippets from a package if the config option is changed after activation", () => { - const originalConfig = atom.config.get('core.packagesWithSnippetsDisabled'); - atom.config.set('core.packagesWithSnippetsDisabled', []); - - activateSnippetsPackage(); + const snippets = snippetsService.snippetsForScopes([ + '.package-with-snippets-unique-scope' + ]) + expect(Object.keys(snippets).length).toBe(0) + atom.config.set('core.packagesWithSnippetsDisabled', originalConfig) + }) + }) + + it('unloads and/or reloads snippets from a package if the config option is changed after activation', () => { + const originalConfig = atom.config.get( + 'core.packagesWithSnippetsDisabled' + ) + atom.config.set('core.packagesWithSnippetsDisabled', []) + + activateSnippetsPackage() runs(() => { - let snippets = snippetsService.snippetsForScopes(['.package-with-snippets-unique-scope']); - expect(Object.keys(snippets).length).toBe(1); + let snippets = snippetsService.snippetsForScopes([ + '.package-with-snippets-unique-scope' + ]) + expect(Object.keys(snippets).length).toBe(1) // Disable it. - atom.config.set('core.packagesWithSnippetsDisabled', ['package-with-snippets']); - snippets = snippetsService.snippetsForScopes(['.package-with-snippets-unique-scope']); - expect(Object.keys(snippets).length).toBe(0); + atom.config.set('core.packagesWithSnippetsDisabled', [ + 'package-with-snippets' + ]) + snippets = snippetsService.snippetsForScopes([ + '.package-with-snippets-unique-scope' + ]) + expect(Object.keys(snippets).length).toBe(0) // Re-enable it. - atom.config.set('core.packagesWithSnippetsDisabled', []); - snippets = snippetsService.snippetsForScopes(['.package-with-snippets-unique-scope']); - expect(Object.keys(snippets).length).toBe(1); - - atom.config.set('core.packagesWithSnippetsDisabled', originalConfig); - }); - }); - }); -}); + atom.config.set('core.packagesWithSnippetsDisabled', []) + snippets = snippetsService.snippetsForScopes([ + '.package-with-snippets-unique-scope' + ]) + expect(Object.keys(snippets).length).toBe(1) + + atom.config.set('core.packagesWithSnippetsDisabled', originalConfig) + }) + }) + }) +}) diff --git a/spec/snippets-spec.js b/spec/snippets-spec.js index 6899447..07267ba 100644 --- a/spec/snippets-spec.js +++ b/spec/snippets-spec.js @@ -1,152 +1,166 @@ -const path = require('path'); -const temp = require('temp').track(); -const Snippets = require('../lib/snippets'); -const {TextEditor} = require('atom'); +const path = require('path') +const temp = require('temp').track() +const Snippets = require('../lib/snippets') +const { TextEditor } = require('atom') -describe("Snippets extension", () => { - let editorElement, editor; +describe('Snippets extension', () => { + let editorElement, editor - const simulateTabKeyEvent = (param) => { + const simulateTabKeyEvent = param => { if (param == null) { - param = {}; + param = {} } - const {shift} = param; - const event = atom.keymaps.constructor.buildKeydownEvent('tab', {shift, target: editorElement}); - atom.keymaps.handleKeyboardEvent(event); - }; + const { shift } = param + const event = atom.keymaps.constructor.buildKeydownEvent('tab', { + shift, + target: editorElement + }) + atom.keymaps.handleKeyboardEvent(event) + } beforeEach(() => { - spyOn(Snippets, 'loadAll'); - spyOn(Snippets, 'getUserSnippetsPath').andReturn(''); + spyOn(Snippets, 'loadAll') + spyOn(Snippets, 'getUserSnippetsPath').andReturn('') - waitsForPromise(() => atom.workspace.open('sample.js')); - waitsForPromise(() => atom.packages.activatePackage('language-javascript')); - waitsForPromise(() => atom.packages.activatePackage('snippets')); + waitsForPromise(() => atom.workspace.open('sample.js')) + waitsForPromise(() => atom.packages.activatePackage('language-javascript')) + waitsForPromise(() => atom.packages.activatePackage('snippets')) runs(() => { - editor = atom.workspace.getActiveTextEditor(); - editorElement = atom.views.getView(editor); - }); - }); + editor = atom.workspace.getActiveTextEditor() + editorElement = atom.views.getView(editor) + }) + }) afterEach(() => { - waitsForPromise(() => atom.packages.deactivatePackage('snippets')); - }); + waitsForPromise(() => atom.packages.deactivatePackage('snippets')) + }) - describe("provideSnippets interface", () => { - let snippetsInterface = null; + describe('provideSnippets interface', () => { + let snippetsInterface = null beforeEach(() => { - snippetsInterface = Snippets.provideSnippets(); - }); + snippetsInterface = Snippets.provideSnippets() + }) - describe("bundledSnippetsLoaded", () => { - it("indicates the loaded state of the bundled snippets", () => { - expect(snippetsInterface.bundledSnippetsLoaded()).toBe(false); - Snippets.doneLoading(); - expect(snippetsInterface.bundledSnippetsLoaded()).toBe(true); - }); + describe('bundledSnippetsLoaded', () => { + it('indicates the loaded state of the bundled snippets', () => { + expect(snippetsInterface.bundledSnippetsLoaded()).toBe(false) + Snippets.doneLoading() + expect(snippetsInterface.bundledSnippetsLoaded()).toBe(true) + }) - it("resets the loaded state after snippets is deactivated", () => { - expect(snippetsInterface.bundledSnippetsLoaded()).toBe(false); - Snippets.doneLoading(); - expect(snippetsInterface.bundledSnippetsLoaded()).toBe(true); + it('resets the loaded state after snippets is deactivated', () => { + expect(snippetsInterface.bundledSnippetsLoaded()).toBe(false) + Snippets.doneLoading() + expect(snippetsInterface.bundledSnippetsLoaded()).toBe(true) - waitsForPromise(() => atom.packages.deactivatePackage('snippets')); - waitsForPromise(() => atom.packages.activatePackage('snippets')); + waitsForPromise(() => atom.packages.deactivatePackage('snippets')) + waitsForPromise(() => atom.packages.activatePackage('snippets')) runs(() => { - expect(snippetsInterface.bundledSnippetsLoaded()).toBe(false); - Snippets.doneLoading(); - expect(snippetsInterface.bundledSnippetsLoaded()).toBe(true); - }); - }); - }); - - describe("insertSnippet", () => { - it("can insert a snippet", () => { - editor.setSelectedBufferRange([[0, 4], [0, 13]]); - snippetsInterface.insertSnippet("hello ${1:world}", editor); - expect(editor.lineTextForBufferRow(0)).toBe("var hello world = function () {"); - }); - }); - }); - - it("returns false for snippetToExpandUnderCursor if getSnippets returns {}", () => { - const snippets = atom.packages.getActivePackage('snippets').mainModule; - expect(snippets.snippetToExpandUnderCursor(editor)).toEqual(false); - }); - - it("ignores invalid snippets in the config", () => { - const snippets = atom.packages.getActivePackage('snippets').mainModule; - - let invalidSnippets = null; - spyOn(snippets.scopedPropertyStore, 'getPropertyValue').andCallFake(() => invalidSnippets); - expect(snippets.getSnippets(editor)).toEqual({}); - - invalidSnippets = 'test'; - expect(snippets.getSnippets(editor)).toEqual({}); - - invalidSnippets = []; - expect(snippets.getSnippets(editor)).toEqual({}); - - invalidSnippets = 3; - expect(snippets.getSnippets(editor)).toEqual({}); - - invalidSnippets = {a: null}; - expect(snippets.getSnippets(editor)).toEqual({}); - }); - - describe("when null snippets are present", () => { - beforeEach(() => Snippets.add(__filename, { - ".source.js": { - "some snippet": { - prefix: "t1", - body: "this is a test" - } - }, + expect(snippetsInterface.bundledSnippetsLoaded()).toBe(false) + Snippets.doneLoading() + expect(snippetsInterface.bundledSnippetsLoaded()).toBe(true) + }) + }) + }) + + describe('insertSnippet', () => { + it('can insert a snippet', () => { + editor.setSelectedBufferRange([ + [0, 4], + [0, 13] + ]) + snippetsInterface.insertSnippet('hello ${1:world}', editor) + expect(editor.lineTextForBufferRow(0)).toBe( + 'var hello world = function () {' + ) + }) + }) + }) + + it('returns false for snippetToExpandUnderCursor if getSnippets returns {}', () => { + const snippets = atom.packages.getActivePackage('snippets').mainModule + expect(snippets.snippetToExpandUnderCursor(editor)).toEqual(false) + }) + + it('ignores invalid snippets in the config', () => { + const snippets = atom.packages.getActivePackage('snippets').mainModule + + let invalidSnippets = null + spyOn(snippets.scopedPropertyStore, 'getPropertyValue').andCallFake( + () => invalidSnippets + ) + expect(snippets.getSnippets(editor)).toEqual({}) + + invalidSnippets = 'test' + expect(snippets.getSnippets(editor)).toEqual({}) + + invalidSnippets = [] + expect(snippets.getSnippets(editor)).toEqual({}) + + invalidSnippets = 3 + expect(snippets.getSnippets(editor)).toEqual({}) + + invalidSnippets = { a: null } + expect(snippets.getSnippets(editor)).toEqual({}) + }) + + describe('when null snippets are present', () => { + beforeEach(() => + Snippets.add(__filename, { + '.source.js': { + 'some snippet': { + prefix: 't1', + body: 'this is a test' + } + }, - ".source.js .nope": { - "some snippet": { - prefix: "t1", - body: null + '.source.js .nope': { + 'some snippet': { + prefix: 't1', + body: null + } } - } - })); - - it("overrides the less-specific defined snippet", () => { - const snippets = Snippets.provideSnippets(); - expect(snippets.snippetsForScopes(['.source.js'])['t1']).toBeTruthy(); - expect(snippets.snippetsForScopes(['.source.js .nope.not-today'])['t1']).toBeFalsy(); - }); - }); + }) + ) + + it('overrides the less-specific defined snippet', () => { + const snippets = Snippets.provideSnippets() + expect(snippets.snippetsForScopes(['.source.js']).t1).toBeTruthy() + expect( + snippets.snippetsForScopes(['.source.js .nope.not-today']).t1 + ).toBeFalsy() + }) + }) describe("when 'tab' is triggered on the editor", () => { beforeEach(() => { Snippets.add(__filename, { - ".source.js": { - "without tab stops": { - prefix: "t1", - body: "this is a test" + '.source.js': { + 'without tab stops': { + prefix: 't1', + body: 'this is a test' }, - "with only an end tab stop": { - prefix: "t1a", - body: "something $0 strange" + 'with only an end tab stop': { + prefix: 't1a', + body: 'something $0 strange' }, - "overlapping prefix": { - prefix: "tt1", - body: "this is another test" + 'overlapping prefix': { + prefix: 'tt1', + body: 'this is another test' }, - "special chars": { - prefix: "@unique", - body: "@unique see" + 'special chars': { + prefix: '@unique', + body: '@unique see' }, - "tab stops": { - prefix: "t2", + 'tab stops': { + prefix: 't2', body: `\ go here next:($2) and finally go here:($0) go here first:($1) @@ -154,8 +168,8 @@ go here first:($1) ` }, - "indented second line": { - prefix: "t3", + 'indented second line': { + prefix: 't3', body: `\ line 1 \tline 2$1 @@ -163,16 +177,16 @@ $2\ ` }, - "multiline with indented placeholder tabstop": { - prefix: "t4", + 'multiline with indented placeholder tabstop': { + prefix: 't4', body: `\ line \${1:1} \${2:body...}\ ` }, - "multiline starting with tabstop": { - prefix: "t4b", + 'multiline starting with tabstop': { + prefix: 't4b', body: `\ $1 = line 1 { line 2 @@ -180,31 +194,31 @@ $1 = line 1 { ` }, - "nested tab stops": { - prefix: "t5", + 'nested tab stops': { + prefix: 't5', body: '${1:"${2:key}"}: ${3:value}' }, - "caused problems with undo": { - prefix: "t6", + 'caused problems with undo': { + prefix: 't6', body: `\ first line$1 \${2:placeholder ending second line}\ ` }, - "tab stops at beginning and then end of snippet": { - prefix: "t6b", - body: "$1expanded$0" + 'tab stops at beginning and then end of snippet': { + prefix: 't6b', + body: '$1expanded$0' }, - "tab stops at end and then beginning of snippet": { - prefix: "t6c", - body: "$0expanded$1" + 'tab stops at end and then beginning of snippet': { + prefix: 't6c', + body: '$0expanded$1' }, - "contains empty lines": { - prefix: "t7", + 'contains empty lines': { + prefix: 't7', body: `\ first line $1 @@ -212,24 +226,24 @@ first line $1 fourth line after blanks $2\ ` }, - "with/without placeholder": { - prefix: "t8", + 'with/without placeholder': { + prefix: 't8', body: `\ with placeholder \${1:test} without placeholder \${2}\ ` }, - "multi-caret": { - prefix: "t9", + 'multi-caret': { + prefix: 't9', body: `\ with placeholder \${1:test} without placeholder $1\ ` }, - "multi-caret-multi-tabstop": { - prefix: "t9b", + 'multi-caret-multi-tabstop': { + prefix: 't9b', body: `\ with placeholder \${1:test} without placeholder $1 @@ -238,974 +252,1167 @@ third tabstop $3\ ` }, - "large indices": { - prefix: "t10", - body: "hello${10} ${11:large} indices${1}" + 'large indices': { + prefix: 't10', + body: 'hello${10} ${11:large} indices${1}' }, - "no body": { - prefix: "bad1" + 'no body': { + prefix: 'bad1' }, - "number body": { - prefix: "bad2", + 'number body': { + prefix: 'bad2', body: 100 }, - "many tabstops": { - prefix: "t11", - body: "$0one${1} ${2:two} three${3}" + 'many tabstops': { + prefix: 't11', + body: '$0one${1} ${2:two} three${3}' }, - "simple transform": { - prefix: "t12", - body: "[${1:b}][/${1/[ ]+.*$//}]" + 'simple transform': { + prefix: 't12', + body: '[${1:b}][/${1/[ ]+.*$//}]' }, - "transform with non-transforming mirrors": { - prefix: "t13", - body: "${1:placeholder}\n${1/(.)/\\u$1/}\n$1" + 'transform with non-transforming mirrors': { + prefix: 't13', + body: '${1:placeholder}\n${1/(.)/\\u$1/}\n$1' }, - "multiple tab stops, some with transforms and some without": { - prefix: "t14", - body: "${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2" + 'multiple tab stops, some with transforms and some without': { + prefix: 't14', + body: + '${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2' }, - "has a transformed tab stop without a corresponding ordinary tab stop": { + 'has a transformed tab stop without a corresponding ordinary tab stop': { prefix: 't15', - body: "${1/(.)/\\u$1/} & $2" + body: '${1/(.)/\\u$1/} & $2' }, - "has a transformed tab stop that occurs before the corresponding ordinary tab stop": { + 'has a transformed tab stop that occurs before the corresponding ordinary tab stop': { prefix: 't16', - body: "& ${1/(.)/\\u$1/} & ${1:q}" + body: '& ${1/(.)/\\u$1/} & ${1:q}' }, "has a placeholder that mirrors another tab stop's content": { prefix: 't17', body: "$4console.${3:log}('${2:uh $1}', $1);$0" }, - "has a transformed tab stop such that it is possible to move the cursor between the ordinary tab stop and its transformed version without an intermediate step": { + 'has a transformed tab stop such that it is possible to move the cursor between the ordinary tab stop and its transformed version without an intermediate step': { prefix: 't18', body: '// $1\n// ${1/./=/}' } } - }); - }); + }) + }) - it("parses snippets once, reusing cached ones on subsequent queries", () => { - spyOn(Snippets, "getBodyParser").andCallThrough(); + it('parses snippets once, reusing cached ones on subsequent queries', () => { + spyOn(Snippets, 'getBodyParser').andCallThrough() - editor.insertText("t1"); - simulateTabKeyEvent(); + editor.insertText('t1') + simulateTabKeyEvent() - expect(Snippets.getBodyParser).toHaveBeenCalled(); - expect(editor.lineTextForBufferRow(0)).toBe("this is a testvar quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 14]); + expect(Snippets.getBodyParser).toHaveBeenCalled() + expect(editor.lineTextForBufferRow(0)).toBe( + 'this is a testvar quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 14]) - Snippets.getBodyParser.reset(); + Snippets.getBodyParser.reset() - editor.setText(""); - editor.insertText("t1"); - simulateTabKeyEvent(); + editor.setText('') + editor.insertText('t1') + simulateTabKeyEvent() - expect(Snippets.getBodyParser).not.toHaveBeenCalled(); - expect(editor.lineTextForBufferRow(0)).toBe("this is a test"); - expect(editor.getCursorScreenPosition()).toEqual([0, 14]); + expect(Snippets.getBodyParser).not.toHaveBeenCalled() + expect(editor.lineTextForBufferRow(0)).toBe('this is a test') + expect(editor.getCursorScreenPosition()).toEqual([0, 14]) - Snippets.getBodyParser.reset(); + Snippets.getBodyParser.reset() Snippets.add(__filename, { - ".source.js": { - "invalidate previous snippet": { - prefix: "t1", - body: "new snippet" + '.source.js': { + 'invalidate previous snippet': { + prefix: 't1', + body: 'new snippet' } } - }); - - editor.setText(""); - editor.insertText("t1"); - simulateTabKeyEvent(); - - expect(Snippets.getBodyParser).toHaveBeenCalled(); - expect(editor.lineTextForBufferRow(0)).toBe("new snippet"); - expect(editor.getCursorScreenPosition()).toEqual([0, 11]); - }); - - describe("when the snippet body is invalid or missing", () => { - it("does not register the snippet", () => { - editor.setText(''); - editor.insertText('bad1'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - expect(editor.getText()).toBe('bad1'); - - editor.setText(''); - editor.setText('bad2'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - expect(editor.getText()).toBe('bad2'); - }); - }); - - describe("when the letters preceding the cursor trigger a snippet", () => { - describe("when the snippet contains no tab stops", () => { - it("replaces the prefix with the snippet text and places the cursor at its end", () => { - editor.insertText("t1"); - expect(editor.getCursorScreenPosition()).toEqual([0, 2]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("this is a testvar quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 14]); - }); - - it("inserts a real tab the next time a tab is pressed after the snippet is expanded", () => { - editor.insertText("t1"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("this is a testvar quicksort = function () {"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("this is a test var quicksort = function () {"); - }); - }); - - describe("when the snippet contains tab stops", () => { + }) + + editor.setText('') + editor.insertText('t1') + simulateTabKeyEvent() + + expect(Snippets.getBodyParser).toHaveBeenCalled() + expect(editor.lineTextForBufferRow(0)).toBe('new snippet') + expect(editor.getCursorScreenPosition()).toEqual([0, 11]) + }) + + describe('when the snippet body is invalid or missing', () => { + it('does not register the snippet', () => { + editor.setText('') + editor.insertText('bad1') + atom.commands.dispatch(editorElement, 'snippets:expand') + expect(editor.getText()).toBe('bad1') + + editor.setText('') + editor.setText('bad2') + atom.commands.dispatch(editorElement, 'snippets:expand') + expect(editor.getText()).toBe('bad2') + }) + }) + + describe('when the letters preceding the cursor trigger a snippet', () => { + describe('when the snippet contains no tab stops', () => { + it('replaces the prefix with the snippet text and places the cursor at its end', () => { + editor.insertText('t1') + expect(editor.getCursorScreenPosition()).toEqual([0, 2]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 'this is a testvar quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 14]) + }) + + it('inserts a real tab the next time a tab is pressed after the snippet is expanded', () => { + editor.insertText('t1') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 'this is a testvar quicksort = function () {' + ) + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 'this is a test var quicksort = function () {' + ) + }) + }) + + describe('when the snippet contains tab stops', () => { it("places the cursor at the first tab-stop, and moves the cursor in response to 'next-tab-stop' events", () => { - const markerCountBefore = editor.getMarkerCount(); - editor.setCursorScreenPosition([2, 0]); - editor.insertText('t2'); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(2)).toBe("go here next:() and finally go here:()"); - expect(editor.lineTextForBufferRow(3)).toBe("go here first:()"); - expect(editor.lineTextForBufferRow(4)).toBe(" if (items.length <= 1) return items;"); - expect(editor.getSelectedBufferRange()).toEqual([[3, 15], [3, 15]]); - - simulateTabKeyEvent(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 14], [2, 14]]); - editor.insertText('abc'); - - simulateTabKeyEvent(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 40], [2, 40]]); + const markerCountBefore = editor.getMarkerCount() + editor.setCursorScreenPosition([2, 0]) + editor.insertText('t2') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(2)).toBe( + 'go here next:() and finally go here:()' + ) + expect(editor.lineTextForBufferRow(3)).toBe('go here first:()') + expect(editor.lineTextForBufferRow(4)).toBe( + ' if (items.length <= 1) return items;' + ) + expect(editor.getSelectedBufferRange()).toEqual([ + [3, 15], + [3, 15] + ]) + + simulateTabKeyEvent() + expect(editor.getSelectedBufferRange()).toEqual([ + [2, 14], + [2, 14] + ]) + editor.insertText('abc') + + simulateTabKeyEvent() + expect(editor.getSelectedBufferRange()).toEqual([ + [2, 40], + [2, 40] + ]) // tab backwards - simulateTabKeyEvent({shift: true}); - expect(editor.getSelectedBufferRange()).toEqual([[2, 14], [2, 17]]); // should highlight text typed at tab stop - - simulateTabKeyEvent({shift: true}); - expect(editor.getSelectedBufferRange()).toEqual([[3, 15], [3, 15]]); + simulateTabKeyEvent({ shift: true }) + expect(editor.getSelectedBufferRange()).toEqual([ + [2, 14], + [2, 17] + ]) // should highlight text typed at tab stop + + simulateTabKeyEvent({ shift: true }) + expect(editor.getSelectedBufferRange()).toEqual([ + [3, 15], + [3, 15] + ]) // shift-tab on first tab-stop does nothing - simulateTabKeyEvent({shift: true}); - expect(editor.getCursorScreenPosition()).toEqual([3, 15]); + simulateTabKeyEvent({ shift: true }) + expect(editor.getCursorScreenPosition()).toEqual([3, 15]) // tab through all tab stops, then tab on last stop to terminate snippet - simulateTabKeyEvent(); - simulateTabKeyEvent(); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(2)).toBe("go here next:(abc) and finally go here:( )"); - expect(editor.getMarkerCount()).toBe(markerCountBefore); - }); - - describe("when tab stops are nested", () => { - it("destroys the inner tab stop if the outer tab stop is modified", () => { - editor.setText(''); - editor.insertText('t5'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - expect(editor.lineTextForBufferRow(0)).toBe('"key": value'); - expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 5]]); - editor.insertText("foo"); - simulateTabKeyEvent(); - expect(editor.getSelectedBufferRange()).toEqual([[0, 5], [0, 10]]); - }); - }); - - describe("when the only tab stop is an end stop", () => { - it("terminates the snippet immediately after moving the cursor to the end stop", () => { - editor.setText(''); - editor.insertText('t1a'); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(0)).toBe("something strange"); - expect(editor.getCursorBufferPosition()).toEqual([0, 10]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("something strange"); - expect(editor.getCursorBufferPosition()).toEqual([0, 12]); - }); - }); - - describe("when tab stops are separated by blank lines", () => { - it("correctly places the tab stops (regression)", () => { - editor.setText(''); - editor.insertText('t7'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - atom.commands.dispatch(editorElement, 'snippets:next-tab-stop'); - expect(editor.getCursorBufferPosition()).toEqual([3, 25]); - }); - }); - - describe("when the cursor is moved beyond the bounds of the current tab stop", () => { - it("terminates the snippet", () => { - editor.setCursorScreenPosition([2, 0]); - editor.insertText('t2'); - simulateTabKeyEvent(); - - editor.moveUp(); - editor.moveLeft(); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(2)).toBe("go here next:( ) and finally go here:()"); - expect(editor.getCursorBufferPosition()).toEqual([2, 16]); + simulateTabKeyEvent() + simulateTabKeyEvent() + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(2)).toBe( + 'go here next:(abc) and finally go here:( )' + ) + expect(editor.getMarkerCount()).toBe(markerCountBefore) + }) + + describe('when tab stops are nested', () => { + it('destroys the inner tab stop if the outer tab stop is modified', () => { + editor.setText('') + editor.insertText('t5') + atom.commands.dispatch(editorElement, 'snippets:expand') + expect(editor.lineTextForBufferRow(0)).toBe('"key": value') + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 0], + [0, 5] + ]) + editor.insertText('foo') + simulateTabKeyEvent() + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 5], + [0, 10] + ]) + }) + }) + + describe('when the only tab stop is an end stop', () => { + it('terminates the snippet immediately after moving the cursor to the end stop', () => { + editor.setText('') + editor.insertText('t1a') + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(0)).toBe('something strange') + expect(editor.getCursorBufferPosition()).toEqual([0, 10]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('something strange') + expect(editor.getCursorBufferPosition()).toEqual([0, 12]) + }) + }) + + describe('when tab stops are separated by blank lines', () => { + it('correctly places the tab stops (regression)', () => { + editor.setText('') + editor.insertText('t7') + atom.commands.dispatch(editorElement, 'snippets:expand') + atom.commands.dispatch(editorElement, 'snippets:next-tab-stop') + expect(editor.getCursorBufferPosition()).toEqual([3, 25]) + }) + }) + + describe('when the cursor is moved beyond the bounds of the current tab stop', () => { + it('terminates the snippet', () => { + editor.setCursorScreenPosition([2, 0]) + editor.insertText('t2') + simulateTabKeyEvent() + + editor.moveUp() + editor.moveLeft() + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(2)).toBe( + 'go here next:( ) and finally go here:()' + ) + expect(editor.getCursorBufferPosition()).toEqual([2, 16]) // test we can terminate with shift-tab - editor.setCursorScreenPosition([4, 0]); - editor.insertText('t2'); - simulateTabKeyEvent(); - simulateTabKeyEvent(); - - editor.moveRight(); - simulateTabKeyEvent({shift: true}); - expect(editor.getCursorBufferPosition()).toEqual([4, 15]); - }); - }); - - describe("when the cursor is moved within the bounds of the current tab stop", () => { - it("should not terminate the snippet", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t8'); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder test"); - editor.moveRight(); - editor.moveLeft(); - editor.insertText("foo"); - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder tesfoot"); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder var quicksort = function () {"); - editor.insertText("test"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder testvar quicksort = function () {"); - editor.moveLeft(); - editor.insertText("foo"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder tesfootvar quicksort = function () {"); - }); - }); - - describe("when the backspace is press within the bounds of the current tab stop", () => { - it("should not terminate the snippet", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t8'); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder test"); - editor.moveRight(); - editor.backspace(); - editor.insertText("foo"); - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder tesfoo"); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder var quicksort = function () {"); - editor.insertText("test"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder testvar quicksort = function () {"); - editor.backspace(); - editor.insertText("foo"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder tesfoovar quicksort = function () {"); - }); - }); - }); - - describe("when the snippet contains hard tabs", () => { - describe("when the edit session is in soft-tabs mode", () => { - it("translates hard tabs in the snippet to the appropriate number of spaces", () => { - expect(editor.getSoftTabs()).toBeTruthy(); - editor.insertText("t3"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(1)).toBe(" line 2"); - expect(editor.getCursorBufferPosition()).toEqual([1, 8]); - }); - }); - - describe("when the edit session is in hard-tabs mode", () => { - it("inserts hard tabs in the snippet directly", () => { - editor.setSoftTabs(false); - editor.insertText("t3"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(1)).toBe("\tline 2"); - expect(editor.getCursorBufferPosition()).toEqual([1, 7]); - }); - }); - }); - - describe("when the snippet prefix is indented", () => { - describe("when the snippet spans a single line", () => { - it("does not indent the next line", () => { - editor.setCursorScreenPosition([2, Infinity]); - editor.insertText(' t1'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - expect(editor.lineTextForBufferRow(3)).toBe(" var pivot = items.shift(), current, left = [], right = [];"); - }); - }); - - describe("when the snippet spans multiple lines", () => { - it("indents the subsequent lines of the snippet to be even with the start of the first line", () => { - expect(editor.getSoftTabs()).toBeTruthy(); - editor.setCursorScreenPosition([2, Infinity]); - editor.insertText(' t3'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - expect(editor.lineTextForBufferRow(2)).toBe(" if (items.length <= 1) return items; line 1"); - expect(editor.lineTextForBufferRow(3)).toBe(" line 2"); - expect(editor.getCursorBufferPosition()).toEqual([3, 12]); - }); - }); - }); - - describe("when the snippet spans multiple lines", () => { + editor.setCursorScreenPosition([4, 0]) + editor.insertText('t2') + simulateTabKeyEvent() + simulateTabKeyEvent() + + editor.moveRight() + simulateTabKeyEvent({ shift: true }) + expect(editor.getCursorBufferPosition()).toEqual([4, 15]) + }) + }) + + describe('when the cursor is moved within the bounds of the current tab stop', () => { + it('should not terminate the snippet', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t8') + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder test') + editor.moveRight() + editor.moveLeft() + editor.insertText('foo') + expect(editor.lineTextForBufferRow(0)).toBe( + 'with placeholder tesfoot' + ) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder var quicksort = function () {' + ) + editor.insertText('test') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder testvar quicksort = function () {' + ) + editor.moveLeft() + editor.insertText('foo') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder tesfootvar quicksort = function () {' + ) + }) + }) + + describe('when the backspace is press within the bounds of the current tab stop', () => { + it('should not terminate the snippet', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t8') + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder test') + editor.moveRight() + editor.backspace() + editor.insertText('foo') + expect(editor.lineTextForBufferRow(0)).toBe( + 'with placeholder tesfoo' + ) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder var quicksort = function () {' + ) + editor.insertText('test') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder testvar quicksort = function () {' + ) + editor.backspace() + editor.insertText('foo') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder tesfoovar quicksort = function () {' + ) + }) + }) + }) + + describe('when the snippet contains hard tabs', () => { + describe('when the edit session is in soft-tabs mode', () => { + it('translates hard tabs in the snippet to the appropriate number of spaces', () => { + expect(editor.getSoftTabs()).toBeTruthy() + editor.insertText('t3') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(1)).toBe(' line 2') + expect(editor.getCursorBufferPosition()).toEqual([1, 8]) + }) + }) + + describe('when the edit session is in hard-tabs mode', () => { + it('inserts hard tabs in the snippet directly', () => { + editor.setSoftTabs(false) + editor.insertText('t3') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(1)).toBe('\tline 2') + expect(editor.getCursorBufferPosition()).toEqual([1, 7]) + }) + }) + }) + + describe('when the snippet prefix is indented', () => { + describe('when the snippet spans a single line', () => { + it('does not indent the next line', () => { + editor.setCursorScreenPosition([2, Infinity]) + editor.insertText(' t1') + atom.commands.dispatch(editorElement, 'snippets:expand') + expect(editor.lineTextForBufferRow(3)).toBe( + ' var pivot = items.shift(), current, left = [], right = [];' + ) + }) + }) + + describe('when the snippet spans multiple lines', () => { + it('indents the subsequent lines of the snippet to be even with the start of the first line', () => { + expect(editor.getSoftTabs()).toBeTruthy() + editor.setCursorScreenPosition([2, Infinity]) + editor.insertText(' t3') + atom.commands.dispatch(editorElement, 'snippets:expand') + expect(editor.lineTextForBufferRow(2)).toBe( + ' if (items.length <= 1) return items; line 1' + ) + expect(editor.lineTextForBufferRow(3)).toBe(' line 2') + expect(editor.getCursorBufferPosition()).toEqual([3, 12]) + }) + }) + }) + + describe('when the snippet spans multiple lines', () => { beforeEach(() => { - editor.update({autoIndent: true}); + editor.update({ autoIndent: true }) // editor.update() returns a Promise that never gets resolved, so we // need to return undefined to avoid a timeout in the spec. // TODO: Figure out why `editor.update({autoIndent: true})` never gets resolved. - }); - - it("places tab stops correctly", () => { - expect(editor.getSoftTabs()).toBeTruthy(); - editor.setCursorScreenPosition([2, Infinity]); - editor.insertText(' t3'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - expect(editor.getCursorBufferPosition()).toEqual([3, 12]); - atom.commands.dispatch(editorElement, 'snippets:next-tab-stop'); - expect(editor.getCursorBufferPosition()).toEqual([4, 4]); - }); - - it("indents the subsequent lines of the snippet based on the indent level before the snippet is inserted", () => { - editor.setCursorScreenPosition([2, Infinity]); - editor.insertNewline(); - editor.insertText('t4b'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - - expect(editor.lineTextForBufferRow(3)).toBe(" = line 1 {"); // 4 + 1 spaces (because the tab stop is invisible) - expect(editor.lineTextForBufferRow(4)).toBe(" line 2"); - expect(editor.lineTextForBufferRow(5)).toBe(" }"); - expect(editor.getCursorBufferPosition()).toEqual([3, 4]); - }); - - it("does not change the relative positioning of the tab stops when inserted multiple times", () => { - editor.setCursorScreenPosition([2, Infinity]); - editor.insertNewline(); - editor.insertText('t4'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - - expect(editor.getSelectedBufferRange()).toEqual([[3, 9], [3, 10]]); - atom.commands.dispatch(editorElement, 'snippets:next-tab-stop'); - expect(editor.getSelectedBufferRange()).toEqual([[4, 6], [4, 13]]); - - editor.insertText('t4'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - - expect(editor.getSelectedBufferRange()).toEqual([[4, 11], [4, 12]]); - atom.commands.dispatch(editorElement, 'snippets:next-tab-stop'); - expect(editor.getSelectedBufferRange()).toEqual([[5, 8], [5, 15]]); - - editor.setText(''); // Clear editor - editor.insertText('t4'); - atom.commands.dispatch(editorElement, 'snippets:expand'); - - expect(editor.getSelectedBufferRange()).toEqual([[0, 5], [0, 6]]); - atom.commands.dispatch(editorElement, 'snippets:next-tab-stop'); - expect(editor.getSelectedBufferRange()).toEqual([[1, 2], [1, 9]]); - }); - }); - - describe("when multiple snippets match the prefix", () => { - it("expands the snippet that is the longest match for the prefix", () => { - editor.insertText('t113'); - expect(editor.getCursorScreenPosition()).toEqual([0, 4]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("t113 var quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 6]); - - editor.undo(); - editor.undo(); - - editor.insertText("tt1"); - expect(editor.getCursorScreenPosition()).toEqual([0, 3]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("this is another testvar quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 20]); - - editor.undo(); - editor.undo(); - - editor.insertText("@t1"); - expect(editor.getCursorScreenPosition()).toEqual([0, 3]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("@this is a testvar quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 15]); - }); - }); - }); - - describe("when the word preceding the cursor ends with a snippet prefix", () => { - it("inserts a tab as normal", () => { - editor.insertText("t1t1t1"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("t1t1t1 var quicksort = function () {"); - }); - }); + }) + + it('places tab stops correctly', () => { + expect(editor.getSoftTabs()).toBeTruthy() + editor.setCursorScreenPosition([2, Infinity]) + editor.insertText(' t3') + atom.commands.dispatch(editorElement, 'snippets:expand') + expect(editor.getCursorBufferPosition()).toEqual([3, 12]) + atom.commands.dispatch(editorElement, 'snippets:next-tab-stop') + expect(editor.getCursorBufferPosition()).toEqual([4, 4]) + }) + + it('indents the subsequent lines of the snippet based on the indent level before the snippet is inserted', () => { + editor.setCursorScreenPosition([2, Infinity]) + editor.insertNewline() + editor.insertText('t4b') + atom.commands.dispatch(editorElement, 'snippets:expand') + + expect(editor.lineTextForBufferRow(3)).toBe(' = line 1 {') // 4 + 1 spaces (because the tab stop is invisible) + expect(editor.lineTextForBufferRow(4)).toBe(' line 2') + expect(editor.lineTextForBufferRow(5)).toBe(' }') + expect(editor.getCursorBufferPosition()).toEqual([3, 4]) + }) + + it('does not change the relative positioning of the tab stops when inserted multiple times', () => { + editor.setCursorScreenPosition([2, Infinity]) + editor.insertNewline() + editor.insertText('t4') + atom.commands.dispatch(editorElement, 'snippets:expand') + + expect(editor.getSelectedBufferRange()).toEqual([ + [3, 9], + [3, 10] + ]) + atom.commands.dispatch(editorElement, 'snippets:next-tab-stop') + expect(editor.getSelectedBufferRange()).toEqual([ + [4, 6], + [4, 13] + ]) + + editor.insertText('t4') + atom.commands.dispatch(editorElement, 'snippets:expand') + + expect(editor.getSelectedBufferRange()).toEqual([ + [4, 11], + [4, 12] + ]) + atom.commands.dispatch(editorElement, 'snippets:next-tab-stop') + expect(editor.getSelectedBufferRange()).toEqual([ + [5, 8], + [5, 15] + ]) + + editor.setText('') // Clear editor + editor.insertText('t4') + atom.commands.dispatch(editorElement, 'snippets:expand') + + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 5], + [0, 6] + ]) + atom.commands.dispatch(editorElement, 'snippets:next-tab-stop') + expect(editor.getSelectedBufferRange()).toEqual([ + [1, 2], + [1, 9] + ]) + }) + }) + + describe('when multiple snippets match the prefix', () => { + it('expands the snippet that is the longest match for the prefix', () => { + editor.insertText('t113') + expect(editor.getCursorScreenPosition()).toEqual([0, 4]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 't113 var quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 6]) + + editor.undo() + editor.undo() + + editor.insertText('tt1') + expect(editor.getCursorScreenPosition()).toEqual([0, 3]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 'this is another testvar quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 20]) + + editor.undo() + editor.undo() + + editor.insertText('@t1') + expect(editor.getCursorScreenPosition()).toEqual([0, 3]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + '@this is a testvar quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 15]) + }) + }) + }) + + describe('when the word preceding the cursor ends with a snippet prefix', () => { + it('inserts a tab as normal', () => { + editor.insertText('t1t1t1') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 't1t1t1 var quicksort = function () {' + ) + }) + }) describe("when the letters preceding the cursor don't match a snippet", () => { - it("inserts a tab as normal", () => { - editor.insertText("xxte"); - expect(editor.getCursorScreenPosition()).toEqual([0, 4]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("xxte var quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 6]); - }); - }); - - describe("when text is selected", () => { - it("inserts a tab as normal", () => { - editor.insertText("t1"); - editor.setSelectedBufferRange([[0, 0], [0, 2]]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe(" t1var quicksort = function () {"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 4]]); - }); - }); - - describe("when a previous snippet expansion has just been undone", () => { - describe("when the tab stops appear in the middle of the snippet", () => { + it('inserts a tab as normal', () => { + editor.insertText('xxte') + expect(editor.getCursorScreenPosition()).toEqual([0, 4]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 'xxte var quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 6]) + }) + }) + + describe('when text is selected', () => { + it('inserts a tab as normal', () => { + editor.insertText('t1') + editor.setSelectedBufferRange([ + [0, 0], + [0, 2] + ]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + ' t1var quicksort = function () {' + ) + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 0], + [0, 4] + ]) + }) + }) + + describe('when a previous snippet expansion has just been undone', () => { + describe('when the tab stops appear in the middle of the snippet', () => { it("expands the snippet based on the current prefix rather than jumping to the old snippet's tab stop", () => { - editor.insertText('t6\n'); - editor.setCursorBufferPosition([0, 2]); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("first line"); - editor.undo(); - expect(editor.lineTextForBufferRow(0)).toBe("t6"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("first line"); - }); - }); - - describe("when the tab stops appear at the beginning and then the end of snippet", () => { + editor.insertText('t6\n') + editor.setCursorBufferPosition([0, 2]) + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('first line') + editor.undo() + expect(editor.lineTextForBufferRow(0)).toBe('t6') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('first line') + }) + }) + + describe('when the tab stops appear at the beginning and then the end of snippet', () => { it("expands the snippet based on the current prefix rather than jumping to the old snippet's tab stop", () => { - editor.insertText('t6b\n'); - editor.setCursorBufferPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("expanded"); - editor.undo(); - expect(editor.lineTextForBufferRow(0)).toBe("t6b"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("expanded"); - expect(editor.getCursorBufferPosition()).toEqual([0, 0]); - }); - }); - - describe("when the tab stops appear at the end and then the beginning of snippet", () => { + editor.insertText('t6b\n') + editor.setCursorBufferPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('expanded') + editor.undo() + expect(editor.lineTextForBufferRow(0)).toBe('t6b') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('expanded') + expect(editor.getCursorBufferPosition()).toEqual([0, 0]) + }) + }) + + describe('when the tab stops appear at the end and then the beginning of snippet', () => { it("expands the snippet based on the current prefix rather than jumping to the old snippet's tab stop", () => { - editor.insertText('t6c\n'); - editor.setCursorBufferPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("expanded"); - editor.undo(); - expect(editor.lineTextForBufferRow(0)).toBe("t6c"); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("expanded"); - expect(editor.getCursorBufferPosition()).toEqual([0, 8]); - }); - }); - }); - - describe("when the prefix contains non-word characters", () => { - it("selects the non-word characters as part of the prefix", () => { - editor.insertText("@unique"); - expect(editor.getCursorScreenPosition()).toEqual([0, 7]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("@unique seevar quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 11]); - - editor.setCursorBufferPosition([10, 0]); - editor.insertText("'@unique"); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(10)).toBe("'@unique see"); - expect(editor.getCursorScreenPosition()).toEqual([10, 12]); - }); - - it("does not select the whitespace before the prefix", () => { - editor.insertText("a; @unique"); - expect(editor.getCursorScreenPosition()).toEqual([0, 10]); - - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("a; @unique seevar quicksort = function () {"); - expect(editor.getCursorScreenPosition()).toEqual([0, 14]); - }); - }); - - describe("when snippet contains tabstops with or without placeholder", () => { - it("should create two markers", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t8'); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder test"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder var quicksort = function () {"); - - expect(editor.getSelectedBufferRange()).toEqual([[0, 17], [0, 21]]); - - simulateTabKeyEvent(); - expect(editor.getSelectedBufferRange()).toEqual([[1, 20], [1, 20]]); - }); - }); - - describe("when snippet contains multi-caret tabstops with or without placeholder", () => { - it("should create two markers", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t9'); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder test"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder var quicksort = function () {"); - editor.insertText('hello'); - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder hello"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder hellovar quicksort = function () {"); - }); - - it("terminates the snippet when cursors are destroyed", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t9b'); - simulateTabKeyEvent(); - editor.getCursors()[0].destroy(); - editor.getCursorBufferPosition(); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(1)).toEqual("without placeholder "); - }); - - it("terminates the snippet expansion if a new cursor moves outside the bounds of the tab stops", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t9b'); - simulateTabKeyEvent(); - editor.insertText('test'); - - editor.getCursors()[0].destroy(); - editor.moveDown(); // this should destroy the previous expansion - editor.moveToBeginningOfLine(); + editor.insertText('t6c\n') + editor.setCursorBufferPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('expanded') + editor.undo() + expect(editor.lineTextForBufferRow(0)).toBe('t6c') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('expanded') + expect(editor.getCursorBufferPosition()).toEqual([0, 8]) + }) + }) + }) + + describe('when the prefix contains non-word characters', () => { + it('selects the non-word characters as part of the prefix', () => { + editor.insertText('@unique') + expect(editor.getCursorScreenPosition()).toEqual([0, 7]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + '@unique seevar quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 11]) + + editor.setCursorBufferPosition([10, 0]) + editor.insertText("'@unique") + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(10)).toBe("'@unique see") + expect(editor.getCursorScreenPosition()).toEqual([10, 12]) + }) + + it('does not select the whitespace before the prefix', () => { + editor.insertText('a; @unique') + expect(editor.getCursorScreenPosition()).toEqual([0, 10]) + + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 'a; @unique seevar quicksort = function () {' + ) + expect(editor.getCursorScreenPosition()).toEqual([0, 14]) + }) + }) + + describe('when snippet contains tabstops with or without placeholder', () => { + it('should create two markers', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t8') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder test') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder var quicksort = function () {' + ) + + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 17], + [0, 21] + ]) + + simulateTabKeyEvent() + expect(editor.getSelectedBufferRange()).toEqual([ + [1, 20], + [1, 20] + ]) + }) + }) + + describe('when snippet contains multi-caret tabstops with or without placeholder', () => { + it('should create two markers', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t9') + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder test') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder var quicksort = function () {' + ) + editor.insertText('hello') + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder hello') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder hellovar quicksort = function () {' + ) + }) + + it('terminates the snippet when cursors are destroyed', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t9b') + simulateTabKeyEvent() + editor.getCursors()[0].destroy() + editor.getCursorBufferPosition() + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(1)).toEqual('without placeholder ') + }) + + it('terminates the snippet expansion if a new cursor moves outside the bounds of the tab stops', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t9b') + simulateTabKeyEvent() + editor.insertText('test') + + editor.getCursors()[0].destroy() + editor.moveDown() // this should destroy the previous expansion + editor.moveToBeginningOfLine() // this should insert whitespace instead of going through tabstops of the previous destroyed snippet - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(2).indexOf(" second")).toBe(0); - }); + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(2).indexOf(' second')).toBe(0) + }) - it("moves to the second tabstop after a multi-caret tabstop", () => { - editor.setCursorScreenPosition([0, 0]); - editor.insertText('t9b'); - simulateTabKeyEvent(); - editor.insertText('line 1'); + it('moves to the second tabstop after a multi-caret tabstop', () => { + editor.setCursorScreenPosition([0, 0]) + editor.insertText('t9b') + simulateTabKeyEvent() + editor.insertText('line 1') - simulateTabKeyEvent(); - editor.insertText('line 2'); + simulateTabKeyEvent() + editor.insertText('line 2') - simulateTabKeyEvent(); - editor.insertText('line 3'); + simulateTabKeyEvent() + editor.insertText('line 3') - expect(editor.lineTextForBufferRow(2).indexOf("line 2 ")).toBe(-1); - }); + expect(editor.lineTextForBufferRow(2).indexOf('line 2 ')).toBe(-1) + }) it("mirrors input properly when a tabstop's placeholder refers to another tabstop", () => { - editor.setText('t17'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - editor.insertText("foo"); - expect(editor.getText()).toBe("console.log('uh foo', foo);"); - simulateTabKeyEvent(); - editor.insertText("bar"); - expect(editor.getText()).toBe("console.log('bar', foo);"); - }); - }); - - describe("when the snippet contains tab stops with transformations", () => { - it("transforms the text typed into the first tab stop before setting it in the transformed tab stop", () => { - editor.setText('t12'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.getText()).toBe("[b][/b]"); - editor.insertText('img src'); - expect(editor.getText()).toBe("[img src][/img]"); - }); - - it("bundles the transform mutations along with the original manual mutation for the purposes of undo and redo", () => { - editor.setText('t12'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - editor.insertText('i'); - expect(editor.getText()).toBe("[i][/i]"); - - editor.insertText('mg src'); - expect(editor.getText()).toBe("[img src][/img]"); - - editor.undo(); - expect(editor.getText()).toBe("[i][/i]"); - - editor.redo(); - expect(editor.getText()).toBe("[img src][/img]"); - }); - - it("can pick the right insertion to use as the primary even if a transformed insertion occurs first in the snippet", () => { - editor.setText('t16'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("& Q & q"); - expect(editor.getCursorBufferPosition()).toEqual([0, 7]); - - editor.insertText('rst'); - expect(editor.lineTextForBufferRow(0)).toBe("& RST & rst"); - }); - - it("silently ignores a tab stop without a non-transformed insertion to use as the primary", () => { - editor.setText('t15'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - editor.insertText('a'); - expect(editor.lineTextForBufferRow(0)).toBe(" & a"); - expect(editor.getCursorBufferPosition()).toEqual([0, 4]); - }); - }); - - describe("when the snippet contains mirrored tab stops and tab stops with transformations", () => { - it("adds cursors for the mirrors but not the transformations", () => { - editor.setText('t13'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.getCursors().length).toBe(2); + editor.setText('t17') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + editor.insertText('foo') + expect(editor.getText()).toBe("console.log('uh foo', foo);") + simulateTabKeyEvent() + editor.insertText('bar') + expect(editor.getText()).toBe("console.log('bar', foo);") + }) + }) + + describe('when the snippet contains tab stops with transformations', () => { + it('transforms the text typed into the first tab stop before setting it in the transformed tab stop', () => { + editor.setText('t12') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.getText()).toBe('[b][/b]') + editor.insertText('img src') + expect(editor.getText()).toBe('[img src][/img]') + }) + + it('bundles the transform mutations along with the original manual mutation for the purposes of undo and redo', () => { + editor.setText('t12') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + editor.insertText('i') + expect(editor.getText()).toBe('[i][/i]') + + editor.insertText('mg src') + expect(editor.getText()).toBe('[img src][/img]') + + editor.undo() + expect(editor.getText()).toBe('[i][/i]') + + editor.redo() + expect(editor.getText()).toBe('[img src][/img]') + }) + + it('can pick the right insertion to use as the primary even if a transformed insertion occurs first in the snippet', () => { + editor.setText('t16') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe('& Q & q') + expect(editor.getCursorBufferPosition()).toEqual([0, 7]) + + editor.insertText('rst') + expect(editor.lineTextForBufferRow(0)).toBe('& RST & rst') + }) + + it('silently ignores a tab stop without a non-transformed insertion to use as the primary', () => { + editor.setText('t15') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + editor.insertText('a') + expect(editor.lineTextForBufferRow(0)).toBe(' & a') + expect(editor.getCursorBufferPosition()).toEqual([0, 4]) + }) + }) + + describe('when the snippet contains mirrored tab stops and tab stops with transformations', () => { + it('adds cursors for the mirrors but not the transformations', () => { + editor.setText('t13') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.getCursors().length).toBe(2) expect(editor.getText()).toBe(`\ placeholder PLACEHOLDER \ -` - ); +`) - editor.insertText('foo'); + editor.insertText('foo') expect(editor.getText()).toBe(`\ foo FOO foo\ -` - ); - }); - }); - - describe("when the snippet contains multiple tab stops, some with transformations and some without", () => { - it("does not get confused", () => { - editor.setText('t14'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.getCursors().length).toBe(2); - expect(editor.getText()).toBe("placeholder PLACEHOLDER ANOTHER another "); - simulateTabKeyEvent(); - expect(editor.getCursors().length).toBe(2); - editor.insertText('FOO'); - expect(editor.getText()).toBe("placeholder PLACEHOLDER FOO foo FOO"); - }); - }); - - describe("when the snippet has a transformed tab stop such that it is possible to move the cursor between the ordinary tab stop and its transformed version without an intermediate step", () => { - it("terminates the snippet upon such a cursor move", () => { - editor.setText('t18'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.getText()).toBe("// \n// "); - expect(editor.getCursorBufferPosition()).toEqual([0, 3]); - editor.insertText('wat'); - expect(editor.getText()).toBe("// wat\n// ==="); +`) + }) + }) + + describe('when the snippet contains multiple tab stops, some with transformations and some without', () => { + it('does not get confused', () => { + editor.setText('t14') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.getCursors().length).toBe(2) + expect(editor.getText()).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + simulateTabKeyEvent() + expect(editor.getCursors().length).toBe(2) + editor.insertText('FOO') + expect(editor.getText()).toBe('placeholder PLACEHOLDER FOO foo FOO') + }) + }) + + describe('when the snippet has a transformed tab stop such that it is possible to move the cursor between the ordinary tab stop and its transformed version without an intermediate step', () => { + it('terminates the snippet upon such a cursor move', () => { + editor.setText('t18') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.getText()).toBe('// \n// ') + expect(editor.getCursorBufferPosition()).toEqual([0, 3]) + editor.insertText('wat') + expect(editor.getText()).toBe('// wat\n// ===') // Move the cursor down one line, then up one line. This puts the cursor // back in its previous position, but the snippet should no longer be // active, so when we type more text, it should not be mirrored. - editor.setCursorScreenPosition([1, 6]); - editor.setCursorScreenPosition([0, 6]); - editor.insertText('wat'); - expect(editor.getText()).toBe("// watwat\n// ==="); - }); - }); - - describe("when the snippet contains tab stops with an index >= 10", () => { - it("parses and orders the indices correctly", () => { - editor.setText('t10'); - editor.setCursorScreenPosition([0, 3]); - simulateTabKeyEvent(); - expect(editor.getText()).toBe("hello large indices"); - expect(editor.getCursorBufferPosition()).toEqual([0, 19]); - simulateTabKeyEvent(); - expect(editor.getCursorBufferPosition()).toEqual([0, 5]); - simulateTabKeyEvent(); - expect(editor.getSelectedBufferRange()).toEqual([[0, 6], [0, 11]]); - }); - }); - - describe("when there are multiple cursors", () => { - describe("when the cursors share a common snippet prefix", () => { - it("expands the snippet for all cursors and allows simultaneous editing", () => { - editor.insertText('t9'); - editor.setCursorBufferPosition([12, 2]); - editor.insertText(' t9'); - editor.addCursorAtBufferPosition([0, 2]); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder test"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder var quicksort = function () {"); - expect(editor.lineTextForBufferRow(13)).toBe("}; with placeholder test"); - expect(editor.lineTextForBufferRow(14)).toBe("without placeholder "); - - editor.insertText('hello'); - expect(editor.lineTextForBufferRow(0)).toBe("with placeholder hello"); - expect(editor.lineTextForBufferRow(1)).toBe("without placeholder hellovar quicksort = function () {"); - expect(editor.lineTextForBufferRow(13)).toBe("}; with placeholder hello"); - expect(editor.lineTextForBufferRow(14)).toBe("without placeholder hello"); - }); - - it("applies transformations identically to single-expansion mode", () => { - editor.setText('t14\nt14'); - editor.setCursorBufferPosition([1, 3]); - editor.addCursorAtBufferPosition([0, 3]); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(0)).toBe("placeholder PLACEHOLDER ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("placeholder PLACEHOLDER ANOTHER another "); - - editor.insertText("testing"); - - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing ANOTHER another "); - - simulateTabKeyEvent(); - editor.insertText("AGAIN"); - - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing AGAIN again AGAIN"); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing AGAIN again AGAIN"); - }); - - it("bundles transform-induced mutations into a single history entry along with their triggering edit, even across multiple snippets", () => { - editor.setText('t14\nt14'); - editor.setCursorBufferPosition([1, 3]); - editor.addCursorAtBufferPosition([0, 3]); - simulateTabKeyEvent(); - - expect(editor.lineTextForBufferRow(0)).toBe("placeholder PLACEHOLDER ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("placeholder PLACEHOLDER ANOTHER another "); - - editor.insertText("testing"); - - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing ANOTHER another "); - - simulateTabKeyEvent(); - editor.insertText("AGAIN"); - - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing AGAIN again AGAIN"); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing AGAIN again AGAIN"); - - editor.undo(); - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing ANOTHER another "); - - editor.undo(); - expect(editor.lineTextForBufferRow(0)).toBe("placeholder PLACEHOLDER ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("placeholder PLACEHOLDER ANOTHER another "); - - editor.redo(); - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing ANOTHER another "); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing ANOTHER another "); - - editor.redo(); - expect(editor.lineTextForBufferRow(0)).toBe("testing TESTING testing AGAIN again AGAIN"); - expect(editor.lineTextForBufferRow(1)).toBe("testing TESTING testing AGAIN again AGAIN"); - }); - - describe("when there are many tabstops", () => { - it("moves the cursors between the tab stops for their corresponding snippet when tab and shift-tab are pressed", () => { - editor.addCursorAtBufferPosition([7, 5]); - editor.addCursorAtBufferPosition([12, 2]); - editor.insertText('t11'); - simulateTabKeyEvent(); - - const cursors = editor.getCursors(); - expect(cursors.length).toEqual(3); - - expect(cursors[0].getBufferPosition()).toEqual([0, 3]); - expect(cursors[1].getBufferPosition()).toEqual([7, 8]); - expect(cursors[2].getBufferPosition()).toEqual([12, 5]); - expect(cursors[0].selection.isEmpty()).toBe(true); - expect(cursors[1].selection.isEmpty()).toBe(true); - expect(cursors[2].selection.isEmpty()).toBe(true); - - simulateTabKeyEvent(); - expect(cursors[0].getBufferPosition()).toEqual([0, 7]); - expect(cursors[1].getBufferPosition()).toEqual([7, 12]); - expect(cursors[2].getBufferPosition()).toEqual([12, 9]); - expect(cursors[0].selection.isEmpty()).toBe(false); - expect(cursors[1].selection.isEmpty()).toBe(false); - expect(cursors[2].selection.isEmpty()).toBe(false); - expect(cursors[0].selection.getText()).toEqual('two'); - expect(cursors[1].selection.getText()).toEqual('two'); - expect(cursors[2].selection.getText()).toEqual('two'); - - simulateTabKeyEvent(); - expect(cursors[0].getBufferPosition()).toEqual([0, 13]); - expect(cursors[1].getBufferPosition()).toEqual([7, 18]); - expect(cursors[2].getBufferPosition()).toEqual([12, 15]); - expect(cursors[0].selection.isEmpty()).toBe(true); - expect(cursors[1].selection.isEmpty()).toBe(true); - expect(cursors[2].selection.isEmpty()).toBe(true); - - simulateTabKeyEvent(); - expect(cursors[0].getBufferPosition()).toEqual([0, 0]); - expect(cursors[1].getBufferPosition()).toEqual([7, 5]); - expect(cursors[2].getBufferPosition()).toEqual([12, 2]); - expect(cursors[0].selection.isEmpty()).toBe(true); - expect(cursors[1].selection.isEmpty()).toBe(true); - expect(cursors[2].selection.isEmpty()).toBe(true); - }); - }); - }); - - describe("when the cursors do not share common snippet prefixes", () => { - it("inserts tabs as normal", () => { - editor.insertText('t9'); - editor.setCursorBufferPosition([12, 2]); - editor.insertText(' t8'); - editor.addCursorAtBufferPosition([0, 2]); - simulateTabKeyEvent(); - expect(editor.lineTextForBufferRow(0)).toBe("t9 var quicksort = function () {"); - expect(editor.lineTextForBufferRow(12)).toBe("}; t8 "); - }); - }); - - describe("when a snippet is triggered within an existing snippet expansion", () => { - it("ignores the snippet expansion and goes to the next tab stop", () => { - editor.addCursorAtBufferPosition([7, 5]); - editor.addCursorAtBufferPosition([12, 2]); - editor.insertText('t11'); - simulateTabKeyEvent(); - simulateTabKeyEvent(); - - editor.insertText('t1'); - simulateTabKeyEvent(); - - const cursors = editor.getCursors(); - expect(cursors.length).toEqual(3); - - expect(cursors[0].getBufferPosition()).toEqual([0, 12]); - expect(cursors[1].getBufferPosition()).toEqual([7, 17]); - expect(cursors[2].getBufferPosition()).toEqual([12, 14]); - expect(cursors[0].selection.isEmpty()).toBe(true); - expect(cursors[1].selection.isEmpty()).toBe(true); - expect(cursors[2].selection.isEmpty()).toBe(true); - expect(editor.lineTextForBufferRow(0)).toBe("one t1 threevar quicksort = function () {"); - expect(editor.lineTextForBufferRow(7)).toBe(" }one t1 three"); - expect(editor.lineTextForBufferRow(12)).toBe("};one t1 three"); - }); - }); - }); - - describe("when the editor is not a pane item (regression)", () => { - it("handles tab stops correctly", () => { - editor = new TextEditor(); - atom.grammars.assignLanguageMode(editor, 'source.js'); - editorElement = editor.getElement(); - - editor.insertText('t2'); - simulateTabKeyEvent(); - editor.insertText('ABC'); - expect(editor.getText()).toContain('go here first:(ABC)'); - - editor.undo(); - editor.undo(); - expect(editor.getText()).toBe('t2'); - simulateTabKeyEvent(); - editor.insertText('ABC'); - expect(editor.getText()).toContain('go here first:(ABC)'); - }); - }); - }); - - describe("when atom://.atom/snippets is opened", () => { - it("opens ~/.atom/snippets.cson", () => { - jasmine.unspy(Snippets, 'getUserSnippetsPath'); - atom.workspace.destroyActivePaneItem(); - const configDirPath = temp.mkdirSync('atom-config-dir-'); - spyOn(atom, 'getConfigDirPath').andReturn(configDirPath); - atom.workspace.open('atom://.atom/snippets'); - - waitsFor(() => atom.workspace.getActiveTextEditor() != null); + editor.setCursorScreenPosition([1, 6]) + editor.setCursorScreenPosition([0, 6]) + editor.insertText('wat') + expect(editor.getText()).toBe('// watwat\n// ===') + }) + }) + + describe('when the snippet contains tab stops with an index >= 10', () => { + it('parses and orders the indices correctly', () => { + editor.setText('t10') + editor.setCursorScreenPosition([0, 3]) + simulateTabKeyEvent() + expect(editor.getText()).toBe('hello large indices') + expect(editor.getCursorBufferPosition()).toEqual([0, 19]) + simulateTabKeyEvent() + expect(editor.getCursorBufferPosition()).toEqual([0, 5]) + simulateTabKeyEvent() + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 6], + [0, 11] + ]) + }) + }) + + describe('when there are multiple cursors', () => { + describe('when the cursors share a common snippet prefix', () => { + it('expands the snippet for all cursors and allows simultaneous editing', () => { + editor.insertText('t9') + editor.setCursorBufferPosition([12, 2]) + editor.insertText(' t9') + editor.addCursorAtBufferPosition([0, 2]) + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder test') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder var quicksort = function () {' + ) + expect(editor.lineTextForBufferRow(13)).toBe( + '}; with placeholder test' + ) + expect(editor.lineTextForBufferRow(14)).toBe('without placeholder ') + + editor.insertText('hello') + expect(editor.lineTextForBufferRow(0)).toBe('with placeholder hello') + expect(editor.lineTextForBufferRow(1)).toBe( + 'without placeholder hellovar quicksort = function () {' + ) + expect(editor.lineTextForBufferRow(13)).toBe( + '}; with placeholder hello' + ) + expect(editor.lineTextForBufferRow(14)).toBe( + 'without placeholder hello' + ) + }) + + it('applies transformations identically to single-expansion mode', () => { + editor.setText('t14\nt14') + editor.setCursorBufferPosition([1, 3]) + editor.addCursorAtBufferPosition([0, 3]) + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(0)).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + + editor.insertText('testing') + + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + + simulateTabKeyEvent() + editor.insertText('AGAIN') + + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing AGAIN again AGAIN' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing AGAIN again AGAIN' + ) + }) + + it('bundles transform-induced mutations into a single history entry along with their triggering edit, even across multiple snippets', () => { + editor.setText('t14\nt14') + editor.setCursorBufferPosition([1, 3]) + editor.addCursorAtBufferPosition([0, 3]) + simulateTabKeyEvent() + + expect(editor.lineTextForBufferRow(0)).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + + editor.insertText('testing') + + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + + simulateTabKeyEvent() + editor.insertText('AGAIN') + + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing AGAIN again AGAIN' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing AGAIN again AGAIN' + ) + + editor.undo() + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + + editor.undo() + expect(editor.lineTextForBufferRow(0)).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'placeholder PLACEHOLDER ANOTHER another ' + ) + + editor.redo() + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing ANOTHER another ' + ) + + editor.redo() + expect(editor.lineTextForBufferRow(0)).toBe( + 'testing TESTING testing AGAIN again AGAIN' + ) + expect(editor.lineTextForBufferRow(1)).toBe( + 'testing TESTING testing AGAIN again AGAIN' + ) + }) + + describe('when there are many tabstops', () => { + it('moves the cursors between the tab stops for their corresponding snippet when tab and shift-tab are pressed', () => { + editor.addCursorAtBufferPosition([7, 5]) + editor.addCursorAtBufferPosition([12, 2]) + editor.insertText('t11') + simulateTabKeyEvent() + + const cursors = editor.getCursors() + expect(cursors.length).toEqual(3) + + expect(cursors[0].getBufferPosition()).toEqual([0, 3]) + expect(cursors[1].getBufferPosition()).toEqual([7, 8]) + expect(cursors[2].getBufferPosition()).toEqual([12, 5]) + expect(cursors[0].selection.isEmpty()).toBe(true) + expect(cursors[1].selection.isEmpty()).toBe(true) + expect(cursors[2].selection.isEmpty()).toBe(true) + + simulateTabKeyEvent() + expect(cursors[0].getBufferPosition()).toEqual([0, 7]) + expect(cursors[1].getBufferPosition()).toEqual([7, 12]) + expect(cursors[2].getBufferPosition()).toEqual([12, 9]) + expect(cursors[0].selection.isEmpty()).toBe(false) + expect(cursors[1].selection.isEmpty()).toBe(false) + expect(cursors[2].selection.isEmpty()).toBe(false) + expect(cursors[0].selection.getText()).toEqual('two') + expect(cursors[1].selection.getText()).toEqual('two') + expect(cursors[2].selection.getText()).toEqual('two') + + simulateTabKeyEvent() + expect(cursors[0].getBufferPosition()).toEqual([0, 13]) + expect(cursors[1].getBufferPosition()).toEqual([7, 18]) + expect(cursors[2].getBufferPosition()).toEqual([12, 15]) + expect(cursors[0].selection.isEmpty()).toBe(true) + expect(cursors[1].selection.isEmpty()).toBe(true) + expect(cursors[2].selection.isEmpty()).toBe(true) + + simulateTabKeyEvent() + expect(cursors[0].getBufferPosition()).toEqual([0, 0]) + expect(cursors[1].getBufferPosition()).toEqual([7, 5]) + expect(cursors[2].getBufferPosition()).toEqual([12, 2]) + expect(cursors[0].selection.isEmpty()).toBe(true) + expect(cursors[1].selection.isEmpty()).toBe(true) + expect(cursors[2].selection.isEmpty()).toBe(true) + }) + }) + }) + + describe('when the cursors do not share common snippet prefixes', () => { + it('inserts tabs as normal', () => { + editor.insertText('t9') + editor.setCursorBufferPosition([12, 2]) + editor.insertText(' t8') + editor.addCursorAtBufferPosition([0, 2]) + simulateTabKeyEvent() + expect(editor.lineTextForBufferRow(0)).toBe( + 't9 var quicksort = function () {' + ) + expect(editor.lineTextForBufferRow(12)).toBe('}; t8 ') + }) + }) + + describe('when a snippet is triggered within an existing snippet expansion', () => { + it('ignores the snippet expansion and goes to the next tab stop', () => { + editor.addCursorAtBufferPosition([7, 5]) + editor.addCursorAtBufferPosition([12, 2]) + editor.insertText('t11') + simulateTabKeyEvent() + simulateTabKeyEvent() + + editor.insertText('t1') + simulateTabKeyEvent() + + const cursors = editor.getCursors() + expect(cursors.length).toEqual(3) + + expect(cursors[0].getBufferPosition()).toEqual([0, 12]) + expect(cursors[1].getBufferPosition()).toEqual([7, 17]) + expect(cursors[2].getBufferPosition()).toEqual([12, 14]) + expect(cursors[0].selection.isEmpty()).toBe(true) + expect(cursors[1].selection.isEmpty()).toBe(true) + expect(cursors[2].selection.isEmpty()).toBe(true) + expect(editor.lineTextForBufferRow(0)).toBe( + 'one t1 threevar quicksort = function () {' + ) + expect(editor.lineTextForBufferRow(7)).toBe(' }one t1 three') + expect(editor.lineTextForBufferRow(12)).toBe('};one t1 three') + }) + }) + }) + + describe('when the editor is not a pane item (regression)', () => { + it('handles tab stops correctly', () => { + editor = new TextEditor() + atom.grammars.assignLanguageMode(editor, 'source.js') + editorElement = editor.getElement() + + editor.insertText('t2') + simulateTabKeyEvent() + editor.insertText('ABC') + expect(editor.getText()).toContain('go here first:(ABC)') + + editor.undo() + editor.undo() + expect(editor.getText()).toBe('t2') + simulateTabKeyEvent() + editor.insertText('ABC') + expect(editor.getText()).toContain('go here first:(ABC)') + }) + }) + }) + + describe('when atom://.atom/snippets is opened', () => { + it('opens ~/.atom/snippets.cson', () => { + jasmine.unspy(Snippets, 'getUserSnippetsPath') + atom.workspace.destroyActivePaneItem() + const configDirPath = temp.mkdirSync('atom-config-dir-') + spyOn(atom, 'getConfigDirPath').andReturn(configDirPath) + atom.workspace.open('atom://.atom/snippets') + + waitsFor(() => atom.workspace.getActiveTextEditor() != null) runs(() => { - expect(atom.workspace.getActiveTextEditor().getURI()).toBe(path.join(configDirPath, 'snippets.cson')); - }); - }); - }); - - describe("snippet insertion API", () => { - it("will automatically parse snippet definition and replace selection", () => { - editor.setSelectedBufferRange([[0, 4], [0, 13]]); - Snippets.insert("hello ${1:world}", editor); - - expect(editor.lineTextForBufferRow(0)).toBe("var hello world = function () {"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 10], [0, 15]]); - }); - }); + expect(atom.workspace.getActiveTextEditor().getURI()).toBe( + path.join(configDirPath, 'snippets.cson') + ) + }) + }) + }) + + describe('snippet insertion API', () => { + it('will automatically parse snippet definition and replace selection', () => { + editor.setSelectedBufferRange([ + [0, 4], + [0, 13] + ]) + Snippets.insert('hello ${1:world}', editor) + + expect(editor.lineTextForBufferRow(0)).toBe( + 'var hello world = function () {' + ) + expect(editor.getSelectedBufferRange()).toEqual([ + [0, 10], + [0, 15] + ]) + }) + }) describe("when the 'snippets:available' command is triggered", () => { - let availableSnippetsView = null; + let availableSnippetsView = null beforeEach(() => { Snippets.add(__filename, { - ".source.js": { - "test": { - prefix: "test", - body: "${1:Test pass you will}, young " + '.source.js': { + test: { + prefix: 'test', + body: '${1:Test pass you will}, young ' }, - "challenge": { - prefix: "chal", - body: "$1: ${2:To pass this challenge}" + challenge: { + prefix: 'chal', + body: '$1: ${2:To pass this challenge}' } } - } - ); + }) - delete Snippets.availableSnippetsView; + delete Snippets.availableSnippetsView - atom.commands.dispatch(editorElement, "snippets:available"); + atom.commands.dispatch(editorElement, 'snippets:available') - waitsFor(() => atom.workspace.getModalPanels().length === 1); + waitsFor(() => atom.workspace.getModalPanels().length === 1) runs(() => { - availableSnippetsView = atom.workspace.getModalPanels()[0].getItem(); - }); - }); - - it("renders a select list of all available snippets", () => { - expect(availableSnippetsView.selectListView.getSelectedItem().prefix).toBe('test'); - expect(availableSnippetsView.selectListView.getSelectedItem().name).toBe('test'); - expect(availableSnippetsView.selectListView.getSelectedItem().bodyText).toBe('${1:Test pass you will}, young '); - - availableSnippetsView.selectListView.selectNext(); - - expect(availableSnippetsView.selectListView.getSelectedItem().prefix).toBe('chal'); - expect(availableSnippetsView.selectListView.getSelectedItem().name).toBe('challenge'); - expect(availableSnippetsView.selectListView.getSelectedItem().bodyText).toBe('$1: ${2:To pass this challenge}'); - }); - - it("writes the selected snippet to the editor as snippet", () => { - availableSnippetsView.selectListView.confirmSelection(); - - expect(editor.getCursorScreenPosition()).toEqual([0, 18]); - expect(editor.getSelectedText()).toBe('Test pass you will'); - expect(editor.lineTextForBufferRow(0)).toBe('Test pass you will, young var quicksort = function () {'); - }); - - it("closes the dialog when triggered again", () => { - atom.commands.dispatch(availableSnippetsView.selectListView.refs.queryEditor.element, 'snippets:available'); - expect(atom.workspace.getModalPanels().length).toBe(0); - }); - }); -}); + availableSnippetsView = atom.workspace.getModalPanels()[0].getItem() + }) + }) + + it('renders a select list of all available snippets', () => { + expect( + availableSnippetsView.selectListView.getSelectedItem().prefix + ).toBe('test') + expect(availableSnippetsView.selectListView.getSelectedItem().name).toBe( + 'test' + ) + expect( + availableSnippetsView.selectListView.getSelectedItem().bodyText + ).toBe('${1:Test pass you will}, young ') + + availableSnippetsView.selectListView.selectNext() + + expect( + availableSnippetsView.selectListView.getSelectedItem().prefix + ).toBe('chal') + expect(availableSnippetsView.selectListView.getSelectedItem().name).toBe( + 'challenge' + ) + expect( + availableSnippetsView.selectListView.getSelectedItem().bodyText + ).toBe('$1: ${2:To pass this challenge}') + }) + + it('writes the selected snippet to the editor as snippet', () => { + availableSnippetsView.selectListView.confirmSelection() + + expect(editor.getCursorScreenPosition()).toEqual([0, 18]) + expect(editor.getSelectedText()).toBe('Test pass you will') + expect(editor.lineTextForBufferRow(0)).toBe( + 'Test pass you will, young var quicksort = function () {' + ) + }) + + it('closes the dialog when triggered again', () => { + atom.commands.dispatch( + availableSnippetsView.selectListView.refs.queryEditor.element, + 'snippets:available' + ) + expect(atom.workspace.getModalPanels().length).toBe(0) + }) + }) +})